'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 useSWR from 'swr'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import TextInput from '@/components/input/TextInput'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import RequirePermission from '@/components/helper/RequirePermission'; import { NonstockFormSchema, NonstockFormValues, UpdateNonstockFormSchema, } from '@/components/pages/master-data/nonstock/form/NonstockForm.schema'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { Nonstock, CreateNonstockPayload, UpdateNonstockPayload, } from '@/types/api/master-data/nonstock'; import { NonstockApi, SupplierApi, UomApi } from '@/services/api/master-data'; import { cn } from '@/lib/helper'; import { flags } from '@/types/api/api-general'; import { SUPPLIER_FLAG_OPTIONS } from '@/config/constant'; interface NonstockFormProps { type?: 'add' | 'edit' | 'detail'; initialValues?: Nonstock; } const NonstockForm = ({ type = 'add', initialValues }: NonstockFormProps) => { const router = useRouter(); const deleteModal = useModal(); const [nonstockFormErrorMessage, setNonstockFormErrorMessage] = useState(''); const [isDeleteLoading, setIsDeleteLoading] = useState(false); const createNonstockHandler = useCallback( async (payload: CreateNonstockPayload) => { const createNonstockRes = await NonstockApi.create(payload); if (isResponseError(createNonstockRes)) { setNonstockFormErrorMessage(createNonstockRes.message); return; } toast.success(createNonstockRes?.message as string); router.push('/master-data/nonstock'); }, [router] ); const updateNonstockHandler = useCallback( async (nonstockId: number, payload: UpdateNonstockPayload) => { const updateNonstockRes = await NonstockApi.update(nonstockId, payload); if (updateNonstockRes?.status === 'error') { setNonstockFormErrorMessage(updateNonstockRes.message); return; } toast.success(updateNonstockRes?.message as string); router.refresh(); router.push('/master-data/nonstock'); }, [router] ); const formikInitialValues = useMemo(() => { return { name: initialValues?.name ?? '', uomId: initialValues?.uom_id ?? 0, uom: initialValues?.uom ? { value: initialValues?.uom.id, label: initialValues?.uom.name, } : null, supplierIds: initialValues?.suppliers.map((supplier) => supplier.id) ?? [], suppliers: initialValues?.suppliers.map((supplier) => ({ value: supplier.id, label: supplier.name, })) ?? [], flags: initialValues?.flags ?? [], }; }, [initialValues]); const formik = useFormik({ initialValues: formikInitialValues, validationSchema: type === 'edit' ? UpdateNonstockFormSchema : NonstockFormSchema, onSubmit: async (values) => { setNonstockFormErrorMessage(''); const nonstockPayload: CreateNonstockPayload = { name: values.name, uom_id: values.uomId, supplier_ids: values.supplierIds as number[], flags: values.flags as flags[], }; switch (type) { case 'add': await createNonstockHandler(nonstockPayload); break; case 'edit': await updateNonstockHandler( initialValues?.id as number, nonstockPayload ); break; } }, }); const { setValues: formikSetValues } = formik; // UOM const [uomSelectInputValue, setUomSelectInputValue] = useState(''); const uomsUrl = `${UomApi.basePath}?${new URLSearchParams({ search: uomSelectInputValue ?? '', }).toString()}`; const { data: uoms, isLoading: isLoadingUoms } = useSWR( uomsUrl, UomApi.getAllFetcher ); const uomOptions = isResponseSuccess(uoms) ? uoms?.data.map((uom) => ({ value: uom.id, label: uom.name, })) : []; const uomChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('uom', true); formik.setFieldValue('uom', val); formik.setFieldTouched('uomId', true); formik.setFieldValue('uomId', (val as OptionType)?.value); }; // supplier const [supplierSelectInputValue, setSupplierSelectInputValue] = useState(''); const suppliersUrl = `${SupplierApi.basePath}?${new URLSearchParams({ search: supplierSelectInputValue ?? '', }).toString()}`; const { data: suppliers, isLoading: isLoadingSuppliers } = useSWR( suppliersUrl, SupplierApi.getAllFetcher ); const supplierOptions = isResponseSuccess(suppliers) ? suppliers?.data .filter((sup) => sup.category === 'BOP') .map((supplier) => ({ value: supplier.id, label: supplier.name, })) : []; const supplierChangeHandler = (val: OptionType | OptionType[] | null) => { formik.setFieldTouched('suppliers', true); formik.setFieldValue('suppliers', val); const supplierIds = (val as OptionType[]).map( (supplier) => supplier.value as number ); formik.setFieldTouched('supplierIds', true); formik.setFieldValue('supplierIds', supplierIds); }; const deleteNonstockClickHandler = () => { deleteModal.openModal(); }; const confirmationModalDeleteClickHandler = async () => { setIsDeleteLoading(true); await NonstockApi.delete(initialValues?.id as number); deleteModal.closeModal(); toast.success('Successfully delete Nonstock!'); setIsDeleteLoading(false); router.push('/master-data/nonstock'); }; const flagsChangeHandler = (val: OptionType | OptionType[] | null) => { const formattedFlags = (val as OptionType[]).map( (flag) => flag.value as string ); formik.setFieldValue('flags', formattedFlags); }; useEffect(() => { formikSetValues(formikInitialValues); }, [formikSetValues, formikInitialValues]); return ( <>

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

formik.values.flags?.includes(opt.value) )} onChange={flagsChangeHandler} options={SUPPLIER_FLAG_OPTIONS} isError={formik.touched.flags && Boolean(formik.errors.flags)} errorMessage={formik.errors.flags as string} isDisabled={type === 'detail'} isClearable />
{type !== 'add' && (
{type !== 'edit' && ( )}
)} {type !== 'detail' && (
)}
{nonstockFormErrorMessage && (
{nonstockFormErrorMessage}
)}
{type !== 'add' && ( )} ); }; export default NonstockForm;