refactor(FE): Refactor TransferToLayingFilterModal to use schema

validation
This commit is contained in:
rstubryan
2026-02-25 11:02:26 +07:00
parent 90942b41b9
commit e2e64f093f
3 changed files with 64 additions and 21 deletions
@@ -13,6 +13,10 @@ import { OptionType, useSelect } from '@/components/input/SelectInput';
import { ProjectFlockApi } from '@/services/api/production'; import { ProjectFlockApi } from '@/services/api/production';
import { Flock } from '@/types/api/master-data/flock'; import { Flock } from '@/types/api/master-data/flock';
import { TransferToLayingFilter } from '@/types/api/production/transfer-to-laying'; import { TransferToLayingFilter } from '@/types/api/production/transfer-to-laying';
import {
TransferToLayingFilterSchema,
TransferToLayingFilterValues,
} from '@/components/pages/production/transfer-to-laying/filter/TransferToLayingFilter';
interface TransferToLayingFilterModal { interface TransferToLayingFilterModal {
ref: RefObject<HTMLDialogElement | null>; ref: RefObject<HTMLDialogElement | null>;
@@ -49,13 +53,7 @@ const TransferToLayingFilterModal = ({
category: 'LAYING', category: 'LAYING',
}); });
const formik = useFormik<{ const formik = useFormik<TransferToLayingFilterValues>({
startDate: string;
endDate: string;
flockSource: { value: number; label: string }[];
flockDestination: { value: number; label: string }[];
status: { value: number; label: string }[];
}>({
initialValues: { initialValues: {
startDate: '', startDate: '',
endDate: '', endDate: '',
@@ -63,15 +61,22 @@ const TransferToLayingFilterModal = ({
flockDestination: [], flockDestination: [],
status: [], status: [],
}, },
validationSchema: TransferToLayingFilterSchema,
onSubmit: async (values) => { onSubmit: async (values) => {
const formattedValues = { const formattedValues = {
...values, ...values,
flockSource: values.flockSource.map((item) => item.value), flockSource: values.flockSource
flockDestination: values.flockDestination.map((item) => item.value), ? (values.flockSource as OptionType[]).map((item) => item.value)
status: values.status.map((item) => item.value), : [],
flockDestination: values.flockDestination
? (values.flockDestination as OptionType[]).map((item) => item.value)
: [],
status: values.status
? (values.status as OptionType[]).map((item) => item.value)
: [],
}; };
onSubmit?.(formattedValues); onSubmit?.(formattedValues as TransferToLayingFilter);
closeModalHandler(); closeModalHandler();
}, },
onReset: () => { onReset: () => {
@@ -81,17 +86,17 @@ const TransferToLayingFilterModal = ({
}); });
const flockSourceChangeHandler = (val: OptionType | OptionType[] | null) => { const flockSourceChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('flockSource', val as OptionType[]); formik.setFieldValue('flockSource', val);
}; };
const flockDestinationChangeHandler = ( const flockDestinationChangeHandler = (
val: OptionType | OptionType[] | null val: OptionType | OptionType[] | null
) => { ) => {
formik.setFieldValue('flockDestination', val as OptionType[]); formik.setFieldValue('flockDestination', val);
}; };
const statusChangeHandler = (val: OptionType | OptionType[] | null) => { const statusChangeHandler = (val: OptionType | OptionType[] | null) => {
formik.setFieldValue('status', val as OptionType[]); formik.setFieldValue('status', val);
}; };
return ( return (
@@ -132,7 +137,7 @@ const TransferToLayingFilterModal = ({
<DateInput <DateInput
name='startDate' name='startDate'
placeholder='Tanggal Awal' placeholder='Tanggal Awal'
value={formik.values.startDate} value={formik.values.startDate || ''}
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
/> />
@@ -140,16 +145,22 @@ const TransferToLayingFilterModal = ({
<DateInput <DateInput
name='endDate' name='endDate'
placeholder='Tanggal Akhir' placeholder='Tanggal Akhir'
value={formik.values.endDate} value={formik.values.endDate || ''}
onChange={formik.handleChange} onChange={formik.handleChange}
onBlur={formik.handleBlur} onBlur={formik.handleBlur}
isError={formik.touched.endDate && !!formik.errors.endDate}
/> />
</div> </div>
{formik.touched.endDate && formik.errors.endDate && (
<span className='text-xs text-error mt-1'>
{formik.errors.endDate}
</span>
)}
<SelectInputCheckbox <SelectInputCheckbox
label='Flock Asal' label='Flock Asal'
placeholder='Flock Asal' placeholder='Flock Asal'
value={formik.values.flockSource} value={formik.values.flockSource as OptionType[]}
onChange={flockSourceChangeHandler} onChange={flockSourceChangeHandler}
options={flockSourceOptions} options={flockSourceOptions}
isLoading={isLoadingFlockSourceOptions} isLoading={isLoadingFlockSourceOptions}
@@ -160,7 +171,7 @@ const TransferToLayingFilterModal = ({
<SelectInputCheckbox <SelectInputCheckbox
label='Flock Tujuan' label='Flock Tujuan'
placeholder='Flock Tujuan' placeholder='Flock Tujuan'
value={formik.values.flockDestination} value={formik.values.flockDestination as OptionType[]}
onChange={flockDestinationChangeHandler} onChange={flockDestinationChangeHandler}
options={flockDestinationOptions} options={flockDestinationOptions}
isLoading={isLoadingFlockDestinationOptions} isLoading={isLoadingFlockDestinationOptions}
@@ -176,7 +187,7 @@ const TransferToLayingFilterModal = ({
{ value: 'APPROVED', label: 'Disetujui' }, { value: 'APPROVED', label: 'Disetujui' },
{ value: 'REJECTED', label: 'Ditolak' }, { value: 'REJECTED', label: 'Ditolak' },
]} ]}
value={formik.values.status} value={formik.values.status as OptionType[]}
onChange={statusChangeHandler} onChange={statusChangeHandler}
/> />
</div> </div>
@@ -1,6 +1,6 @@
'use client'; 'use client';
import { ChangeEventHandler, useEffect, useMemo, useState } from 'react'; import { ChangeEventHandler, useEffect, useState } from 'react';
import useSWR from 'swr'; import useSWR from 'swr';
import { import {
CellContext, CellContext,
@@ -17,7 +17,6 @@ import { useModal } from '@/components/Modal';
import CheckboxInput from '@/components/input/CheckboxInput'; import CheckboxInput from '@/components/input/CheckboxInput';
import RequirePermission from '@/components/helper/RequirePermission'; import RequirePermission from '@/components/helper/RequirePermission';
import PopoverButton from '@/components/popover/PopoverButton'; import PopoverButton from '@/components/popover/PopoverButton';
import Badge from '@/components/Badge';
import PopoverContent from '@/components/popover/PopoverContent'; import PopoverContent from '@/components/popover/PopoverContent';
import Dropdown from '@/components/Dropdown'; import Dropdown from '@/components/Dropdown';
import StatusBadge from '@/components/helper/StatusBadge'; import StatusBadge from '@/components/helper/StatusBadge';
@@ -0,0 +1,33 @@
import * as yup from 'yup';
export type TransferToLayingFilterType = {
startDate: string | null;
endDate: string | null;
flockSource: number[];
flockDestination: number[];
status: string[];
};
export const TransferToLayingFilterSchema = yup.object({
startDate: yup.string().optional().nullable(),
endDate: yup
.string()
.optional()
.nullable()
.test(
'is-greater-than-start',
'Tanggal akhir tidak boleh masa lampau',
function (value) {
const { startDate } = this.parent;
if (!startDate || !value) return true;
return new Date(value) >= new Date(startDate);
}
),
flockSource: yup.array().optional().nullable(),
flockDestination: yup.array().optional().nullable(),
status: yup.array().optional().nullable(),
});
export type TransferToLayingFilterValues = yup.InferType<
typeof TransferToLayingFilterSchema
>;