refactor(FE): Refactor filter schema and form handling for

PurchasesPerSupplier
This commit is contained in:
rstubryan
2026-02-12 10:55:40 +07:00
parent e23b53d797
commit 322b519def
2 changed files with 106 additions and 141 deletions
@@ -1,19 +1,17 @@
import { OptionType } from '@/components/input/SelectInput';
import * as yup from 'yup'; import * as yup from 'yup';
export type PurchasesPerSupplierFilterType = { export type PurchasesPerSupplierFilterType = {
start_date: string | null | undefined; start_date: string | null;
end_date: string | null | undefined; end_date: string | null;
area_ids: OptionType[] | null | undefined; area_ids: string | null;
supplier_ids: OptionType[] | null | undefined; supplier_ids: string | null;
product_ids: OptionType[] | null | undefined; product_ids: string | null;
product_category_ids: OptionType[] | null | undefined; product_category_ids: string | null;
filter_by: OptionType | null | undefined; filter_by: string | null;
sort_by: OptionType | null | undefined; sort_by: string | null;
}; };
export const PurchasesPerSupplierFilterSchema: yup.ObjectSchema<PurchasesPerSupplierFilterType> = export const PurchasesPerSupplierFilterSchema = yup.object({
yup.object({
start_date: yup.string().optional().nullable(), start_date: yup.string().optional().nullable(),
end_date: yup end_date: yup
.string() .string()
@@ -28,61 +26,13 @@ export const PurchasesPerSupplierFilterSchema: yup.ObjectSchema<PurchasesPerSupp
return new Date(value) >= new Date(start_date); return new Date(value) >= new Date(start_date);
} }
), ),
area_ids: yup area_ids: yup.string().nullable(),
.array() supplier_ids: yup.string().nullable(),
.of( product_ids: yup.string().nullable(),
yup.object({ product_category_ids: yup.string().nullable(),
value: yup.mixed<string | number>().required(), filter_by: yup.string().nullable(),
label: yup.string().required(), sort_by: yup.string().nullable(),
}) });
)
.optional()
.nullable(),
supplier_ids: yup
.array()
.of(
yup.object({
value: yup.mixed<string | number>().required(),
label: yup.string().required(),
})
)
.optional()
.nullable(),
product_ids: yup
.array()
.of(
yup.object({
value: yup.mixed<string | number>().required(),
label: yup.string().required(),
})
)
.optional()
.nullable(),
product_category_ids: yup
.array()
.of(
yup.object({
value: yup.mixed<string | number>().required(),
label: yup.string().required(),
})
)
.optional()
.nullable(),
filter_by: yup
.object({
value: yup.mixed<string | number>().required(),
label: yup.string().required(),
})
.optional()
.nullable(),
sort_by: yup
.object({
value: yup.mixed<string | number>().required(),
label: yup.string().required(),
})
.optional()
.nullable(),
});
export type PurchasesPerSupplierFilterValues = yup.InferType< export type PurchasesPerSupplierFilterValues = yup.InferType<
typeof PurchasesPerSupplierFilterSchema typeof PurchasesPerSupplierFilterSchema
@@ -125,21 +125,14 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
validationSchema: PurchasesPerSupplierFilterSchema, validationSchema: PurchasesPerSupplierFilterSchema,
onSubmit: (values, { setSubmitting }) => { onSubmit: (values, { setSubmitting }) => {
setFilterParams({ setFilterParams({
start_date: values.start_date?.toString() || undefined, start_date: values.start_date || undefined,
end_date: values.end_date?.toString() || undefined, end_date: values.end_date || undefined,
area_id: area_id: values.area_ids || undefined,
values.area_ids?.map((v) => String(v.value)).join(',') || undefined, supplier_id: values.supplier_ids || undefined,
supplier_id: product_id: values.product_ids || undefined,
values.supplier_ids?.map((v) => String(v.value)).join(',') || product_category_id: values.product_category_ids || undefined,
undefined, filter_by: values.filter_by || undefined,
product_id: sort_by: values.sort_by || undefined,
values.product_ids?.map((v) => String(v.value)).join(',') ||
undefined,
product_category_id:
values.product_category_ids?.map((v) => String(v.value)).join(',') ||
undefined,
filter_by: values.filter_by?.value?.toString() || undefined,
sort_by: values.sort_by?.value?.toString() || undefined,
}); });
filterModal.closeModal(); filterModal.closeModal();
setIsSubmitted(true); setIsSubmitted(true);
@@ -220,6 +213,48 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
[formik, dateErrorShown] [formik, dateErrorShown]
); );
// ===== DERIVED VALUES =====
const areaIdsValue = useMemo(() => {
if (!formik.values.area_ids) return [];
const ids = formik.values.area_ids.split(',');
return areaOptions.filter((opt) => ids.includes(String(opt.value)));
}, [formik.values.area_ids, areaOptions]);
const supplierIdsValue = useMemo(() => {
if (!formik.values.supplier_ids) return [];
const ids = formik.values.supplier_ids.split(',');
return supplierOptions.filter((opt) => ids.includes(String(opt.value)));
}, [formik.values.supplier_ids, supplierOptions]);
const productIdsValue = useMemo(() => {
if (!formik.values.product_ids) return [];
const ids = formik.values.product_ids.split(',');
return productOptions.filter((opt) => ids.includes(String(opt.value)));
}, [formik.values.product_ids, productOptions]);
const productCategoryIdsValue = useMemo(() => {
if (!formik.values.product_category_ids) return [];
const ids = formik.values.product_category_ids.split(',');
return productCategoryOptions.filter((opt) =>
ids.includes(String(opt.value))
);
}, [formik.values.product_category_ids, productCategoryOptions]);
const filterByValue = useMemo(() => {
if (!formik.values.filter_by) return null;
return (
dataTypeOptions.find((opt) => opt.value === formik.values.filter_by) ||
null
);
}, [formik.values.filter_by, dataTypeOptions]);
const sortByValue = useMemo(() => {
if (!formik.values.sort_by) return null;
return (
sortByOptions.find((opt) => opt.value === formik.values.sort_by) || null
);
}, [formik.values.sort_by, sortByOptions]);
// ===== ACTIVE FILTERS COUNT ===== // ===== ACTIVE FILTERS COUNT =====
const activeFiltersCount = useMemo(() => { const activeFiltersCount = useMemo(() => {
let count = 0; let count = 0;
@@ -875,17 +910,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Area' label='Area'
placeholder='Pilih Area' placeholder='Pilih Area'
options={areaOptions} options={areaOptions}
value={ value={areaIdsValue}
(formik.values.area_ids as
| { value: number; label: string }
| { value: number; label: string }[]
| null
| undefined) || []
}
onChange={(val) => { onChange={(val) => {
formik.setFieldValue( formik.setFieldValue(
'area_ids', 'area_ids',
Array.isArray(val) ? val : val ? [val] : null Array.isArray(val) && val.length > 0
? val.map((v) => String(v.value)).join(',')
: null
); );
}} }}
isLoading={isLoadingAreas} isLoading={isLoadingAreas}
@@ -898,17 +929,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Supplier' label='Supplier'
placeholder='Pilih Supplier' placeholder='Pilih Supplier'
options={supplierOptions} options={supplierOptions}
value={ value={supplierIdsValue}
(formik.values.supplier_ids as
| { value: number; label: string }
| { value: number; label: string }[]
| null
| undefined) || []
}
onChange={(val) => { onChange={(val) => {
formik.setFieldValue( formik.setFieldValue(
'supplier_ids', 'supplier_ids',
Array.isArray(val) ? val : val ? [val] : null Array.isArray(val) && val.length > 0
? val.map((v) => String(v.value)).join(',')
: null
); );
}} }}
isLoading={isLoadingSuppliers} isLoading={isLoadingSuppliers}
@@ -921,17 +948,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Produk' label='Produk'
placeholder='Pilih Produk' placeholder='Pilih Produk'
options={productOptions} options={productOptions}
value={ value={productIdsValue}
(formik.values.product_ids as
| { value: number; label: string }
| { value: number; label: string }[]
| null
| undefined) || []
}
onChange={(val) => { onChange={(val) => {
formik.setFieldValue( formik.setFieldValue(
'product_ids', 'product_ids',
Array.isArray(val) ? val : val ? [val] : null Array.isArray(val) && val.length > 0
? val.map((v) => String(v.value)).join(',')
: null
); );
}} }}
isLoading={isLoadingProducts} isLoading={isLoadingProducts}
@@ -944,17 +967,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Kategori Produk' label='Kategori Produk'
placeholder='Pilih Kategori Produk' placeholder='Pilih Kategori Produk'
options={productCategoryOptions} options={productCategoryOptions}
value={ value={productCategoryIdsValue}
(formik.values.product_category_ids as
| { value: number; label: string }
| { value: number; label: string }[]
| null
| undefined) || []
}
onChange={(val) => { onChange={(val) => {
formik.setFieldValue( formik.setFieldValue(
'product_category_ids', 'product_category_ids',
Array.isArray(val) ? val : val ? [val] : null Array.isArray(val) && val.length > 0
? val.map((v) => String(v.value)).join(',')
: null
); );
}} }}
isLoading={isLoadingProductCategories} isLoading={isLoadingProductCategories}
@@ -967,15 +986,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Filter Berdasarkan' label='Filter Berdasarkan'
placeholder='Pilih Filter Berdasarkan' placeholder='Pilih Filter Berdasarkan'
options={dataTypeOptions} options={dataTypeOptions}
value={ value={filterByValue}
(formik.values.filter_by as
| { value: string; label: string }
| null
| undefined) || null
}
onChange={(val) => { onChange={(val) => {
if (!Array.isArray(val)) { if (!Array.isArray(val)) {
formik.setFieldValue('filter_by', val); formik.setFieldValue(
'filter_by',
val?.value?.toString() || null
);
} }
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}
@@ -987,15 +1004,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
label='Urutkan Berdasarkan' label='Urutkan Berdasarkan'
placeholder='Pilih Urutkan Berdasarkan' placeholder='Pilih Urutkan Berdasarkan'
options={sortByOptions} options={sortByOptions}
value={ value={sortByValue}
(formik.values.sort_by as
| { value: string; label: string }
| null
| undefined) || null
}
onChange={(val) => { onChange={(val) => {
if (!Array.isArray(val)) { if (!Array.isArray(val)) {
formik.setFieldValue('sort_by', val); formik.setFieldValue(
'sort_by',
val?.value?.toString() || null
);
} }
}} }}
className={{ wrapper: 'w-full' }} className={{ wrapper: 'w-full' }}