mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-06-21 21:58:44 +00:00
Merge branch 'feat/filter-po' into 'production'
adjust filter po See merge request mbugroup/lti-web-client!519
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 Link from 'next/link';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
|
|
||||||
import DateInput from '@/components/input/DateInput';
|
import DateInput from '@/components/input/DateInput';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import Modal, { useModal } from '@/components/Modal';
|
import Modal, { useModal } from '@/components/Modal';
|
||||||
@@ -23,8 +22,7 @@ import PopoverContent from '@/components/popover/PopoverContent';
|
|||||||
import RequirePermission from '@/components/helper/RequirePermission';
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import PurchaseTableSkeleton from '@/components/pages/purchase/skeleton/PurchaseTableSkeleton';
|
import PurchaseTableSkeleton from '@/components/pages/purchase/skeleton/PurchaseTableSkeleton';
|
||||||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
import PurchaseInlineFilter from '@/components/pages/purchase/PurchaseInlineFilter';
|
||||||
import PurchaseFilterModal from '@/components/pages/purchase/PurchaseFilterModal';
|
|
||||||
import Dropdown from '@/components/dropdown/Dropdown';
|
import Dropdown from '@/components/dropdown/Dropdown';
|
||||||
import { OptionType } from '@/components/input/SelectInput';
|
import { OptionType } from '@/components/input/SelectInput';
|
||||||
|
|
||||||
@@ -258,7 +256,6 @@ const PurchaseTable = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ===== MODAL HOOKS =====
|
// ===== MODAL HOOKS =====
|
||||||
const filterModal = useModal();
|
|
||||||
const deleteModal = useModal();
|
const deleteModal = useModal();
|
||||||
const exportProgressInputModal = useModal();
|
const exportProgressInputModal = useModal();
|
||||||
|
|
||||||
@@ -878,47 +875,6 @@ const PurchaseTable = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-1 flex-row justify-start sm:justify-end items-center gap-3 flex-wrap'>
|
<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
|
<Dropdown
|
||||||
align='end'
|
align='end'
|
||||||
direction='bottom'
|
direction='bottom'
|
||||||
@@ -976,6 +932,14 @@ const PurchaseTable = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<PurchaseInlineFilter
|
||||||
|
initialValues={purchaseFilterInitialValues}
|
||||||
|
searchValue={tableFilterState.search}
|
||||||
|
onSearchChange={searchChangeHandler}
|
||||||
|
onSubmit={filterSubmitHandler}
|
||||||
|
onReset={filterResetHandler}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Table Section */}
|
{/* Table Section */}
|
||||||
<div className='flex flex-col mb-4'>
|
<div className='flex flex-col mb-4'>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
@@ -1033,13 +997,6 @@ const PurchaseTable = () => {
|
|||||||
|
|
||||||
{/* ===== MODAL COMPONENTS ===== */}
|
{/* ===== MODAL COMPONENTS ===== */}
|
||||||
|
|
||||||
<PurchaseFilterModal
|
|
||||||
ref={filterModal.ref}
|
|
||||||
initialValues={purchaseFilterInitialValues}
|
|
||||||
onSubmit={filterSubmitHandler}
|
|
||||||
onReset={filterResetHandler}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
ref={deleteModal.ref}
|
ref={deleteModal.ref}
|
||||||
type='error'
|
type='error'
|
||||||
|
|||||||
Reference in New Issue
Block a user