Skip to content

Commit

Permalink
[UPDATE] - Forms
Browse files Browse the repository at this point in the history
  • Loading branch information
nulzo committed Nov 30, 2023
1 parent d648561 commit 88a4811
Show file tree
Hide file tree
Showing 6 changed files with 1,250 additions and 0 deletions.
316 changes: 316 additions & 0 deletions frontend/src/forms/AnnouncementForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
import { CalendarIcon } from "@radix-ui/react-icons";
import { cn } from "@/lib/utils";
import { Calendar } from "@/components/ui/calendar";
import {
Popover,
PopoverTrigger,
PopoverContent,
} from "@/components/ui/popover";
import { Textarea } from "@/components/ui/textarea";
import { format } from "date-fns";
import { Button } from "@/components/ui/button";
import { Switch } from "@/components/ui/switch";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Input } from "@/components/ui/input";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { toast } from "@/components/ui/use-toast";

const max_announcement_length = 255;

const FormSchema = z.object({
title: z
.string({
required_error: "enter a title for the announcement.",
})
.min(4, {
message: "title must be more than 4 characters.",
})
.max(30, {
message: "title must not be more than 30 characters.",
}),
body: z
.string({
required_error: "enter a body for the announcement.",
})
.min(4, {
message: "body must be more than 4 characters.",
})
.max(max_announcement_length, {
message: `body must not be more than ${max_announcement_length} characters.`,
}),
variant: z.string({
required_error: "enter a variant for the announcement.",
}),
start_date: z.date({
required_error: "enter a start date for the announcement.",
}),
end_date: z.date({
required_error: "enter an end date for the announcement.",
}),
show_date: z
.boolean({
invalid_type_error: "erm... you really broke something...",
})
.default(false),
});

function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
),
});
}

export default function AnnouncementForm() {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
});
const max_length = 255;
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel className="text-foreground">
Announcement title
</FormLabel>
<FormControl>
<Input
className="text-foreground"
placeholder="enter title here..."
{...field}
/>
</FormControl>
<FormDescription></FormDescription>
<FormMessage className="text-warning" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="body"
render={({ field }) => (
<FormItem>
<FormLabel className="text-foreground">
Announcement body
</FormLabel>
<FormControl>
<div className="relative">
{field.value && field.value.length > max_length && (
<p className="absolute top-0 right-0 text-warning font-bold text-xs pr-2 pt-1">
{(field.value && max_length - field.value.length) ||
max_length}
</p>
)}
{field.value && field.value.length <= max_length && (
<p className="absolute top-0 right-0 text-muted-foreground/50 text-xs pr-2 pt-1">
{max_length - field.value.length}
</p>
)}
{!field.value && (
<p className="absolute top-0 right-0 text-muted-foreground/50 text-xs pr-2 pt-1">
{max_length}
</p>
)}
<Textarea
className="text-foreground resize-none min-h-[15vh]"
placeholder="enter body here..."
{...field}
/>
</div>
</FormControl>
<FormMessage className="text-warning" />
</FormItem>
)}
/>
<FormField
control={form.control}
name="variant"
render={({ field }) => (
<FormItem className="">
<div className="space-y-0.5 flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className=" text-foreground">
Announcement type
</FormLabel>
<FormDescription className="text-muted-foreground">
Select the variant of announcement that is displayed.
</FormDescription>
</div>
<div>
<Select onValueChange={field.onChange}>
<FormControl>
<SelectTrigger className="text-foreground w-[240px]">
<SelectValue>
{field.value || (
<span className="text-muted-foreground">
select an announcement type
</span>
)}
</SelectValue>
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="general">General</SelectItem>
<SelectItem value="info">Informative</SelectItem>
<SelectItem value="alert">Alert</SelectItem>
<SelectItem value="warning">Warning</SelectItem>
<SelectItem value="tutor">Tutors Only</SelectItem>
</SelectContent>
</Select>
<FormMessage className="text-warning mt-1" />
</div>
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="start_date"
render={({ field }) => (
<FormItem className="">
<div className="space-y-0.5 flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className=" text-foreground">Start date</FormLabel>
<FormDescription className="text-muted-foreground">
Select the start date of the announcement.
</FormDescription>
</div>
<div>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal text-foreground",
!field.value && "text-muted-foreground",
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>select start date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage className="text-warning mt-1" />
</div>
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="end_date"
render={({ field }) => (
<FormItem className="">
<div className="space-y-0.5 flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className=" text-foreground">Start date</FormLabel>
<FormDescription className="text-muted-foreground">
Select the start date of the announcement.
</FormDescription>
</div>
<div>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal text-foreground",
!field.value && "text-muted-foreground",
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>select end date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage className="text-warning" />
</div>
</div>
</FormItem>
)}
/>
<FormField
control={form.control}
name="show_date"
render={({ field }) => (
<FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<FormLabel className=" text-foreground">Show date</FormLabel>
<FormDescription className="text-muted-foreground">
Show the start and end dates in the announcement.
</FormDescription>
</div>

<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<Button type="submit">Schedule</Button>
</form>
</Form>
);
}
48 changes: 48 additions & 0 deletions frontend/src/forms/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// import { LoaderIcon } from "lucide-react";
// import { Button } from "@/components/ui/button";
// import {
// MsalAuthenticationTemplate,
// useIsAuthenticated,
// } from "@azure/msal-react";
// import { useMsal } from "@azure/msal-react";
// import { loginRequest } from "../authConfig";
// import MicrosoftIcon from "@/components/assets/MicrosoftIcon";
// import { InteractionType } from "@azure/msal-browser";
//
// function Loading() {
// return <LoaderIcon />;
// }
//
// export default function LoginForm() {
// const { instance, inProgress } = useMsal();
//
// function onSubmit(loginType: string) {
// // if (loginType === "popup") {
// // instance.loginPopup(loginRequest).catch(e) => {
// // console.log(e);
// // }
// // }
// <MsalAuthenticationTemplate
// interactionType={InteractionType.Popup}
// authenticationRequest={loginRequest}
// loadingComponent={Loading}
// >
// <p>erm</p>
// </MsalAuthenticationTemplate>;
// }
//
// return (
// <form onSubmit={onSubmit}>
// <div className="grid gap-2">
// <Button disabled={inProgress != "login"} className="space-y-4">
// {inProgress != "login" ? (
// <LoaderIcon className="mr-2 h-4 w-4 animate-spin" />
// ) : (
// <MicrosoftIcon />
// )}{" "}
// Microsoft Sign On
// </Button>
// </div>
// </form>
// );
// }
Loading

0 comments on commit 88a4811

Please sign in to comment.