diff --git a/src/components/pages/purchase/PurchaseFilterModal.tsx b/src/components/pages/purchase/PurchaseFilterModal.tsx new file mode 100644 index 00000000..a9cd00cd --- /dev/null +++ b/src/components/pages/purchase/PurchaseFilterModal.tsx @@ -0,0 +1,201 @@ +'use client'; + +import { RefObject, useState, useEffect } from 'react'; +import { useFormik } from 'formik'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Modal from '@/components/Modal'; +import Button from '@/components/Button'; +import DateInput from '@/components/input/DateInput'; +import SelectInputCheckbox from '@/components/input/SelectInputCheckbox'; + +import { OptionType, useSelect } from '@/components/input/SelectInput'; +import { PurchaseFilter } from '@/types/api/purchase/purchase'; +import { ProductCategory } from '@/types/api/master-data/product-category'; +import { ProductCategoryApi } from '@/services/api/master-data'; +import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line'; + +interface PurchaseFilterModalProps { + ref: RefObject; + onSubmit?: (values: PurchaseFilter) => void; + onReset?: () => void; +} + +const PurchaseFilterModal = ({ + ref, + onSubmit, + onReset, +}: PurchaseFilterModalProps) => { + const closeModalHandler = () => { + ref.current?.close(); + }; + + // ===== DATE ERROR STATE ===== + const [dateErrorShown, setDateErrorShown] = useState(false); + const [hasDateError, setHasDateError] = useState(false); + + // ===== CLEANUP TOAST ON UNMOUNT ===== + useEffect(() => { + return () => { + if (dateErrorShown) { + toast.dismiss(); + } + }; + }, [dateErrorShown]); + + // ===== CLEANUP TOAST WHEN MODAL CLOSES ===== + useEffect(() => { + const dialogElement = ref.current; + const handleModalClose = () => { + if (dateErrorShown) { + toast.dismiss(); + setDateErrorShown(false); + } + }; + + dialogElement?.addEventListener('close', handleModalClose); + + return () => { + dialogElement?.removeEventListener('close', handleModalClose); + }; + }, [ref, dateErrorShown]); + + const { + setInputValue: setProductCategoryInputValue, + options: productCategoryOptions, + isLoadingOptions: isLoadingProductCategoryOptions, + loadMore: loadMoreProductCategory, + } = useSelect( + ProductCategoryApi.basePath, + 'id', + 'name', + 'search' + ); + + const formik = useFormik<{ + poDate: string; + category: { label: string; value: number }[]; + status: { label: string; value: string }[]; + }>({ + initialValues: { + poDate: '', + category: [], + status: [], + }, + onSubmit: async (values) => { + const formattedValues = { + ...values, + category: values.category.map((item) => String(item.value)), + status: values.status.map((item) => String(item.value)), + }; + + onSubmit?.(formattedValues); + closeModalHandler(); + }, + onReset: () => { + onReset?.(); + closeModalHandler(); + }, + }); + + const productCategoryChangeHandler = ( + val: OptionType | OptionType[] | null + ) => { + formik.setFieldValue('category', val); + }; + + const statusChangeHandler = (val: OptionType | OptionType[] | null) => { + formik.setFieldValue('status', val); + }; + + return ( + +
+ {/* Modal Header */} +
+
+ +

Filter Data

+
+ + +
+ + {/* Modal Body */} +
+
+ + + + + ({ + label: item.step_name, + value: item.step_name, + }))} + /> +
+
+ + {/* Modal Footer */} +
+ + + +
+
+
+ ); +}; + +export default PurchaseFilterModal;