diff --git a/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx new file mode 100644 index 00000000..90b9e4e0 --- /dev/null +++ b/src/components/pages/master-data/warehouse/form/WarehouseForm.tsx @@ -0,0 +1,528 @@ +'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 { + WarehouseFormSchema, + WarehouseFormValues, + UpdateWarehouseFormSchema, +} from '@/components/pages/master-data/warehouse/form/WarehouseForm.schema'; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { + Warehouse, + CreateWarehousePayload, + UpdateWarehousePayload, +} from '@/types/api/master-data/warehouse'; +import { + AreaApi, + KandangApi, + LocationApi, + WarehouseApi, +} from '@/services/api/master-data'; +import { cn } from '@/lib/helper'; +import { WAREHOUSE_TYPE_OPTIONS } from '@/config/constant'; + +interface WarehouseFormProps { + type?: 'add' | 'edit' | 'detail'; + initialValues?: Warehouse; +} + +const WarehouseForm = ({ type = 'add', initialValues }: WarehouseFormProps) => { + const router = useRouter(); + const deleteModal = useModal(); + + const [warehouseFormErrorMessage, setWarehouseFormErrorMessage] = + useState(''); + const [isDeleteLoading, setIsDeleteLoading] = useState(false); + + const createWarehouseHandler = useCallback( + async (payload: CreateWarehousePayload) => { + const createWarehouseRes = await WarehouseApi.create(payload); + + if (isResponseError(createWarehouseRes)) { + setWarehouseFormErrorMessage(createWarehouseRes.message); + return; + } + + toast.success(createWarehouseRes?.message as string); + router.push('/master-data/warehouse'); + }, + [router] + ); + + const updateWarehouseHandler = useCallback( + async (warehouseId: number, payload: UpdateWarehousePayload) => { + const updateWarehouseRes = await WarehouseApi.update( + warehouseId, + payload + ); + + if (updateWarehouseRes?.status === 'error') { + setWarehouseFormErrorMessage(updateWarehouseRes.message); + return; + } + + toast.success(updateWarehouseRes?.message as string); + router.refresh(); + router.push('/master-data/warehouse'); + }, + [router] + ); + + const formikInitialValues = useMemo(() => { + switch (initialValues?.type) { + case 'AREA': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'AREA', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: 0, + location: null, + kandangId: 0, + kandang: null, + }; + + case 'LOKASI': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'LOKASI', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: initialValues?.location?.id ?? 0, + location: initialValues?.location + ? { + value: initialValues.location.id, + label: initialValues.location.name, + } + : null, + kandangId: 0, + kandang: null, + }; + + case 'KANDANG': + return { + name: initialValues?.name ?? '', + type: initialValues?.type ?? 'KANDANG', + areaId: initialValues?.area?.id ?? 0, + area: initialValues?.area + ? { + value: initialValues.area.id, + label: initialValues.area.name, + } + : null, + locationId: initialValues?.location?.id ?? 0, + location: initialValues?.location + ? { + value: initialValues.location.id, + label: initialValues.location.name, + } + : null, + kandangId: initialValues?.kandang?.id ?? 0, + kandang: initialValues?.kandang + ? { + value: initialValues.kandang.id, + label: initialValues.kandang.name, + } + : null, + }; + + default: + return { + name: '', + type: 'AREA', + areaId: 0, + area: null, + locationId: 0, + location: null, + kandangId: 0, + kandang: null, + }; + } + }, [initialValues]); + + const formik = useFormik({ + initialValues: formikInitialValues, + validationSchema: + type === 'edit' ? UpdateWarehouseFormSchema : WarehouseFormSchema, + onSubmit: async (values) => { + setWarehouseFormErrorMessage(''); + + let warehousePayload: CreateWarehousePayload | undefined = undefined; + + switch (values.type) { + case 'AREA': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + }; + break; + + case 'LOKASI': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + location_id: values.locationId as number, + }; + break; + + case 'KANDANG': + warehousePayload = { + name: values.name, + type: values.type, + area_id: values.areaId as number, + location_id: values.locationId as number, + kandang_id: values.kandangId as number, + }; + break; + } + + switch (type) { + case 'add': + await createWarehouseHandler(warehousePayload); + break; + + case 'edit': + await updateWarehouseHandler( + initialValues?.id as number, + warehousePayload + ); + break; + } + }, + }); + + const { setValues: formikSetValues } = formik; + + // Area + const [areaSelectInputValue, setAreaSelectInputValue] = useState(''); + + const areasUrl = `${AreaApi.basePath}?${new URLSearchParams({ + search: areaSelectInputValue ?? '', + }).toString()}`; + + const { data: areas, isLoading: isLoadingAreas } = useSWR( + areasUrl, + AreaApi.getAllFetcher + ); + + const areaOptions = isResponseSuccess(areas) + ? areas?.data.map((area) => ({ + value: area.id, + label: area.name, + })) + : []; + + // Location + const [locationSelectInputValue, setLocationSelectInputValue] = useState(''); + + const locationsUrl = `${LocationApi.basePath}?${new URLSearchParams({ + search: locationSelectInputValue ?? '', + }).toString()}`; + + const { data: locations, isLoading: isLoadingLocations } = useSWR( + locationsUrl, + LocationApi.getAllFetcher + ); + + const locationOptions = isResponseSuccess(locations) + ? locations?.data.map((location) => ({ + value: location.id, + label: location.name, + })) + : []; + + // Kandang + const [kandangSelectInputValue, setKandangSelectInputValue] = useState(''); + + const kandangsUrl = `${KandangApi.basePath}?${new URLSearchParams({ + search: kandangSelectInputValue ?? '', + }).toString()}`; + + const { data: kandangs, isLoading: isLoadingKandangs } = useSWR( + kandangsUrl, + KandangApi.getAllFetcher + ); + + const kandangOptions = isResponseSuccess(kandangs) + ? kandangs?.data.map((kandang) => ({ + value: kandang.id, + label: kandang.name, + })) + : []; + + const typeChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('type', true); + formik.setFieldValue('type', (val as OptionType)?.value); + }; + + const areaChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('area', true); + formik.setFieldValue('area', val); + + formik.setFieldTouched('areaId', true); + formik.setFieldValue('areaId', (val as OptionType)?.value); + }; + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('location', true); + formik.setFieldValue('location', val); + + formik.setFieldTouched('locationId', true); + formik.setFieldValue('locationId', (val as OptionType)?.value); + }; + + const kandangChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldTouched('kandang', true); + formik.setFieldValue('kandang', val); + + formik.setFieldTouched('kandangId', true); + formik.setFieldValue('kandangId', (val as OptionType)?.value); + }; + + const deleteWarehouseClickHandler = () => { + deleteModal.openModal(); + }; + + const confirmationModalDeleteClickHandler = async () => { + setIsDeleteLoading(true); + + await WarehouseApi.delete(initialValues?.id as number); + + deleteModal.closeModal(); + toast.success('Successfully delete Warehouse!'); + setIsDeleteLoading(false); + router.push('/master-data/warehouse'); + }; + + useEffect(() => { + formikSetValues(formikInitialValues); + }, [formikSetValues, formikInitialValues]); + + return ( + <> +
+
+ + +

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

+
+ +
+
+ + + + + + + {(formik.values.type === 'LOKASI' || + formik.values.type === 'KANDANG') && ( + + )} + + {formik.values.type === 'KANDANG' && ( + + )} +
+ +
+ {type !== 'add' && ( +
+ + + {type !== 'edit' && ( + + )} +
+ )} + + {type !== 'detail' && ( +
+ + + +
+ )} +
+ + {warehouseFormErrorMessage && ( +
+ + {warehouseFormErrorMessage} +
+ )} +
+
+ + {type !== 'add' && ( + + )} + + ); +}; + +export default WarehouseForm;