From 625d38d8df758f4308be4fb26d200e87384c66c8 Mon Sep 17 00:00:00 2001 From: Ethan Bickel Date: Tue, 5 Nov 2024 17:11:45 -0600 Subject: [PATCH] add editing club listed officers and display them --- .../edit/officers/EditListedOfficerForm.tsx | 217 ++++++++++++++++++ .../edit/officers/EditOfficerForm.tsx | 38 +-- .../manage/[clubId]/edit/officers/page.tsx | 9 +- .../club/listing/ClubInfoSegment.tsx | 14 +- src/server/api/routers/club.ts | 32 +-- src/server/api/routers/clubEdit.ts | 64 +++++- src/server/db/index.ts | 2 + src/utils/formSchemas.ts | 9 + 8 files changed, 316 insertions(+), 69 deletions(-) create mode 100644 src/app/manage/[clubId]/edit/officers/EditListedOfficerForm.tsx diff --git a/src/app/manage/[clubId]/edit/officers/EditListedOfficerForm.tsx b/src/app/manage/[clubId]/edit/officers/EditListedOfficerForm.tsx new file mode 100644 index 00000000..3f8e99cd --- /dev/null +++ b/src/app/manage/[clubId]/edit/officers/EditListedOfficerForm.tsx @@ -0,0 +1,217 @@ +/* eslint-disable @typescript-eslint/no-misused-promises */ +'use client'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { api } from '@src/trpc/react'; +import { editListedOfficerSchema } from '@src/utils/formSchemas'; +import { useRouter } from 'next/navigation'; +import { useReducer } from 'react'; +import { + type FieldErrors, + type UseFormRegister, + useFieldArray, + useForm, +} from 'react-hook-form'; +import { type z } from 'zod'; + +type x = { + id?: boolean; + name?: boolean; + position?: boolean; +}[]; +const modifiedFields = ( + dirtyFields: x, + data: z.infer, + officers: { + id?: string; + name: string; + position: string; + }[], +) => { + const modded = data.officers.filter( + (value, index) => + !!officers.find((off) => off.id === value.id) && + dirtyFields[index]?.position, + ); + const created = data.officers.filter( + (value) => typeof value.id === 'undefined', + ); + return { + modified: modded as { id: string; name: string; position: string }[], + created: created as { name: string; position: string }[], + }; +}; + +type modifyDeletedAction = + | { + type: 'add'; + target: string; + } + | { type: 'reset' }; +const deletedReducer = (state: Array, action: modifyDeletedAction) => { + switch (action.type) { + case 'add': + return [...state, action.target]; + case 'reset': + return []; + } +}; + +type EditOfficerFormProps = { + clubId: string; + officers: { + id: string; + name: string; + position: string; + }[]; +}; +const EditOfficerForm = ({ clubId, officers }: EditOfficerFormProps) => { + const { + control, + register, + handleSubmit, + reset, + formState: { errors, dirtyFields, isDirty }, + } = useForm>({ + resolver: zodResolver(editListedOfficerSchema), + defaultValues: { officers: officers }, + }); + const { fields, append, remove } = useFieldArray({ + control, + name: 'officers', + }); + const [deleted, modifyDeleted] = useReducer(deletedReducer, []); + const removeItem = (index: number) => { + const off = officers.find((officer) => officer.id == fields[index]?.id); + if (off) modifyDeleted({ type: 'add', target: off.id }); + remove(index); + }; + const router = useRouter(); + const editOfficers = api.club.edit.listedOfficers.useMutation({ + onSuccess: () => { + router.push(`/directory/${clubId}`); + }, + }); + const submitForm = handleSubmit((data) => { + if (dirtyFields.officers !== undefined) { + const { modified, created } = modifiedFields( + dirtyFields.officers, + data, + officers, + ); + if (!editOfficers.isPending) { + editOfficers.mutate({ + clubId: clubId, + deleted: deleted, + modified: modified, + created: created, + }); + } + } + }); + return ( +
+
+
+
+ +
+
+ {errors.officers && ( +

{errors.officers.message}

+ )} +
+
+ {fields.map((field, index) => ( + + ))} +
+
+
+ + +
+
+
+ ); +}; +export default EditOfficerForm; +type OfficerItemProps = { + register: UseFormRegister>; + remove: (index: number) => void; + index: number; + errors: FieldErrors>; +}; +const OfficerItem = ({ register, index, remove, errors }: OfficerItemProps) => { + return ( +
+
+
+ + {errors.officers && errors.officers[index]?.position && ( +

+ {errors.officers[index]?.position?.message} +

+ )} +
+
+ + {errors.officers && errors.officers[index]?.position && ( +

+ {errors.officers[index]?.position?.message} +

+ )} +
+
+ +
+ ); +}; diff --git a/src/app/manage/[clubId]/edit/officers/EditOfficerForm.tsx b/src/app/manage/[clubId]/edit/officers/EditOfficerForm.tsx index f0f027d7..aacdb39b 100644 --- a/src/app/manage/[clubId]/edit/officers/EditOfficerForm.tsx +++ b/src/app/manage/[clubId]/edit/officers/EditOfficerForm.tsx @@ -6,12 +6,7 @@ import { api } from '@src/trpc/react'; import { editOfficerSchema } from '@src/utils/formSchemas'; import { useRouter } from 'next/navigation'; import { useReducer } from 'react'; -import { - type FieldErrors, - type UseFormRegister, - useFieldArray, - useForm, -} from 'react-hook-form'; +import { useFieldArray, useForm } from 'react-hook-form'; import { type z } from 'zod'; type x = { @@ -69,14 +64,12 @@ type EditOfficerFormProps = { userId: string; name: string; locked: boolean; - title: string; position: 'President' | 'Officer'; }[]; }; const EditOfficerForm = ({ clubId, officers }: EditOfficerFormProps) => { const { control, - register, handleSubmit, reset, formState: { errors, dirtyFields, isDirty }, @@ -143,11 +136,9 @@ const EditOfficerForm = ({ clubId, officers }: EditOfficerFormProps) => { {fields.map((field, index) => ( @@ -181,23 +172,13 @@ const EditOfficerForm = ({ clubId, officers }: EditOfficerFormProps) => { }; export default EditOfficerForm; type OfficerItemProps = { - register: UseFormRegister>; remove: (index: number, userId: string) => void; id: string; index: number; name: string; locked: boolean; - errors: FieldErrors>; }; -const OfficerItem = ({ - register, - index, - id, - name, - remove, - errors, - locked, -}: OfficerItemProps) => { +const OfficerItem = ({ index, id, name, remove, locked }: OfficerItemProps) => { return (
@@ -206,21 +187,6 @@ const OfficerItem = ({ {name}
-
- - {errors.officers && errors.officers[index]?.title && ( -

- {errors.officers[index]?.title?.message} -

- )} -