diff --git a/src/components/pages/expense/ExpensesTable.tsx b/src/components/pages/expense/ExpensesTable.tsx index 61fa7fa6..83b8015f 100644 --- a/src/components/pages/expense/ExpensesTable.tsx +++ b/src/components/pages/expense/ExpensesTable.tsx @@ -51,7 +51,9 @@ type ExpenseTableFilters = { transactionDate: string; realizationDate: string; locationId: string; + locationName: string; vendorId: string; + vendorName: string; userId: string; }; @@ -235,6 +237,7 @@ const ExpensesTable = () => { setPage, setPageSize, toQueryString: getTableFilterQueryString, + reset: resetFilter, } = useTableFilter({ initial: { page: 1, @@ -244,7 +247,9 @@ const ExpensesTable = () => { transactionDate: '', realizationDate: '', locationId: '', + locationName: '', vendorId: '', + vendorName: '', userId: '', }, paramMap: { @@ -254,7 +259,9 @@ const ExpensesTable = () => { transactionDate: 'transaction_date', realizationDate: 'realization_date', locationId: 'location_id', + locationName: 'location_name', vendorId: 'vendor_id', + vendorName: 'vendor_name', userId: 'user_id', }, @@ -740,20 +747,31 @@ const ExpensesTable = () => { const handleFilterSubmit = (values: { transaction_date?: string | null; realization_date?: string | null; - location_id?: string | null; - vendor_id?: string | null; + location?: { value: number; label: string } | null; + vendor?: { value: number; label: string } | null; }) => { updateFilter('transactionDate', values.transaction_date || ''); updateFilter('realizationDate', values.realization_date || ''); - updateFilter('locationId', values.location_id || ''); - updateFilter('vendorId', values.vendor_id || ''); + updateFilter( + 'locationId', + values.location?.value ? String(values.location?.value) : '' + ); + updateFilter( + 'locationName', + values.location?.label ? String(values.location?.label) : '' + ); + updateFilter( + 'vendorId', + values.vendor?.value ? String(values.vendor?.value) : '' + ); + updateFilter( + 'vendorName', + values.vendor?.label ? String(values.vendor?.label) : '' + ); }; const handleFilterReset = () => { - updateFilter('transactionDate', ''); - updateFilter('realizationDate', ''); - updateFilter('locationId', ''); - updateFilter('vendorId', ''); + resetFilter(); }; // track sorting @@ -927,6 +945,8 @@ const ExpensesTable = () => { 'search', 'nameSort', 'userId', + 'locationName', + 'vendorName', ]} onClick={handleFilterModalOpen} className='px-3 py-2.5' @@ -1245,6 +1265,24 @@ const ExpensesTable = () => { ref={filterModal.ref} onSubmit={handleFilterSubmit} onReset={handleFilterReset} + initialValues={{ + location: + tableFilterState.locationId && tableFilterState.locationName + ? { + value: Number(tableFilterState.locationId), + label: tableFilterState.locationName, + } + : null, + vendor: + tableFilterState.vendorId && tableFilterState.vendorName + ? { + value: Number(tableFilterState.vendorId), + label: tableFilterState.vendorName, + } + : null, + realization_date: tableFilterState.realizationDate, + transaction_date: tableFilterState.transactionDate, + }} /> ); diff --git a/src/components/pages/expense/filter/ExpensesFilter.ts b/src/components/pages/expense/filter/ExpensesFilter.ts index 8ee14a90..703863ea 100644 --- a/src/components/pages/expense/filter/ExpensesFilter.ts +++ b/src/components/pages/expense/filter/ExpensesFilter.ts @@ -3,8 +3,8 @@ import * as yup from 'yup'; export type ExpensesFilterType = { transaction_date: string | null; realization_date: string | null; - location_id: string | null; - vendor_id: string | null; + location: { value: number; label: string } | null; + vendor: { value: number; label: string } | null; }; export const ExpensesFilterSchema = yup.object({ @@ -21,8 +21,18 @@ export const ExpensesFilterSchema = yup.object({ return new Date(value) >= new Date(transaction_date); } ), - location_id: yup.string().nullable(), - vendor_id: yup.string().nullable(), + location: yup + .object({ + value: yup.number().required(), + label: yup.string().required(), + }) + .nullable(), + vendor: yup + .object({ + value: yup.number().required(), + label: yup.string().required(), + }) + .nullable(), }); export type ExpensesFilterValues = yup.InferType; diff --git a/src/components/pages/expense/filter/ExpensesFilterModal.tsx b/src/components/pages/expense/filter/ExpensesFilterModal.tsx index 1885785f..67e4b0ac 100644 --- a/src/components/pages/expense/filter/ExpensesFilterModal.tsx +++ b/src/components/pages/expense/filter/ExpensesFilterModal.tsx @@ -1,6 +1,6 @@ 'use client'; -import { RefObject } from 'react'; +import { RefObject, useCallback } from 'react'; import { useFormik } from 'formik'; import { Icon } from '@iconify/react'; @@ -39,54 +39,51 @@ const ExpensesFilterModal = ({ setInputValue: setLocationInputValue, options: locationOptions, isLoadingOptions: isLoadingLocationOptions, + loadMore: loadMoreLocations, } = useSelect(LocationApi.basePath, 'id', 'name'); const { setInputValue: setVendorInputValue, options: vendorOptions, isLoadingOptions: isLoadingVendorOptions, + loadMore: loadMoreVendors, } = useSelect(SupplierApi.basePath, 'id', 'name'); const formik = useFormik({ initialValues: initialValues || { transaction_date: null, realization_date: null, - location_id: null, - vendor_id: null, + location: null, + vendor: null, }, validationSchema: ExpensesFilterSchema, onSubmit: async (values) => { onSubmit?.(values); closeModalHandler(); }, - onReset: () => { - onReset?.(); - closeModalHandler(); - }, }); - const locationValue = formik.values.location_id - ? locationOptions.find( - (opt) => String(opt.value) === formik.values.location_id - ) || null - : null; + const { resetForm } = formik; - const vendorValue = formik.values.vendor_id - ? vendorOptions.find( - (opt) => String(opt.value) === formik.values.vendor_id - ) || null - : null; + const formikResetHandler = useCallback(() => { + resetForm({ + values: { + transaction_date: null, + realization_date: null, + location: null, + vendor: null, + }, + }); + onReset?.(); + closeModalHandler(); + }, [resetForm, onReset, closeModalHandler]); const locationChangeHandler = (val: OptionType | OptionType[] | null) => { - const locationId = - val && !Array.isArray(val) ? (String(val.value) as string) : null; - formik.setFieldValue('location_id', locationId); + formik.setFieldValue('location', val as OptionType | null); }; const vendorChangeHandler = (val: OptionType | OptionType[] | null) => { - const vendorId = - val && !Array.isArray(val) ? (String(val.value) as string) : null; - formik.setFieldValue('vendor_id', vendorId); + formik.setFieldValue('vendor', val as OptionType | null); }; return ( @@ -98,7 +95,7 @@ const ExpensesFilterModal = ({ >
{/* Modal Header */} @@ -160,10 +157,11 @@ const ExpensesFilterModal = ({ label='Lokasi' placeholder='Pilih Lokasi' options={locationOptions} - value={locationValue} + value={formik.values.location} onChange={locationChangeHandler} onInputChange={setLocationInputValue} isLoading={isLoadingLocationOptions} + onMenuScrollToBottom={loadMoreLocations} isClearable isSearchable={true} className={{ wrapper: 'w-full' }} @@ -173,10 +171,11 @@ const ExpensesFilterModal = ({ label='Vendor' placeholder='Pilih Vendor' options={vendorOptions} - value={vendorValue} + value={formik.values.vendor} onChange={vendorChangeHandler} onInputChange={setVendorInputValue} isLoading={isLoadingVendorOptions} + onMenuScrollToBottom={loadMoreVendors} isClearable isSearchable={true} className={{ wrapper: 'w-full' }} diff --git a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx index 1fdb1e65..5e6844f3 100644 --- a/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx +++ b/src/components/pages/purchase/form/request/PurchaseRequestForm.tsx @@ -55,7 +55,6 @@ const PurchaseRequestForm = ({ const deleteModal = useModal(); const [isDeleteLoading, setIsDeleteLoading] = useState(false); - const [, setLocationSelectInputValue] = useState(''); const [selectedPurchaseItems, setSelectedPurchaseItems] = useState( [] ); @@ -163,6 +162,7 @@ const PurchaseRequestForm = ({ options: locationOptions, isLoadingOptions: isLoadingLocations, loadMore: loadMoreLocations, + setInputValue: setLocationSelectInputValue, } = useSelect(LocationApi.basePath, 'id', 'name', '', { area_id: selectedArea != ''