From d5962f94a1ff0be63114e5d5721dd6fecdef826a Mon Sep 17 00:00:00 2001 From: rstubryan Date: Fri, 13 Feb 2026 09:29:37 +0700 Subject: [PATCH] refactor(FE): Refactor production result filter to use OptionType --- .../filter/ProductionResultFilter.ts | 50 +++++++++++++++++-- .../tab/ProductionResultTab.tsx | 44 +++++++++------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/components/pages/report/production-result/filter/ProductionResultFilter.ts b/src/components/pages/report/production-result/filter/ProductionResultFilter.ts index 3281bb19..6df3759e 100644 --- a/src/components/pages/report/production-result/filter/ProductionResultFilter.ts +++ b/src/components/pages/report/production-result/filter/ProductionResultFilter.ts @@ -1,3 +1,4 @@ +import { OptionType } from '@/components/input/SelectInput'; import * as yup from 'yup'; export type ProductionResultFilterProps = { @@ -7,12 +8,51 @@ export type ProductionResultFilterProps = { kandang_id: string | null; }; +export type ProductionResultFilterFormType = { + area_id: OptionType | null; + location_id: OptionType | null; + project_flock_id: OptionType | null; + kandang_id: OptionType | null; +}; + export const ProductionResultFilterSchema = yup.object({ - area_id: yup.string().required('Area wajib dipilih'), - location_id: yup.string().required('Lokasi wajib dipilih'), - project_flock_id: yup.string().required('Project Flock wajib dipilih'), - kandang_id: yup.string().required('Kandang wajib dipilih'), -}); + area_id: yup + .mixed() + .required('Area wajib dipilih') + .test('is-not-empty', 'Area wajib dipilih', (value) => { + if (Array.isArray(value)) { + return value.length > 0; + } + return !!value; + }), + location_id: yup + .mixed() + .required('Lokasi wajib dipilih') + .test('is-not-empty', 'Lokasi wajib dipilih', (value) => { + if (Array.isArray(value)) { + return value.length > 0; + } + return !!value; + }), + project_flock_id: yup + .mixed() + .required('Project Flock wajib dipilih') + .test('is-not-empty', 'Project Flock wajib dipilih', (value) => { + if (Array.isArray(value)) { + return value.length > 0; + } + return !!value; + }), + kandang_id: yup + .mixed() + .required('Kandang wajib dipilih') + .test('is-not-empty', 'Kandang wajib dipilih', (value) => { + if (Array.isArray(value)) { + return value.length > 0; + } + return !!value; + }), +}) as yup.ObjectSchema; export type ProductionResultFilterValues = yup.InferType< typeof ProductionResultFilterSchema diff --git a/src/components/pages/report/production-result/tab/ProductionResultTab.tsx b/src/components/pages/report/production-result/tab/ProductionResultTab.tsx index 2d7915e8..090ca781 100644 --- a/src/components/pages/report/production-result/tab/ProductionResultTab.tsx +++ b/src/components/pages/report/production-result/tab/ProductionResultTab.tsx @@ -8,15 +8,15 @@ import toast from 'react-hot-toast'; import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import Dropdown from '@/components/dropdown/Dropdown'; -import SelectInput, { - OptionType, - useSelect, -} from '@/components/input/SelectInput'; +import SelectInput, { useSelect } from '@/components/input/SelectInput'; import Menu from '@/components/menu/Menu'; import MenuItem from '@/components/menu/MenuItem'; import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/ProductionResultProjectFlockKandangTable'; import { useFormik } from 'formik'; -import { ProductionResultFilterSchema } from '@/components/pages/report/production-result/filter/ProductionResultFilter'; +import { + ProductionResultFilterSchema, + type ProductionResultFilterValues, +} from '@/components/pages/report/production-result/filter/ProductionResultFilter'; import { BaseKandang } from '@/types/api/master-data/kandang'; import { AreaApi, LocationApi } from '@/services/api/master-data'; @@ -53,13 +53,6 @@ interface FilterParams { project_flock_kandang_id?: string; } -type ProductionResultFilterFormValues = { - area_id: OptionType | null; - location_id: OptionType | null; - project_flock_id: OptionType | null; - kandang_id: OptionType | null; -}; - const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => { // ===== STATE MANAGEMENT ===== const [isPdfExportLoading, setIsPdfExportLoading] = useState(false); @@ -213,7 +206,7 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => { ]; // ===== FORMIK SETUP ===== - const formik = useFormik({ + const formik = useFormik({ initialValues: { area_id: null, location_id: null, @@ -221,6 +214,8 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => { kandang_id: null, }, validationSchema: ProductionResultFilterSchema, + validateOnBlur: true, + validateOnChange: true, onSubmit: (values) => { setFilterParams({ area_id: values.area_id?.value @@ -723,7 +718,7 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => { {/* Modal Body */}
{ onInputChange={setAreaInputValue} onMenuScrollToBottom={loadMoreAreas} isClearable + isError={formik.touched.area_id && Boolean(formik.errors.area_id)} + errorMessage={formik.errors.area_id} className={{ wrapper: 'w-full' }} /> { onMenuScrollToBottom={loadMoreLocations} isClearable isDisabled={!formik.values.area_id} + isError={ + formik.touched.location_id && Boolean(formik.errors.location_id) + } + errorMessage={formik.errors.location_id} className={{ wrapper: 'w-full' }} /> { onMenuScrollToBottom={loadMoreProjectFlocks} isClearable isDisabled={!formik.values.location_id} + isError={ + formik.touched.project_flock_id && + Boolean(formik.errors.project_flock_id) + } + errorMessage={formik.errors.project_flock_id} className={{ wrapper: 'w-full' }} /> { onMenuScrollToBottom={loadMoreProjectFlockKandangs} isClearable isDisabled={!formik.values.project_flock_id} + isError={ + formik.touched.kandang_id && Boolean(formik.errors.kandang_id) + } + errorMessage={formik.errors.kandang_id} className={{ wrapper: 'w-full' }} />