mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-06-21 13:48:46 +00:00
adjust filter po
This commit is contained in:
@@ -0,0 +1,521 @@
|
||||
'use client';
|
||||
|
||||
import {
|
||||
ChangeEventHandler,
|
||||
useState,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { useFormik } from 'formik';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
import { Icon } from '@iconify/react';
|
||||
import Button from '@/components/Button';
|
||||
import DateInput from '@/components/input/DateInput';
|
||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||||
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
|
||||
import SelectInput from '@/components/input/SelectInput';
|
||||
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
||||
|
||||
import { OptionType, useSelect } from '@/components/input/SelectInput';
|
||||
import { PurchaseFilter } from '@/types/api/purchase/purchase';
|
||||
import { AreaApi, LocationApi, SupplierApi } from '@/services/api/master-data';
|
||||
import { ProductCategory } from '@/types/api/master-data/product-category';
|
||||
import { ProductCategoryApi } from '@/services/api/master-data';
|
||||
import { Area } from '@/types/api/master-data/area';
|
||||
import { Location } from '@/types/api/master-data/location';
|
||||
import { Supplier } from '@/types/api/master-data/supplier';
|
||||
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
|
||||
import { ProjectFlockApi } from '@/services/api/production';
|
||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||
import { isResponseSuccess } from '@/lib/api-helper';
|
||||
|
||||
const filterByOptions: OptionType<string>[] = [
|
||||
{ value: 'po_date', label: 'Tanggal PO' },
|
||||
{ value: 'received_date', label: 'Tanggal Terima' },
|
||||
{ value: 'due_date', label: 'Tanggal Jatuh Tempo' },
|
||||
{ value: 'created_at', label: 'Tanggal Dibuat' },
|
||||
];
|
||||
|
||||
interface PurchaseInlineFilterProps {
|
||||
initialValues?: {
|
||||
poDate: string;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
filterBy: OptionType<string> | undefined;
|
||||
category: OptionType<number>[];
|
||||
status: OptionType<string>[];
|
||||
supplier: OptionType<number> | null;
|
||||
area: OptionType<number> | null;
|
||||
location: OptionType<number> | null;
|
||||
project_flock: OptionType<number> | null;
|
||||
project_flock_kandang: OptionType<number> | null;
|
||||
};
|
||||
searchValue?: string;
|
||||
onSearchChange?: ChangeEventHandler<HTMLInputElement>;
|
||||
onSubmit?: (values: PurchaseFilter) => void;
|
||||
onReset?: () => void;
|
||||
}
|
||||
|
||||
const PurchaseInlineFilter = ({
|
||||
initialValues,
|
||||
searchValue,
|
||||
onSearchChange,
|
||||
onSubmit,
|
||||
onReset,
|
||||
}: PurchaseInlineFilterProps) => {
|
||||
const [hasDateError, setHasDateError] = useState(false);
|
||||
const [dateErrorShown, setDateErrorShown] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
}
|
||||
};
|
||||
}, [dateErrorShown]);
|
||||
|
||||
const {
|
||||
setInputValue: setProductCategoryInputValue,
|
||||
options: productCategoryOptions,
|
||||
isLoadingOptions: isLoadingProductCategoryOptions,
|
||||
loadMore: loadMoreProductCategory,
|
||||
} = useSelect<ProductCategory>(
|
||||
ProductCategoryApi.basePath,
|
||||
'id',
|
||||
'name',
|
||||
'search'
|
||||
);
|
||||
|
||||
const [selectedAreaId, setSelectedAreaId] = useState(
|
||||
initialValues?.area?.value ? String(initialValues.area.value) : ''
|
||||
);
|
||||
const [selectedLocationId, setSelectedLocationId] = useState(
|
||||
initialValues?.location?.value ? String(initialValues.location.value) : ''
|
||||
);
|
||||
|
||||
const {
|
||||
setInputValue: setSupplierInputValue,
|
||||
options: supplierOptions,
|
||||
isLoadingOptions: isLoadingSupplierOptions,
|
||||
loadMore: loadMoreSuppliers,
|
||||
} = useSelect<Supplier>(SupplierApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
setInputValue: setAreaInputValue,
|
||||
options: areaOptions,
|
||||
isLoadingOptions: isLoadingAreaOptions,
|
||||
loadMore: loadMoreAreas,
|
||||
} = useSelect<Area>(AreaApi.basePath, 'id', 'name', 'search');
|
||||
|
||||
const {
|
||||
setInputValue: setLocationInputValue,
|
||||
options: locationOptions,
|
||||
isLoadingOptions: isLoadingLocationOptions,
|
||||
loadMore: loadMoreLocations,
|
||||
} = useSelect<Location>(LocationApi.basePath, 'id', 'name', 'search', {
|
||||
area_id: selectedAreaId || '',
|
||||
});
|
||||
|
||||
const {
|
||||
setInputValue: setProjectFlockInputValue,
|
||||
options: projectFlockOptions,
|
||||
rawData: projectFlocksRawData,
|
||||
isLoadingOptions: isLoadingProjectFlockOptions,
|
||||
loadMore: loadMoreProjectFlocks,
|
||||
} = useSelect<ProjectFlock>(
|
||||
ProjectFlockApi.basePath,
|
||||
'id',
|
||||
'flock_name',
|
||||
'search',
|
||||
{
|
||||
location_id: selectedLocationId || '',
|
||||
}
|
||||
);
|
||||
|
||||
const formik = useFormik<{
|
||||
poDate: string;
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
filterBy: OptionType<string> | undefined;
|
||||
category: { label: string; value: number }[];
|
||||
status: { label: string; value: string }[];
|
||||
supplier: OptionType<number> | null;
|
||||
area: OptionType<number> | null;
|
||||
location: OptionType<number> | null;
|
||||
project_flock: OptionType<number> | null;
|
||||
project_flock_kandang: OptionType<number> | null;
|
||||
}>({
|
||||
initialValues: initialValues || {
|
||||
poDate: '',
|
||||
start_date: '',
|
||||
end_date: '',
|
||||
filterBy: undefined,
|
||||
category: [],
|
||||
status: [],
|
||||
supplier: null,
|
||||
area: null,
|
||||
location: null,
|
||||
project_flock: null,
|
||||
project_flock_kandang: null,
|
||||
},
|
||||
onSubmit: async (values) => {
|
||||
const formattedValues = {
|
||||
...values,
|
||||
category: values.category.map((item) => String(item.value)),
|
||||
category_labels: values.category,
|
||||
status: values.status.map((item) => String(item.value)),
|
||||
supplier_id: values.supplier?.value,
|
||||
supplier_label: values.supplier?.label,
|
||||
area_id: values.area?.value,
|
||||
area_label: values.area?.label,
|
||||
location_id: values.location?.value,
|
||||
location_label: values.location?.label,
|
||||
project_flock_id: values.project_flock?.value,
|
||||
project_flock_label: values.project_flock?.label,
|
||||
project_flock_kandang_id: values.project_flock_kandang?.value,
|
||||
project_flock_kandang_label: values.project_flock_kandang?.label,
|
||||
};
|
||||
|
||||
onSubmit?.(formattedValues);
|
||||
},
|
||||
});
|
||||
|
||||
const { resetForm, submitForm } = formik;
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedAreaId(
|
||||
initialValues?.area?.value ? String(initialValues.area.value) : ''
|
||||
);
|
||||
setSelectedLocationId(
|
||||
initialValues?.location?.value ? String(initialValues.location.value) : ''
|
||||
);
|
||||
}, [initialValues?.area, initialValues?.location]);
|
||||
|
||||
const projectFlockKandangOptions = useMemo(() => {
|
||||
if (
|
||||
!formik.values.project_flock ||
|
||||
!projectFlocksRawData ||
|
||||
!isResponseSuccess(projectFlocksRawData)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const selectedProjectFlock = projectFlocksRawData.data.find(
|
||||
(item) => item.id === formik.values.project_flock?.value
|
||||
);
|
||||
|
||||
return (
|
||||
selectedProjectFlock?.kandangs?.map((item) => ({
|
||||
value: item.project_flock_kandang_id,
|
||||
label: item.name,
|
||||
})) || []
|
||||
);
|
||||
}, [formik.values.project_flock, projectFlocksRawData]);
|
||||
|
||||
const productCategoryChangeHandler = (
|
||||
val: OptionType | OptionType[] | null
|
||||
) => {
|
||||
formik.setFieldValue('category', val);
|
||||
};
|
||||
|
||||
const statusChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
formik.setFieldValue('status', val);
|
||||
};
|
||||
|
||||
const formikResetHandler = useCallback(() => {
|
||||
setHasDateError(false);
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
resetForm({
|
||||
values: {
|
||||
poDate: '',
|
||||
start_date: '',
|
||||
end_date: '',
|
||||
filterBy: undefined,
|
||||
category: [],
|
||||
status: [],
|
||||
supplier: null,
|
||||
area: null,
|
||||
location: null,
|
||||
project_flock: null,
|
||||
project_flock_kandang: null,
|
||||
},
|
||||
});
|
||||
setSelectedAreaId('');
|
||||
setSelectedLocationId('');
|
||||
onReset?.();
|
||||
}, [resetForm, onReset, dateErrorShown]);
|
||||
|
||||
const handleStartDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
formik.setFieldValue('start_date', value);
|
||||
|
||||
if (value && formik.values.end_date) {
|
||||
if (new Date(formik.values.end_date) < new Date(value)) {
|
||||
setHasDateError(true);
|
||||
if (!dateErrorShown) {
|
||||
toast.error('Tanggal akhir tidak boleh sebelum tanggal mulai', {
|
||||
duration: Infinity,
|
||||
});
|
||||
setDateErrorShown(true);
|
||||
}
|
||||
} else {
|
||||
setHasDateError(false);
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setHasDateError(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEndDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value;
|
||||
formik.setFieldValue('end_date', value);
|
||||
|
||||
if (value && formik.values.start_date) {
|
||||
if (new Date(value) < new Date(formik.values.start_date)) {
|
||||
setHasDateError(true);
|
||||
if (!dateErrorShown) {
|
||||
toast.error('Tanggal akhir tidak boleh sebelum tanggal mulai', {
|
||||
duration: Infinity,
|
||||
});
|
||||
setDateErrorShown(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setHasDateError(false);
|
||||
if (dateErrorShown) {
|
||||
toast.dismiss();
|
||||
setDateErrorShown(false);
|
||||
}
|
||||
};
|
||||
|
||||
const formikSubmitHandler = useCallback(async () => {
|
||||
await submitForm();
|
||||
}, [submitForm]);
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={formik.handleSubmit}
|
||||
onReset={formikResetHandler}
|
||||
className='w-full p-4 border-b border-base-content/10'
|
||||
>
|
||||
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-x-4 gap-y-1'>
|
||||
{/* Row 1: Tanggal Awal, Tanggal Akhir, Filter Berdasarkan, PO Date */}
|
||||
<DateInput
|
||||
label='Tanggal Awal'
|
||||
name='start_date'
|
||||
placeholder='Pilih tanggal'
|
||||
value={formik.values.start_date}
|
||||
onChange={handleStartDateChange}
|
||||
/>
|
||||
|
||||
<DateInput
|
||||
label='Tanggal Akhir'
|
||||
name='end_date'
|
||||
placeholder='Pilih tanggal'
|
||||
value={formik.values.end_date}
|
||||
onChange={handleEndDateChange}
|
||||
isError={hasDateError}
|
||||
/>
|
||||
|
||||
<SelectInputRadio
|
||||
label='Filter Berdasarkan'
|
||||
placeholder='Pilih Filter Berdasarkan'
|
||||
options={filterByOptions}
|
||||
value={formik.values.filterBy ?? null}
|
||||
onChange={(val) =>
|
||||
formik.setFieldValue(
|
||||
'filterBy',
|
||||
!Array.isArray(val) ? (val ?? undefined) : undefined
|
||||
)
|
||||
}
|
||||
isClearable
|
||||
/>
|
||||
|
||||
<DateInput
|
||||
label='PO Date'
|
||||
name='poDate'
|
||||
placeholder='Pilih Tanggal'
|
||||
value={formik.values.poDate}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
|
||||
{/* Row 2: Area, Lokasi, Project Flock, Kandang */}
|
||||
<SelectInput
|
||||
label='Area'
|
||||
placeholder='Pilih Area'
|
||||
value={formik.values.area}
|
||||
onChange={(val) => {
|
||||
const nextValue = !Array.isArray(val)
|
||||
? (val as OptionType<number> | null)
|
||||
: null;
|
||||
formik.setFieldValue('area', nextValue);
|
||||
formik.setFieldValue('location', null);
|
||||
formik.setFieldValue('project_flock', null);
|
||||
formik.setFieldValue('project_flock_kandang', null);
|
||||
setSelectedAreaId(nextValue?.value ? String(nextValue.value) : '');
|
||||
setSelectedLocationId('');
|
||||
}}
|
||||
options={areaOptions}
|
||||
isLoading={isLoadingAreaOptions}
|
||||
onInputChange={setAreaInputValue}
|
||||
onMenuScrollToBottom={loadMoreAreas}
|
||||
isClearable
|
||||
/>
|
||||
|
||||
<SelectInput
|
||||
label='Lokasi'
|
||||
placeholder='Pilih Lokasi'
|
||||
value={formik.values.location}
|
||||
onChange={(val) => {
|
||||
const nextValue = !Array.isArray(val)
|
||||
? (val as OptionType<number> | null)
|
||||
: null;
|
||||
formik.setFieldValue('location', nextValue);
|
||||
formik.setFieldValue('project_flock', null);
|
||||
formik.setFieldValue('project_flock_kandang', null);
|
||||
setSelectedLocationId(
|
||||
nextValue?.value ? String(nextValue.value) : ''
|
||||
);
|
||||
}}
|
||||
options={locationOptions}
|
||||
isLoading={isLoadingLocationOptions}
|
||||
onInputChange={setLocationInputValue}
|
||||
onMenuScrollToBottom={loadMoreLocations}
|
||||
isClearable
|
||||
isDisabled={!formik.values.area}
|
||||
/>
|
||||
|
||||
<SelectInput
|
||||
label='Project Flock'
|
||||
placeholder='Pilih Project Flock'
|
||||
value={formik.values.project_flock}
|
||||
onChange={(val) => {
|
||||
const nextValue = !Array.isArray(val)
|
||||
? (val as OptionType<number> | null)
|
||||
: null;
|
||||
formik.setFieldValue('project_flock', nextValue);
|
||||
formik.setFieldValue('project_flock_kandang', null);
|
||||
}}
|
||||
options={projectFlockOptions}
|
||||
isLoading={isLoadingProjectFlockOptions}
|
||||
onInputChange={setProjectFlockInputValue}
|
||||
onMenuScrollToBottom={loadMoreProjectFlocks}
|
||||
isClearable
|
||||
isDisabled={!formik.values.location}
|
||||
/>
|
||||
|
||||
<SelectInput
|
||||
label='Kandang'
|
||||
placeholder='Pilih Kandang'
|
||||
value={formik.values.project_flock_kandang}
|
||||
onChange={(val) =>
|
||||
formik.setFieldValue(
|
||||
'project_flock_kandang',
|
||||
!Array.isArray(val) ? (val as OptionType<number> | null) : null
|
||||
)
|
||||
}
|
||||
options={projectFlockKandangOptions}
|
||||
isClearable
|
||||
isDisabled={!formik.values.project_flock}
|
||||
/>
|
||||
|
||||
{/* Row 3: Kategori, Status, Vendor, Search */}
|
||||
<SelectInputCheckbox
|
||||
label='Kategori Produk'
|
||||
placeholder='Pilih Kategori'
|
||||
value={formik.values.category}
|
||||
onChange={productCategoryChangeHandler}
|
||||
options={productCategoryOptions}
|
||||
isLoading={isLoadingProductCategoryOptions}
|
||||
onInputChange={setProductCategoryInputValue}
|
||||
onMenuScrollToBottom={loadMoreProductCategory}
|
||||
/>
|
||||
|
||||
<SelectInputCheckbox
|
||||
label='Status'
|
||||
placeholder='Pilih Status'
|
||||
value={formik.values.status}
|
||||
onChange={statusChangeHandler}
|
||||
options={PURCHASE_ORDER_APPROVAL_LINE.map((item) => ({
|
||||
label: item.step_name,
|
||||
value: item.step_name,
|
||||
}))}
|
||||
/>
|
||||
|
||||
<SelectInput
|
||||
label='Vendor'
|
||||
placeholder='Pilih Vendor'
|
||||
value={formik.values.supplier}
|
||||
onChange={(val) =>
|
||||
formik.setFieldValue(
|
||||
'supplier',
|
||||
!Array.isArray(val) ? (val as OptionType<number> | null) : null
|
||||
)
|
||||
}
|
||||
options={supplierOptions}
|
||||
isLoading={isLoadingSupplierOptions}
|
||||
onInputChange={setSupplierInputValue}
|
||||
onMenuScrollToBottom={loadMoreSuppliers}
|
||||
isClearable
|
||||
/>
|
||||
|
||||
<div className='flex flex-col'>
|
||||
<label className='block text-xs font-semibold text-base-content py-2'>
|
||||
Search
|
||||
</label>
|
||||
<DebouncedTextInput
|
||||
name='search'
|
||||
placeholder='Cari...'
|
||||
value={searchValue ?? ''}
|
||||
onChange={onSearchChange}
|
||||
startAdornment={
|
||||
<Icon icon='heroicons:magnifying-glass' width={20} height={20} />
|
||||
}
|
||||
className={{
|
||||
inputWrapper: 'rounded-xl! shadow-button-soft',
|
||||
input:
|
||||
'placeholder:font-semibold placeholder:text-base-content/50',
|
||||
}}
|
||||
/>
|
||||
<p className='text-xs text-base-content/50 mt-1'>
|
||||
Bisa cari PR/PO, vendor, produk, atau PO ekspedisi (biaya
|
||||
pengiriman).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex justify-end gap-3 mt-4'>
|
||||
<Button
|
||||
type='reset'
|
||||
variant='outline'
|
||||
color='none'
|
||||
className='px-4 py-2.5 rounded-xl text-sm text-base-content/65'
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type='button'
|
||||
onClick={formikSubmitHandler}
|
||||
disabled={hasDateError}
|
||||
className='px-4 py-2.5 rounded-xl text-sm text-base-100'
|
||||
>
|
||||
Cari
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default PurchaseInlineFilter;
|
||||
@@ -13,7 +13,6 @@ import toast from 'react-hot-toast';
|
||||
import Link from 'next/link';
|
||||
import { Icon } from '@iconify/react';
|
||||
import Table from '@/components/Table';
|
||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
||||
import DateInput from '@/components/input/DateInput';
|
||||
import Button from '@/components/Button';
|
||||
import Modal, { useModal } from '@/components/Modal';
|
||||
@@ -23,8 +22,7 @@ import PopoverContent from '@/components/popover/PopoverContent';
|
||||
import RequirePermission from '@/components/helper/RequirePermission';
|
||||
import StatusBadge from '@/components/helper/StatusBadge';
|
||||
import PurchaseTableSkeleton from '@/components/pages/purchase/skeleton/PurchaseTableSkeleton';
|
||||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||
import PurchaseFilterModal from '@/components/pages/purchase/PurchaseFilterModal';
|
||||
import PurchaseInlineFilter from '@/components/pages/purchase/PurchaseInlineFilter';
|
||||
import Dropdown from '@/components/dropdown/Dropdown';
|
||||
import { OptionType } from '@/components/input/SelectInput';
|
||||
|
||||
@@ -258,7 +256,6 @@ const PurchaseTable = () => {
|
||||
};
|
||||
|
||||
// ===== MODAL HOOKS =====
|
||||
const filterModal = useModal();
|
||||
const deleteModal = useModal();
|
||||
const exportProgressInputModal = useModal();
|
||||
|
||||
@@ -878,47 +875,6 @@ const PurchaseTable = () => {
|
||||
</div>
|
||||
|
||||
<div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
|
||||
<DebouncedTextInput
|
||||
name='search'
|
||||
placeholder='Search'
|
||||
value={tableFilterState.search}
|
||||
onChange={searchChangeHandler}
|
||||
startAdornment={
|
||||
<Icon
|
||||
icon='heroicons:magnifying-glass'
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
}
|
||||
className={{
|
||||
wrapper: 'w-full min-w-24 max-w-3xs',
|
||||
inputWrapper: 'rounded-xl! shadow-button-soft',
|
||||
input:
|
||||
'placeholder:font-semibold placeholder:text-base-content/50',
|
||||
}}
|
||||
/>
|
||||
|
||||
<ButtonFilter
|
||||
values={tableFilterState}
|
||||
excludeFields={[
|
||||
'page',
|
||||
'pageSize',
|
||||
'search',
|
||||
'filter_by',
|
||||
'sort_by',
|
||||
'order_by',
|
||||
'product_category_name',
|
||||
'supplier_name',
|
||||
'area_name',
|
||||
'location_name',
|
||||
'project_flock_name',
|
||||
'project_flock_kandang_name',
|
||||
]}
|
||||
fieldGroups={[['start_date', 'end_date']]}
|
||||
onClick={filterModal.openModal}
|
||||
className='px-3 py-2.5'
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
align='end'
|
||||
direction='bottom'
|
||||
@@ -976,6 +932,14 @@ const PurchaseTable = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PurchaseInlineFilter
|
||||
initialValues={purchaseFilterInitialValues}
|
||||
searchValue={tableFilterState.search}
|
||||
onSearchChange={searchChangeHandler}
|
||||
onSubmit={filterSubmitHandler}
|
||||
onReset={filterResetHandler}
|
||||
/>
|
||||
|
||||
{/* Table Section */}
|
||||
<div className='flex flex-col mb-4'>
|
||||
{isLoading ? (
|
||||
@@ -1033,13 +997,6 @@ const PurchaseTable = () => {
|
||||
|
||||
{/* ===== MODAL COMPONENTS ===== */}
|
||||
|
||||
<PurchaseFilterModal
|
||||
ref={filterModal.ref}
|
||||
initialValues={purchaseFilterInitialValues}
|
||||
onSubmit={filterSubmitHandler}
|
||||
onReset={filterResetHandler}
|
||||
/>
|
||||
|
||||
<ConfirmationModal
|
||||
ref={deleteModal.ref}
|
||||
type='error'
|
||||
|
||||
Reference in New Issue
Block a user