fix: persist table filter state in master data

This commit is contained in:
ValdiANS
2026-04-29 15:10:41 +07:00
parent 29347c24f4
commit 46daed8fc4
17 changed files with 276 additions and 434 deletions
@@ -1,13 +1,6 @@
'use client';
import {
ChangeEventHandler,
useCallback,
useEffect,
useMemo,
useState,
} from 'react';
import { usePathname } from 'next/navigation';
import { ChangeEventHandler, useMemo, useState } from 'react';
import useSWR from 'swr';
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
import toast from 'react-hot-toast';
@@ -33,7 +26,6 @@ import { ProductApi, ProductCategoryApi } from '@/services/api/master-data';
import { formatCurrency } from '@/lib/helper';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { useUiStore } from '@/stores/ui/ui.store';
import {
ProductFilterSchema,
ProductFilterType,
@@ -119,25 +111,27 @@ const RowOptionsMenu = ({
};
const ProductsTable = () => {
const { searchValue, setSearchValue, setTableState } = useUiStore();
const pathname = usePathname();
const {
state: tableFilterState,
updateFilter,
setPage,
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
} = useTableFilter<{
search: string;
productCategoryFilter?: OptionType<string>;
}>({
initial: {
search: '',
productCategoryFilter: '',
productCategoryFilter: undefined,
},
paramMap: {
page: 'page',
pageSize: 'limit',
productCategoryFilter: 'product_category_id',
},
persist: true,
storeName: 'product-table',
});
// ===== FILTER MODAL STATE =====
@@ -146,19 +140,32 @@ const ProductsTable = () => {
// ===== FORMIK SETUP =====
const formik = useFormik<ProductFilterType>({
initialValues: {
product_category_id: null,
product_category: tableFilterState.productCategoryFilter,
},
validationSchema: ProductFilterSchema,
onSubmit: (values, { setSubmitting }) => {
updateFilter('productCategoryFilter', values.product_category_id || '');
updateFilter(
'productCategoryFilter',
values.product_category || undefined,
true
);
filterModal.closeModal();
setSubmitting(false);
},
onReset: () => {
updateFilter('productCategoryFilter', '');
},
});
const formikResetHandler = () => {
updateFilter('productCategoryFilter', undefined, true);
formik.resetForm({
values: {
product_category: undefined,
},
});
filterModal.closeModal();
};
// ===== PRODUCT CATEGORY OPTIONS =====
const {
setInputValue: setProductCategoryInputValue,
@@ -173,25 +180,11 @@ const ProductsTable = () => {
);
// ===== FILTER HANDLERS =====
const handleFilterProductCategoryChange = useCallback(
(val: OptionType | OptionType[] | null) => {
const category = val as OptionType | null;
const categoryId = category?.value ? String(category.value) : null;
formik.setFieldValue('product_category_id', categoryId);
},
[formik]
);
// ===== FILTER HELPERS =====
const productCategoryIdValue = useMemo(() => {
if (!formik.values.product_category_id) return null;
return (
productCategoryOptions.find(
(opt) => String(opt.value) === formik.values.product_category_id
) || null
);
}, [formik.values.product_category_id, productCategoryOptions]);
const handleFilterProductCategoryChange = (
val: OptionType | OptionType[] | null
) => {
formik.setFieldValue('product_category', val);
};
// ===== HANDLE FILTER MODAL OPEN =====
const handleFilterModalOpen = () => {
@@ -199,10 +192,6 @@ const ProductsTable = () => {
formik.validateForm();
};
useEffect(() => {
updateFilter('search', searchValue);
}, [searchValue, updateFilter]);
const [sorting, setSorting] = useState<SortingState>([]);
const {
@@ -220,13 +209,8 @@ const ProductsTable = () => {
);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
useEffect(() => {
setTableState('product-table', pathname);
}, [pathname, setTableState]);
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
setSearchValue(e.target.value);
updateFilter('search', e.target.value);
updateFilter('search', e.target.value, true);
};
const confirmationModalDeleteClickHandler = async () => {
@@ -477,13 +461,13 @@ const ProductsTable = () => {
<Icon icon='heroicons:x-mark' width={20} height={20} />
</Button>
</div>
<form onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
<form onSubmit={formik.handleSubmit} onReset={formikResetHandler}>
<div className='p-4 flex flex-col gap-1.5'>
<SelectInput
label='Kategori Produk'
placeholder='Pilih Kategori Produk'
options={productCategoryOptions}
value={productCategoryIdValue}
value={formik.values.product_category}
onChange={handleFilterProductCategoryChange}
onInputChange={setProductCategoryInputValue}
isLoading={isLoadingProductCategoryOptions}
@@ -499,10 +483,7 @@ const ProductsTable = () => {
type='button'
variant='soft'
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
onClick={() => {
formik.resetForm();
filterModal.closeModal();
}}
onClick={formikResetHandler}
>
Reset Filter
</Button>