From 8afc1a63818fcd2bbdd01983017331894e94e612 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 20 Apr 2026 00:28:41 +0700 Subject: [PATCH] feat: create ReportDepreciationFilterModal component --- .../tab/ReportDepreciationFilterModal.tsx | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/components/pages/report/expense/tab/ReportDepreciationFilterModal.tsx diff --git a/src/components/pages/report/expense/tab/ReportDepreciationFilterModal.tsx b/src/components/pages/report/expense/tab/ReportDepreciationFilterModal.tsx new file mode 100644 index 00000000..91e5f536 --- /dev/null +++ b/src/components/pages/report/expense/tab/ReportDepreciationFilterModal.tsx @@ -0,0 +1,270 @@ +'use client'; + +import { RefObject, useMemo, useState } from 'react'; +import { useFormik } from 'formik'; +import * as yup from 'yup'; + +import { Icon } from '@iconify/react'; +import Modal from '@/components/Modal'; +import Button from '@/components/Button'; +import DateInput from '@/components/input/DateInput'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; + +import { AreaApi, LocationApi } from '@/services/api/master-data'; +import { ProjectFlockApi } from '@/services/api/production'; +import { Area } from '@/types/api/master-data/area'; +import { Location } from '@/types/api/master-data/location'; +import { ProjectFlock } from '@/types/api/production/project-flock'; + +export type ReportDepreciationFilterValues = { + area_id: string | null; + location_id: string | null; + project_flock_id: string | null; + period: string | null; +}; + +export const ReportDepreciationFilterSchema = yup.object({ + area_id: yup.string().nullable(), + location_id: yup.string().nullable(), + project_flock_id: yup.string().nullable(), + period: yup.string().nullable().required('Periode wajib dipilih'), +}) as yup.ObjectSchema; + +interface ReportDepreciationFilterModalProps { + ref: RefObject; + initialValues?: ReportDepreciationFilterValues; + onSubmit?: (values: Partial) => void; + onReset?: () => void; +} + +const defaultInitialValues: ReportDepreciationFilterValues = { + area_id: null, + location_id: null, + project_flock_id: null, + period: null, +}; + +const ReportDepreciationFilterModal = ({ + ref, + initialValues, + onSubmit, + onReset, +}: ReportDepreciationFilterModalProps) => { + const [selectedAreaId, setSelectedAreaId] = useState( + initialValues?.area_id || undefined + ); + const [selectedLocationId, setSelectedLocationId] = useState< + string | undefined + >(initialValues?.location_id || undefined); + + const closeModalHandler = () => { + ref.current?.close(); + }; + + const { + setInputValue: setAreaInputValue, + options: areaOptions, + isLoadingOptions: isLoadingAreaOptions, + loadMore: loadMoreAreas, + } = useSelect(AreaApi.basePath, 'id', 'name', 'search'); + + const { + setInputValue: setLocationInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + loadMore: loadMoreLocations, + } = useSelect(LocationApi.basePath, 'id', 'name', 'search', { + area_id: selectedAreaId || '', + }); + + const { + setInputValue: setProjectFlockInputValue, + options: projectFlockOptions, + isLoadingOptions: isLoadingProjectFlockOptions, + loadMore: loadMoreProjectFlocks, + } = useSelect( + ProjectFlockApi.basePath, + 'id', + 'flock_name', + 'search', + { + location_id: selectedLocationId || '', + } + ); + + const formik = useFormik({ + initialValues: initialValues || defaultInitialValues, + validationSchema: ReportDepreciationFilterSchema, + onSubmit: async (values) => { + onSubmit?.(values); + closeModalHandler(); + }, + onReset: (_) => { + onReset?.(); + closeModalHandler(); + }, + }); + + 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 projectFlockValue = useMemo(() => { + if (!formik.values.project_flock_id) return null; + return ( + projectFlockOptions.find( + (opt) => String(opt.value) === formik.values.project_flock_id + ) || null + ); + }, [formik.values.project_flock_id, projectFlockOptions]); + + const areaChangeHandler = (val: OptionType | OptionType[] | null) => { + const areaId = val && !Array.isArray(val) ? String(val.value) : null; + + setSelectedAreaId(areaId || undefined); + formik.setFieldValue('area_id', areaId); + formik.setFieldValue('location_id', null); + formik.setFieldValue('project_flock_id', null); + setSelectedLocationId(undefined); + }; + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + const locationId = val && !Array.isArray(val) ? String(val.value) : null; + + setSelectedLocationId(locationId || undefined); + formik.setFieldValue('location_id', locationId); + formik.setFieldValue('project_flock_id', null); + }; + + const projectFlockChangeHandler = (val: OptionType | OptionType[] | null) => { + const projectFlockId = + val && !Array.isArray(val) ? String(val.value) : null; + + formik.setFieldValue('project_flock_id', projectFlockId); + }; + + return ( + +
+
+
+ +

Filter Data

+
+ + +
+ +
+ + + + + + + +
+ +
+ + + +
+
+
+ ); +}; + +export default ReportDepreciationFilterModal;