diff --git a/src/components/pages/production/project-flock/ProjectFlockTable.tsx b/src/components/pages/production/project-flock/ProjectFlockTable.tsx index 7a8ba4e1..7b090c11 100644 --- a/src/components/pages/production/project-flock/ProjectFlockTable.tsx +++ b/src/components/pages/production/project-flock/ProjectFlockTable.tsx @@ -3,7 +3,10 @@ import Button from '@/components/Button'; import CheckboxInput from '@/components/input/CheckboxInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput'; -import { OptionType, useSelect } from '@/components/input/SelectInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWithNotes'; @@ -22,6 +25,7 @@ import { useRouter } from 'next/navigation'; import { ChangeEventHandler, useEffect, useMemo, useState } from 'react'; import toast from 'react-hot-toast'; import useSWR from 'swr'; +import { useFormik } from 'formik'; import RequirePermission from '@/components/helper/RequirePermission'; import StatusBadge from '@/components/helper/StatusBadge'; @@ -32,6 +36,12 @@ import { useProjectFlockStore } from '@/stores/production/project-flock/project- import { ProjectFlockFormValues } from './form/ProjectFlockForm.schema'; import { useChickinStore } from '@/stores/production/chickin/chickin.store'; import { useProjectFlockClosingStore } from '@/stores/production/project-flock-closing/project-flock-closing.store'; +import { + ProjectFlockFilterSchema, + ProjectFlockFilterType, +} from './filter/ProjectFlockFilter'; +import Modal from '@/components/Modal'; +import SelectInputRadio from '@/components/input/SelectInputRadio'; const RowOptionsMenu = ({ props, @@ -154,19 +164,19 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { } = useTableFilter({ initial: { search: '', - areaFilter: '', - locationFilter: '', - kandangFilter: '', - periodFilter: '', + area_id: '', + location_id: '', + kandang_id: '', + category: '', }, paramMap: { page: 'page', pageSize: 'limit', search: 'search', - areaFilter: 'area_id', - locationFilter: 'location_id', - kandangFilter: 'kandang_id', - periodFilter: 'period', + area_id: 'area_id', + location_id: 'location_id', + kandang_id: 'kandang_id', + category: 'category', }, }); const router = useRouter(); @@ -207,6 +217,169 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { setClosingLoading, } = useProjectFlockClosingStore(); + // ===== FILTER MODAL STATE ===== + const filterModal = useModal(); + + // ===== FILTER DEPENDENCIES STATE ===== + const [filterAreaId, setFilterAreaId] = useState( + undefined + ); + const [filterLocationId, setFilterLocationId] = useState( + undefined + ); + + // ===== FORMIK SETUP FOR FILTER ===== + const formik = useFormik({ + initialValues: { + area_id: null, + location_id: null, + kandang_id: null, + category: null, + }, + validationSchema: ProjectFlockFilterSchema, + onSubmit: (values, { setSubmitting }) => { + updateFilter('area_id', values.area_id || ''); + updateFilter('location_id', values.location_id || ''); + updateFilter('kandang_id', values.kandang_id || ''); + updateFilter('category', values.category || ''); + filterModal.closeModal(); + setSubmitting(false); + }, + onReset: () => { + updateFilter('area_id', ''); + updateFilter('location_id', ''); + updateFilter('kandang_id', ''); + updateFilter('category', ''); + setFilterAreaId(undefined); + setFilterLocationId(undefined); + filterModal.closeModal(); + }, + }); + + // ===== FILTER OPTIONS ===== + const { + setInputValue: setAreaInputValue, + options: areaOptions, + isLoadingOptions: isLoadingAreaOptions, + loadMore: loadMoreAreas, + } = useSelect(AreaApi.basePath, 'id', 'name'); + + const { + setInputValue: setLocationInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + loadMore: loadMoreLocations, + } = useSelect(LocationApi.basePath, 'id', 'name', 'search', { + area_id: filterAreaId || '', + }); + + const { + setInputValue: setKandangInputValue, + options: kandangOptions, + isLoadingOptions: isLoadingKandangOptions, + loadMore: loadMoreKandangs, + } = useSelect(KandangApi.basePath, 'id', 'name', 'search', { + area_id: filterAreaId || '', + location_id: filterLocationId || '', + }); + + const categoryOptions = useMemo( + () => [ + { value: 'GROWING', label: 'Growing' }, + { value: 'LAYING', label: 'Laying' }, + ], + [] + ); + + // ===== FILTER HELPERS ===== + const areaValue = useMemo(() => { + if (!formik.values.area_id) return null; + return ( + areaOptions.find((opt) => String(opt.value) === formik.values.area_id) || + null + ); + }, [formik.values.area_id, areaOptions]); + + const locationValue = useMemo(() => { + if (!formik.values.location_id) return null; + return ( + locationOptions.find( + (opt) => String(opt.value) === formik.values.location_id + ) || null + ); + }, [formik.values.location_id, locationOptions]); + + const kandangValue = useMemo(() => { + if (!formik.values.kandang_id) return null; + return ( + kandangOptions.find( + (opt) => String(opt.value) === formik.values.kandang_id + ) || null + ); + }, [formik.values.kandang_id, kandangOptions]); + + const categoryValue = useMemo(() => { + if (!formik.values.category) return null; + return ( + categoryOptions.find((opt) => opt.value === formik.values.category) || + null + ); + }, [formik.values.category, categoryOptions]); + + // ===== ACTIVE FILTERS COUNT ===== + const activeFiltersCount = useMemo(() => { + let count = 0; + if (tableFilterState.area_id) count += 1; + if (tableFilterState.location_id) count += 1; + if (tableFilterState.kandang_id) count += 1; + if (tableFilterState.category) count += 1; + return count; + }, [ + tableFilterState.area_id, + tableFilterState.location_id, + tableFilterState.kandang_id, + tableFilterState.category, + ]); + + const hasFilters = activeFiltersCount > 0; + + // ===== FILTER DEPENDENCY HANDLERS ===== + const handleFilterAreaChange = (area: OptionType | null) => { + const areaId = area?.value ? String(area.value) : undefined; + setFilterAreaId(areaId); + if (!areaId) { + setFilterLocationId(undefined); + formik.setFieldValue('location_id', null); + formik.setFieldValue('kandang_id', null); + } + }; + + const handleFilterLocationChange = (location: OptionType | null) => { + const locationId = location?.value ? String(location.value) : undefined; + setFilterLocationId(locationId); + if (!locationId) { + formik.setFieldValue('kandang_id', null); + } + }; + + // ===== HANDLE FILTER MODAL OPEN ===== + const handleFilterModalOpen = () => { + const areaId = tableFilterState.area_id || null; + const locationId = tableFilterState.location_id || null; + + formik.setValues({ + area_id: areaId, + location_id: locationId, + kandang_id: tableFilterState.kandang_id || null, + category: tableFilterState.category || null, + }); + + setFilterAreaId(areaId || undefined); + setFilterLocationId(locationId || undefined); + + filterModal.openModal(); + }; + // ===== Fetch Data ===== const { data: projectFlocks, @@ -768,26 +941,21 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { void }) => { }} /> + {/* Filter Modal */} + + {/* Modal Header */} +
+
+ +

Filter Data

+
+ +
+
+
+ { + if (!Array.isArray(val)) { + const areaValue = val?.value ? String(val.value) : null; + formik.setFieldValue('area_id', areaValue); + handleFilterAreaChange(val || null); + } + }} + onInputChange={setAreaInputValue} + isLoading={isLoadingAreaOptions} + isClearable + onMenuScrollToBottom={loadMoreAreas} + className={{ wrapper: 'w-full' }} + /> + + { + if (!Array.isArray(val)) { + const locationValue = val?.value ? String(val.value) : null; + formik.setFieldValue('location_id', locationValue); + handleFilterLocationChange(val || null); + } + }} + onInputChange={setLocationInputValue} + isLoading={isLoadingLocationOptions} + isClearable + onMenuScrollToBottom={loadMoreLocations} + className={{ wrapper: 'w-full' }} + /> + + { + if (!Array.isArray(val)) { + formik.setFieldValue( + 'kandang_id', + val?.value ? String(val.value) : null + ); + } + }} + onInputChange={setKandangInputValue} + isLoading={isLoadingKandangOptions} + isClearable + onMenuScrollToBottom={loadMoreKandangs} + className={{ wrapper: 'w-full' }} + /> + + { + if (!Array.isArray(val)) { + formik.setFieldValue('category', val?.value || null); + } + }} + className={{ wrapper: 'w-full' }} + isClearable={true} + /> +
+ + {/* Modal Footer */} +
+ + +
+
+
+ {/* Project Flock Closing Modal */} ;