diff --git a/src/components/pages/uniformity/UniformityTable.tsx b/src/components/pages/uniformity/UniformityTable.tsx index 52b98c91..2b23c009 100644 --- a/src/components/pages/uniformity/UniformityTable.tsx +++ b/src/components/pages/uniformity/UniformityTable.tsx @@ -23,6 +23,18 @@ import UniformityTableSkeleton from '@/components/pages/uniformity/skeleton/Unif import RequirePermission from '@/components/helper/RequirePermission'; import { useUniformityStore } from '@/stores/uniformity/uniformity.store'; import FloatingActionsButton from '@/components/FloatingActionsButton'; +import Modal from '@/components/Modal'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; +import DateInput from '@/components/input/DateInput'; +import { LocationApi } from '@/services/api/master-data'; +import { + ProjectFlockApi, + ProjectFlockKandangApi, +} from '@/services/api/production'; +import { Kandang } from '@/types/api/master-data/kandang'; import { getStatusColor, getStatusIndicatorColor, @@ -170,16 +182,170 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => { const singleRejectModal = useModal(); const bulkApproveModal = useModal(); const bulkRejectModal = useModal(); + const filterModal = useModal(); + + // ===== FILTER STATE ===== + const [filterLocation, setFilterLocation] = useState(null); + const [filterProjectFlock, setFilterProjectFlock] = + useState(null); + const [filterKandang, setFilterKandang] = useState(null); + const [filterStartDate, setFilterStartDate] = useState(''); + const [filterEndDate, setFilterEndDate] = useState(''); + const [projectFlockSearchValue, setProjectFlockSearchValue] = useState(''); + + const { + setInputValue: setFilterLocationInputValue, + options: filterLocationOptions, + isLoadingOptions: isLoadingFilterLocations, + } = useSelect(LocationApi.basePath, 'id', 'name', 'search'); + + // ===== FETCH PROJECT FLOCKS DATA FOR FILTER ===== + const filterProjectFlocksUrl = useMemo(() => { + const params = new URLSearchParams({ + search: projectFlockSearchValue || '', + limit: '100', + }); + if (filterLocation) { + params.append('location_id', filterLocation.value.toString()); + } + return `${ProjectFlockApi.basePath}?${params.toString()}`; + }, [projectFlockSearchValue, filterLocation]); + + const { + data: filterProjectFlocksData, + isLoading: isLoadingFilterProjectFlocks, + } = useSWR(filterProjectFlocksUrl, ProjectFlockApi.getAllFetcher); + + const filterProjectFlocksDataList = useMemo( + () => + isResponseSuccess(filterProjectFlocksData) + ? filterProjectFlocksData.data + : undefined, + [filterProjectFlocksData] + ); + + const filterProjectFlockOptions = useMemo(() => { + let options: OptionType[] = []; + + if (isResponseSuccess(filterProjectFlocksData)) { + const flockOptions = + filterProjectFlocksData?.data.map((projectFlock) => ({ + value: projectFlock.id, + label: projectFlock.flock_name || '', + })) || []; + options = options.concat(flockOptions); + } + + return options; + }, [filterProjectFlocksData]); + + // ===== KANDANG OPTIONS FOR FILTER ===== + const filterKandangOptions = useMemo(() => { + let options: OptionType[] = []; + + if (filterProjectFlock && filterProjectFlocksDataList) { + const selectedProjectFlockData = filterProjectFlocksDataList.find( + (pf) => pf.id === filterProjectFlock.value + ); + + if (selectedProjectFlockData?.kandangs) { + const kandangOpts = selectedProjectFlockData.kandangs.map( + (kandang: Kandang) => ({ + value: kandang.id, + label: kandang.name || '', + }) + ); + options = options.concat(kandangOpts); + } + } + + return options; + }, [filterProjectFlock, filterProjectFlocksDataList]); + + // ===== BUILD SWR KEY WITH FILTERS ===== + const uniformitySwrKey = useMemo(() => { + const basePath = UniformityApi.basePath; + const queryParams = new URLSearchParams(); + + if (filterLocation) { + queryParams.append('location_id', filterLocation.value.toString()); + } + if (filterProjectFlock) { + queryParams.append( + 'project_flock_id', + filterProjectFlock.value.toString() + ); + } + if (filterKandang) { + queryParams.append('kandang_id', filterKandang.value.toString()); + } + if (filterStartDate) { + queryParams.append('start_date', filterStartDate); + } + if (filterEndDate) { + queryParams.append('end_date', filterEndDate); + } + + const tableQueryString = getTableFilterQueryString(); + const tableParams = new URLSearchParams( + tableQueryString.split('?')[1] || '' + ); + + tableParams.forEach((value, key) => { + queryParams.append(key, value); + }); + + const queryString = queryParams.toString(); + return queryString ? `${basePath}?${queryString}` : basePath; + }, [ + filterLocation, + filterProjectFlock, + filterKandang, + filterStartDate, + filterEndDate, + getTableFilterQueryString, + ]); const { data: uniformities, isLoading, mutate: refreshUniformities, - } = useSWR( - `${UniformityApi.basePath}${getTableFilterQueryString()}`, - UniformityApi.getAllFetcher + } = useSWR(uniformitySwrKey, UniformityApi.getAllFetcher); + + // ===== FILTER HANDLERS ===== + const handleFilterLocationChange = useCallback( + (val: OptionType | OptionType[] | null) => { + setFilterLocation(val as OptionType | null); + }, + [] ); + const handleFilterProjectFlockChange = useCallback( + (val: OptionType | OptionType[] | null) => { + setFilterProjectFlock(val as OptionType | null); + }, + [] + ); + + const handleFilterKandangChange = useCallback( + (val: OptionType | OptionType[] | null) => { + setFilterKandang(val as OptionType | null); + }, + [] + ); + + const handleResetFilters = useCallback(() => { + setFilterLocation(null); + setFilterProjectFlock(null); + setFilterKandang(null); + setFilterStartDate(''); + setFilterEndDate(''); + }, []); + + const handleApplyFilters = useCallback(() => { + filterModal.closeModal(); + }, [filterModal]); + const selectedRowIds = useMemo(() => { return Object.keys(rowSelection) .filter((key) => rowSelection[key]) @@ -485,7 +651,7 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
- @@ -683,6 +849,97 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
+ {/* Filter Modal */} + +
+
+

Filter Data

+ +
+ +
+
+ setFilterStartDate(e.target.value)} + className={{ wrapper: 'w-full' }} + /> + + setFilterEndDate(e.target.value)} + className={{ wrapper: 'w-full' }} + /> +
+ + + + + + +
+ +
+ + +
+
+
+ {/* Floating Actions Button */} | undefined> { - return await this.customRequest>(''); + async getUniformity( + location_id?: number, + project_flock_id?: number, + kandang_id?: number, + project_flock_kandang_id?: number, + start_date?: string, + end_date?: string + ): Promise | undefined> { + return await this.customRequest>('', { + method: 'GET', + params: { + location_id: location_id, + project_flock_id: project_flock_id, + kandang_id: kandang_id, + project_flock_kandang_id: project_flock_kandang_id, + start_date: start_date, + end_date: end_date, + }, + }); } async getUniformityDetail(