diff --git a/src/components/AddSenior.tsx b/src/components/AddSenior.tsx index 0a00206a..3581cb03 100644 --- a/src/components/AddSenior.tsx +++ b/src/components/AddSenior.tsx @@ -6,8 +6,11 @@ import React, { useState, } from "react"; import Image, { StaticImageData } from "next/legacy/image"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm, SubmitHandler } from "react-hook-form"; import FilterDropdown from "@components/FilterDropdown"; import { Senior, User } from "@prisma/client"; + import ImageIcon from "../../public/icons/icon_add_photo.png"; import { patchSenior } from "src/app/api/senior/[id]/route.client"; import { postSenior } from "src/app/api/senior/route.client"; @@ -34,17 +37,14 @@ type AddSeniorTileProps = { setSeniorPatch: Dispatch>; }; -type SeniorData = Pick< - z.infer, - "firstname" | "lastname" | "location" | "description" ->; +const seniorFormSchema = seniorSchema.pick({ + firstname: true, + lastname: true, + location: true, + description: true, +}); -const EMPTY_SENIOR: SeniorData = { - firstname: "", - lastname: "", - location: "", - description: "", -}; +type SeniorData = z.infer; export const AddSeniorTile = ({ showAddSeniorPopUp, @@ -116,7 +116,6 @@ const AddSenior = ({ seniorPatch, setSeniorPatch, }: AddSeniorProps) => { - const [seniorData, setSeniorData] = useState(EMPTY_SENIOR); const [selectedStudents, setSelectedStudents] = useState([]); const [currentImage, setCurrentImage] = useState( ImageIcon @@ -124,6 +123,17 @@ const AddSenior = ({ const [confirm, setConfirm] = useState(false); const [error, setError] = useState(false); + const { + register, + handleSubmit, + reset, + setValue, + clearErrors, + formState: { errors, isValid }, + } = useForm({ + resolver: zodResolver(seniorFormSchema), + }); + const initialSenior: Senior | undefined = useMemo(() => { const senior = seniors.find((senior) => senior.id === seniorPatch); return senior; @@ -159,15 +169,32 @@ const AddSenior = ({ }); const fetching = loadingPostSenior || loadingPatchSenior; + const onSubmit: SubmitHandler = async (data, event) => { + event?.preventDefault(); + const seniorModel = { + ...data, + StudentIDs: selectedStudents.map((usr) => usr.id), + }; + if (seniorPatch) { + await throttlePatchSenior({ + seniorId: seniorPatch, + body: seniorModel, + }); + } else { + await throttlePostSenior({ body: seniorModel }); + } + }; + useEffect(() => { - if (initialSenior) - setSeniorData({ - firstname: initialSenior.firstname, - lastname: initialSenior.lastname, - location: initialSenior.location, - description: initialSenior.description, + if (initialSenior) { + setValue("firstname", initialSenior.firstname, { shouldValidate: true }); + setValue("lastname", initialSenior.lastname, { shouldValidate: true }); + setValue("location", initialSenior.location, { shouldValidate: true }); + setValue("description", initialSenior.description, { + shouldValidate: true, }); - }, [initialSenior]); + } + }, [initialSenior, setValue]); useEffect(() => { if (initialSenior) { @@ -181,10 +208,10 @@ const AddSenior = ({ const handlePopUp = () => { setShowAddSeniorPopUp(!showAddSeniorPopUp); - setSeniorData(EMPTY_SENIOR); setSelectedStudents([]); setCurrentImage(ImageIcon); setSeniorPatch(""); // empty string used as falsey value to indicate update or patch + reset(); }; const handleConfirm = () => { @@ -216,7 +243,7 @@ const AddSenior = ({ {showAddSeniorPopUp && ( {!confirm && !error ? ( -
+
{seniorPatch ? "Update" : "Add New"} Senior
@@ -230,25 +257,27 @@ const AddSenior = ({ />
- - {/* Todo: First and Last name values are stored into the seniorData.name field. Seperate into two fields - later as seniorData.name propgates to backend*/}
First name
) => - setSeniorData({ - ...seniorData, - firstname: e.target.value, - }) - } + {...register("firstname", { + onChange: () => clearErrors("firstname"), + })} + autoComplete="off" /> + {errors?.firstname && ( +
+ {errors.firstname.message} +
+ )}
@@ -258,45 +287,31 @@ const AddSenior = ({ ) => - setSeniorData((seniorData) => ({ - ...seniorData, - lastname: e.target.value, - })) - } + {...register("lastname")} + autoComplete="off" />
- {" "} - Location{" "} + Location
) => - setSeniorData({ ...seniorData, location: e.target.value }) - } + {...register("location")} + autoComplete="off" />
- {" "} - Description{" "} + Description