diff --git a/src/components/pages/master-data/fcr/form/FcrForm.tsx b/src/components/pages/master-data/fcr/form/FcrForm.tsx new file mode 100644 index 00000000..ab17eda8 --- /dev/null +++ b/src/components/pages/master-data/fcr/form/FcrForm.tsx @@ -0,0 +1,389 @@ +'use client'; + +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useFormik } from 'formik'; +import { toast } from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import TextInput from '@/components/input/TextInput'; +import { useModal } from '@/components/Modal'; +import ConfirmationModal from '@/components/modal/ConfirmationModal'; + +import { + FcrFormSchema, + FcrFormValues, + UpdateFcrFormSchema, +} from '@/components/pages/master-data/fcr/form/FcrForm.schema'; +import { isResponseError } from '@/lib/api-helper'; +import { + CreateFcrPayload, + Fcr, + FcrWithStandards, + UpdateFcrPayload, +} from '@/types/api/master-data/fcr'; +import { FcrApi } from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; + +interface FcrFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: FcrWithStandards; +} + +const FcrForm = ({ type = 'add', initialValues }: FcrFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [fcrFormErrorMessage, setFcrFormErrorMessage] = useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createFcrHandler = useCallback( + async (payload: CreateFcrPayload) => { + const createFcrRes = await FcrApi.create(payload); + + if (isResponseError(createFcrRes)) { + setFcrFormErrorMessage(createFcrRes.message); + return; + } + + toast.success(createFcrRes?.message as string); + router.push('/master-data/fcr'); + }, + [router] + ); + + const updateFcrHandler = useCallback( + async (fcrId: number, payload: UpdateFcrPayload) => { + const updateFcrRes = await FcrApi.update(fcrId, payload); + + if (updateFcrRes?.status === 'error') { + setFcrFormErrorMessage(updateFcrRes.message); + return; + } + + toast.success(updateFcrRes?.message as string); + router.refresh(); + router.push('/master-data/fcr'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + return { + name: initialValues?.name ?? '', + fcrStandards: initialValues?.fcr_standards + ? initialValues?.fcr_standards + : [ + { + weight: '', + fcr_number: '', + mortality: '', + }, + ], + }; + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: type === 'edit' ? UpdateFcrFormSchema : FcrFormSchema, + onSubmit: async (values) => { + setFcrFormErrorMessage(''); + + const fcrPayload: CreateFcrPayload = { + name: values.name, + fcr_standards: values.fcrStandards as CreateFcrPayload['fcr_standards'], + }; + + switch (type) { + case 'add': + await createFcrHandler(fcrPayload); + break; + + case 'edit': + await updateFcrHandler(initialValues?.id as number, fcrPayload); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + const addFcrStandard = () => + formik.setFieldValue('fcrStandards', [ + ...formik.values.fcrStandards, + { + weight: '', + fcr_number: '', + mortality: '', + }, + ]); + + const removeFcrStandard = (i: number) => + formik.setFieldValue( + 'fcrStandards', + formik.values.fcrStandards.filter((_, idx) => idx !== i) + ); + + const deleteFcrClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await FcrApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete FCR!'); + setIsDeleteLoading(false); + router.push('/master-data/fcr'); + }; + + const isRepeaterInputError = ( + column: keyof CreateFcrPayload['fcr_standards'][0], + idx: number + ) => { + return ( + formik.touched.fcrStandards?.[idx]?.[column] && + Boolean( + formik.errors.fcrStandards?.[idx] instanceof Object && + formik.errors.fcrStandards?.[idx]?.[column] + ) + ); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
+
+ + +

+ {type === 'add' && 'Tambah FCR'} + {type === 'edit' && 'Edit FCR'} + {type === 'detail' && 'Detail FCR'} +

+
+ +
+
+ + +
+
+ + + + + + + {type !== 'detail' && } + + + + + {formik.values.fcrStandards.map((fcrStandard, idx) => ( + + + + + {type !== 'detail' && ( + + )} + + ))} + +
BobotFCRMortalitasAksi
+ + + + + + + +
+
+
+ + {type !== 'detail' && ( + + )} +
+ +
+ {type !== 'add' && ( +
+ + + {type !== 'edit' && ( + + )} +
+ )} + + {type !== 'detail' && ( +
+ + + +
+ )} +
+ + {fcrFormErrorMessage && ( +
+ + {fcrFormErrorMessage} +
+ )} +
+
+ + {type !== 'add' && ( + + )} + + ); +}; + +export default FcrForm;