diff --git a/apps/web/src/app/admin/events/edit/[slug]/page.tsx b/apps/web/src/app/admin/events/edit/[slug]/page.tsx new file mode 100644 index 00000000..72cf3053 --- /dev/null +++ b/apps/web/src/app/admin/events/edit/[slug]/page.tsx @@ -0,0 +1,34 @@ +import { getEventById } from "db/functions"; +import { redirect } from "next/navigation"; +import EditEventForm from "@/components/events/admin/EditEventForm"; + +export default async function EditEventPage({ + params, +}: { + params: { slug: string }; +}) { + const eventId = parseInt(params.slug); + + if (!eventId) { + return

Error: invalid event id

; + } + + const event = await getEventById(eventId); + + if (!event) { + return redirect("/admin/events"); + } + + return ( +
+
+

+ Edit Event +

+
+
+ +
+
+ ); +} diff --git a/apps/web/src/components/events/admin/EditEventForm.tsx b/apps/web/src/components/events/admin/EditEventForm.tsx new file mode 100644 index 00000000..021ec4b9 --- /dev/null +++ b/apps/web/src/components/events/admin/EditEventForm.tsx @@ -0,0 +1,306 @@ +"use client"; + +import { useForm } from "react-hook-form"; +import { + Form, + FormField, + FormItem, + FormLabel, + FormControl, + FormDescription, + FormMessage, +} from "@/components/shadcn/ui/form"; +import { + Select, + SelectTrigger, + SelectContent, + SelectGroup, + SelectItem, + SelectValue, +} from "@/components/shadcn/ui/select"; +import { Input } from "@/components/shadcn/ui/input"; +import { Button } from "@/components/shadcn/ui/button"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { Textarea } from "@/components/shadcn/ui/textarea"; +import c from "config"; +import { DateTimePicker } from "@/components/shadcn/ui/date-time-picker/date-time-picker"; +import { parseAbsolute, getLocalTimeZone } from "@internationalized/date"; +import { useCallback, useState } from "react"; +import { useRouter } from "next/navigation"; +import { ONE_HOUR_IN_MILLISECONDS } from "@/lib/constants"; +import { type eventEditType } from "@/lib/types/events"; +import { newEventFormSchema } from "@/validators/event"; +import { ThreeCircles } from "react-loader-spinner"; +import { useAction } from "next-safe-action/hooks"; +import { editEvent } from "@/actions/admin/event-actions"; +import { toast } from "sonner"; + +export default function EditEventForm({ + id, + title, + description, + type, + host, + endTime, + points, + startTime, + location, +}: eventEditType & { id: number }) { + const [loading, setLoading] = useState(false); + const router = useRouter(); + const userLocalTimeZone = getLocalTimeZone(); + const { execute } = useAction(editEvent, { + onExecute: () => setLoading(true), + onSettled: () => setLoading(false), + onSuccess: () => { + alert("Event Edited Successfully! Redirecting to event page..."); + router.push("/admin/events"); + }, + onError: ({ error }) => { + const description = + error.serverError || + "An error occurred while validating the form data"; + + toast.error("Unable to edit event", { description }); + }, + }); + + const form = useForm>({ + resolver: zodResolver(newEventFormSchema), + defaultValues: { + id, + title, + description, + type: type as any, + host, + startTime, + points, + location, + endTime, + }, + }); + + const onSubmit = useCallback( + (values: z.infer) => { + if (form.formState.isDirty) { + execute(values); + } else { + toast.error("Failed to edit event", { + description: + "Please make changes to the form before submitting it!", + }); + } + }, + [form.formState.isDirty], + ); + + return ( +
+ + ( + + Title + + + + + Keep title short and concise + + + + )} + /> + + ( + + Description + +