-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
1,250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
// ); | ||
// } |
Oops, something went wrong.