'use client'; import { useModal } from '@/components/Modal'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { CustomerApi } from '@/services/api/master-data'; import { CreateCustomerPayload, Customer, UpdateCustomerPayload, } from '@/types/api/master-data/customer'; import { useRouter } from 'next/navigation'; import { useCallback, useEffect, useMemo, useState } from 'react'; import toast from 'react-hot-toast'; import { CustomerFormSchema, CustomerFormValues, UpdateCustomerFormSchema, } from '@/components/pages/master-data/customer/form/CustomerForm.schema'; import { useFormik } from 'formik'; import Button from '@/components/Button'; import { Icon } from '@iconify/react'; import TextInput from '@/components/input/TextInput'; import { cn } from '@/lib/helper'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import TextArea from '@/components/input/TextArea'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; import useSWR from 'swr'; import { UserApi } from '@/services/api/user'; import { TYPE_OPTIONS } from '@/config/constant'; import RequirePermission from '@/components/helper/RequirePermission'; interface CustomerFormProps { formType?: 'add' | 'edit' | 'detail'; initialValues?: Customer; } const CustomerForm = ({ formType = 'add', initialValues, }: CustomerFormProps) => { // Setup Kebutuhan Form const router = useRouter(); const deleteModal = useModal(); // Setup State const [customerFormErrorMessage, setCustomerFormErrorMessage] = useState(''); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [picSelectInputValue, setPicSelectInputValue] = useState(''); // Fetch Data const picUrl = `${UserApi.basePath}?${new URLSearchParams({ search: picSelectInputValue ?? '', })}`; const { data: pic, isLoading: isLoadingPic } = useSWR( picUrl, UserApi.getAllFetcher ); // -- Options data mapping const picOptions = isResponseSuccess(pic) ? pic?.data.map((area) => ({ value: area.id, label: area.name, })) : []; const typeOptions = TYPE_OPTIONS; // Handler Event const createCustomerHandler = useCallback( async (payload: CreateCustomerPayload) => { const createCustomerRes = await CustomerApi.create(payload); if (isResponseError(createCustomerRes)) { setCustomerFormErrorMessage(createCustomerRes.message); return; } toast.success(createCustomerRes?.message as string); router.push('/master-data/customer'); }, [router] ); const updateCustomerHandler = useCallback( async (customerId: number, payload: UpdateCustomerPayload) => { const updateCustomerRes = await CustomerApi.update(customerId, payload); if (isResponseError(updateCustomerRes)) { setCustomerFormErrorMessage(updateCustomerRes.message); return; } toast.success(updateCustomerRes?.message as string); router.push('/master-data/customer'); }, [router] ); const deleteCustomerHandler = () => { deleteModal.openModal(); }; const confirmationModalDeleteclickHandler = async () => { setIsDeleteLoading(true); await CustomerApi.delete(initialValues?.id as number); deleteModal.closeModal(); setIsDeleteLoading(false); router.push('/master-data/customer'); }; // -- Option Handler const picChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('pic', true); formik.setFieldValue('pic', val); formik.setFieldTouched('picId', true); formik.setFieldValue('picId', (val as OptionType)?.value); }; const typeChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('type', true); formik.setFieldValue('type', val); }; // Utils Functions const normalizeType = (type?: string | { value: string; label: string }) => { if (!type) return TYPE_OPTIONS[0]; return typeof type === 'string' ? { value: type, label: type } : type; }; // Memo untuk simpan input sebelumnya const formikInitialValues = useMemo(() => { return { name: initialValues?.name ?? '', email: initialValues?.email ?? '', phone: initialValues?.phone ?? '', picId: initialValues?.pic?.id ?? 0, pic: initialValues?.pic ? { value: initialValues.pic.id, label: initialValues.pic.name, } : { value: 0, label: '', }, type: normalizeType(initialValues?.type), address: initialValues?.address ?? '', account_number: initialValues?.account_number ?? '', }; }, [initialValues]); // Formik const formik = useFormik({ initialValues: formikInitialValues, enableReinitialize: true, validationSchema: formType === 'edit' ? UpdateCustomerFormSchema : CustomerFormSchema, onSubmit: async (values) => { // reset error message setCustomerFormErrorMessage(''); // create payload const payload: CreateCustomerPayload = { name: values.name, email: values.email, phone: values.phone, pic_id: values.picId, type: (values.type as OptionType).value as string, address: values.address, account_number: values.account_number, }; // cek type form yang disubmit switch (formType) { case 'add': await createCustomerHandler(payload); break; case 'edit': await updateCustomerHandler(initialValues?.id as number, payload); break; } }, }); const { setValues: formikSetValues } = formik; // Initialize Formik useEffect(() => { formikSetValues(formikInitialValues); }, [formikSetValues, formikInitialValues]); // Render return ( <>

{formType === 'add' && 'Tambah Customer'} {formType === 'edit' && 'Ubah Customer'} {formType === 'detail' && 'Detail Customer'}

{/* Fields Form */}
item.value === formik.values.type?.value ) ?? undefined } onChange={typeChangeHandler} options={typeOptions} isError={formik.touched.type && Boolean(formik.errors.type)} errorMessage={formik.errors.type as string} isDisabled={formType === 'detail'} isClearable isSearchable={true} />