mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
feat(FE-361,363): Add product category filter and API params
This commit is contained in:
@@ -10,6 +10,7 @@ import DateInput from '@/components/input/DateInput';
|
|||||||
import { AreaApi } from '@/services/api/master-data';
|
import { AreaApi } from '@/services/api/master-data';
|
||||||
import { SupplierApi } from '@/services/api/master-data';
|
import { SupplierApi } from '@/services/api/master-data';
|
||||||
import { ProductApi } from '@/services/api/master-data';
|
import { ProductApi } from '@/services/api/master-data';
|
||||||
|
import { ProductCategoryApi } from '@/services/api/master-data';
|
||||||
import { LogisticApi } from '@/services/api/logistic';
|
import { LogisticApi } from '@/services/api/logistic';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
@@ -33,10 +34,6 @@ interface Totals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PurchasesPerSupplierTab = () => {
|
const PurchasesPerSupplierTab = () => {
|
||||||
const [dataType, setDataType] = useState<'received_date' | 'po_date'>(
|
|
||||||
'received_date'
|
|
||||||
);
|
|
||||||
|
|
||||||
// ===== PAGINATION STATE =====
|
// ===== PAGINATION STATE =====
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [pageSize, setPageSize] = useState(10);
|
const [pageSize, setPageSize] = useState(10);
|
||||||
@@ -50,10 +47,13 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
area_id: '',
|
area_id: '',
|
||||||
supplier_id: '',
|
supplier_id: '',
|
||||||
product_id: '',
|
product_id: '',
|
||||||
|
product_category_id: '',
|
||||||
received_date: '',
|
received_date: '',
|
||||||
po_date: '',
|
po_date: '',
|
||||||
start_date: '',
|
start_date: '',
|
||||||
end_date: '',
|
end_date: '',
|
||||||
|
sort_by: '',
|
||||||
|
filter_by: 'received_date',
|
||||||
},
|
},
|
||||||
paramMap: {
|
paramMap: {
|
||||||
page: 'page',
|
page: 'page',
|
||||||
@@ -61,16 +61,6 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateDataType = useCallback(
|
|
||||||
(newDataType: 'received_date' | 'po_date') => {
|
|
||||||
setDataType(newDataType);
|
|
||||||
updateFilter('received_date', '');
|
|
||||||
updateFilter('po_date', '');
|
|
||||||
setIsSubmitted(false);
|
|
||||||
},
|
|
||||||
[updateFilter]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { options: areaOptions, isLoadingOptions: isLoadingAreas } = useSelect(
|
const { options: areaOptions, isLoadingOptions: isLoadingAreas } = useSelect(
|
||||||
AreaApi.basePath,
|
AreaApi.basePath,
|
||||||
'id',
|
'id',
|
||||||
@@ -84,6 +74,11 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
const { options: productOptions, isLoadingOptions: isLoadingProducts } =
|
const { options: productOptions, isLoadingOptions: isLoadingProducts } =
|
||||||
useSelect(ProductApi.basePath, 'id', 'name', 'search');
|
useSelect(ProductApi.basePath, 'id', 'name', 'search');
|
||||||
|
|
||||||
|
const {
|
||||||
|
options: productCategoryOptions,
|
||||||
|
isLoadingOptions: isLoadingProductCategories,
|
||||||
|
} = useSelect(ProductCategoryApi.basePath, 'id', 'name', 'search');
|
||||||
|
|
||||||
const dataTypeOptions = useMemo(
|
const dataTypeOptions = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ value: 'received_date', label: 'Tanggal Terima' },
|
{ value: 'received_date', label: 'Tanggal Terima' },
|
||||||
@@ -119,15 +114,29 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
[updateFilter]
|
[updateFilter]
|
||||||
);
|
);
|
||||||
|
|
||||||
const dataTypeChangeHandler = useCallback(
|
const productCategoryChangeHandler = useCallback(
|
||||||
(val: OptionType | OptionType[] | null) => {
|
(val: OptionType | OptionType[] | null) => {
|
||||||
const newVal = val as OptionType;
|
const newVal = val as OptionType;
|
||||||
updateDataType(
|
updateFilter(
|
||||||
(newVal?.value as 'received_date' | 'po_date') || 'received_date'
|
'product_category_id',
|
||||||
|
newVal?.value ? String(newVal.value) : ''
|
||||||
);
|
);
|
||||||
setIsSubmitted(false);
|
setIsSubmitted(false);
|
||||||
},
|
},
|
||||||
[updateDataType]
|
[updateFilter]
|
||||||
|
);
|
||||||
|
|
||||||
|
const dataTypeChangeHandler = useCallback(
|
||||||
|
(val: OptionType | OptionType[] | null) => {
|
||||||
|
const newVal = val as OptionType;
|
||||||
|
const filterValue =
|
||||||
|
(newVal?.value as 'received_date' | 'po_date') || 'received_date';
|
||||||
|
updateFilter('filter_by', filterValue);
|
||||||
|
updateFilter('received_date', '');
|
||||||
|
updateFilter('po_date', '');
|
||||||
|
setIsSubmitted(false);
|
||||||
|
},
|
||||||
|
[updateFilter]
|
||||||
);
|
);
|
||||||
|
|
||||||
const startDateChangeHandler = useCallback<
|
const startDateChangeHandler = useCallback<
|
||||||
@@ -156,11 +165,13 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
updateFilter('area_id', '');
|
updateFilter('area_id', '');
|
||||||
updateFilter('supplier_id', '');
|
updateFilter('supplier_id', '');
|
||||||
updateFilter('product_id', '');
|
updateFilter('product_id', '');
|
||||||
|
updateFilter('product_category_id', '');
|
||||||
updateFilter('received_date', '');
|
updateFilter('received_date', '');
|
||||||
updateFilter('po_date', '');
|
updateFilter('po_date', '');
|
||||||
updateFilter('start_date', '');
|
updateFilter('start_date', '');
|
||||||
updateFilter('end_date', '');
|
updateFilter('end_date', '');
|
||||||
setDataType('received_date');
|
updateFilter('sort_by', '');
|
||||||
|
updateFilter('filter_by', 'received_date');
|
||||||
setIsSubmitted(false);
|
setIsSubmitted(false);
|
||||||
}, [updateFilter]);
|
}, [updateFilter]);
|
||||||
|
|
||||||
@@ -183,10 +194,21 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
product_id: tableFilterState.product_id
|
product_id: tableFilterState.product_id
|
||||||
? Number(tableFilterState.product_id)
|
? Number(tableFilterState.product_id)
|
||||||
: undefined,
|
: undefined,
|
||||||
received_date: tableFilterState.received_date || undefined,
|
product_category_id: tableFilterState.product_category_id
|
||||||
po_date: tableFilterState.po_date || undefined,
|
? Number(tableFilterState.product_category_id)
|
||||||
|
: undefined,
|
||||||
|
received_date:
|
||||||
|
tableFilterState.filter_by === 'received_date'
|
||||||
|
? tableFilterState.start_date || undefined
|
||||||
|
: undefined,
|
||||||
|
po_date:
|
||||||
|
tableFilterState.filter_by === 'po_date'
|
||||||
|
? tableFilterState.start_date || undefined
|
||||||
|
: undefined,
|
||||||
start_date: tableFilterState.start_date || undefined,
|
start_date: tableFilterState.start_date || undefined,
|
||||||
end_date: tableFilterState.end_date || undefined,
|
end_date: tableFilterState.end_date || undefined,
|
||||||
|
sort_by: tableFilterState.sort_by || undefined,
|
||||||
|
filter_by: tableFilterState.filter_by || undefined,
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
};
|
};
|
||||||
@@ -199,10 +221,13 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
params.area_id,
|
params.area_id,
|
||||||
params.supplier_id,
|
params.supplier_id,
|
||||||
params.product_id,
|
params.product_id,
|
||||||
|
params.product_category_id,
|
||||||
params.received_date,
|
params.received_date,
|
||||||
params.po_date,
|
params.po_date,
|
||||||
params.start_date,
|
params.start_date,
|
||||||
params.end_date,
|
params.end_date,
|
||||||
|
params.sort_by,
|
||||||
|
params.filter_by,
|
||||||
params.page,
|
params.page,
|
||||||
params.limit
|
params.limit
|
||||||
)
|
)
|
||||||
@@ -254,7 +279,6 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
items: LogisticPurchasePerSupplierReport['rows'];
|
items: LogisticPurchasePerSupplierReport['rows'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group data by supplier for display
|
|
||||||
const groupedData = useMemo(() => {
|
const groupedData = useMemo(() => {
|
||||||
const groups: { [key: number]: GroupedSupplierData } = {};
|
const groups: { [key: number]: GroupedSupplierData } = {};
|
||||||
|
|
||||||
@@ -468,7 +492,7 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
</Menu>
|
</Menu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div className='grid grid-cols-12 gap-4'>
|
<div className='grid grid-cols-3 gap-4'>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Area'
|
label='Area'
|
||||||
placeholder='Pilih Area'
|
placeholder='Pilih Area'
|
||||||
@@ -484,9 +508,6 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
onChange={areaChangeHandler}
|
onChange={areaChangeHandler}
|
||||||
isLoading={isLoadingAreas}
|
isLoading={isLoadingAreas}
|
||||||
isClearable
|
isClearable
|
||||||
className={{
|
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Supplier'
|
label='Supplier'
|
||||||
@@ -503,9 +524,6 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
onChange={supplierChangeHandler}
|
onChange={supplierChangeHandler}
|
||||||
isLoading={isLoadingSuppliers}
|
isLoading={isLoadingSuppliers}
|
||||||
isClearable
|
isClearable
|
||||||
className={{
|
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Produk'
|
label='Produk'
|
||||||
@@ -522,45 +540,55 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
onChange={productChangeHandler}
|
onChange={productChangeHandler}
|
||||||
isLoading={isLoadingProducts}
|
isLoading={isLoadingProducts}
|
||||||
isClearable
|
isClearable
|
||||||
className={{
|
/>
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
</div>
|
||||||
}}
|
<div className='grid grid-cols-3 gap-4'>
|
||||||
|
<SelectInput
|
||||||
|
label='Kategori Produk'
|
||||||
|
placeholder='Pilih Kategori Produk'
|
||||||
|
options={productCategoryOptions}
|
||||||
|
value={
|
||||||
|
tableFilterState.product_category_id
|
||||||
|
? productCategoryOptions.find(
|
||||||
|
(option) =>
|
||||||
|
option.value ===
|
||||||
|
Number(tableFilterState.product_category_id)
|
||||||
|
) || null
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
onChange={productCategoryChangeHandler}
|
||||||
|
isLoading={isLoadingProductCategories}
|
||||||
|
isClearable
|
||||||
/>
|
/>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Tipe Data'
|
label='Filter Berdasarkan'
|
||||||
placeholder='Pilih Tipe Data'
|
placeholder='Pilih Filter Berdasarkan'
|
||||||
options={dataTypeOptions}
|
options={dataTypeOptions}
|
||||||
value={
|
value={
|
||||||
dataTypeOptions?.find((option) => option.value === dataType) ||
|
dataTypeOptions?.find(
|
||||||
null
|
(option) => option.value === tableFilterState.filter_by
|
||||||
|
) || null
|
||||||
}
|
}
|
||||||
onChange={dataTypeChangeHandler}
|
onChange={dataTypeChangeHandler}
|
||||||
isLoading={false}
|
isLoading={false}
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
className={{
|
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<DateInput
|
|
||||||
label='Tanggal Awal'
|
|
||||||
name='start_date'
|
|
||||||
placeholder='Pilih Tanggal Awal'
|
|
||||||
value={tableFilterState.start_date}
|
|
||||||
onChange={startDateChangeHandler}
|
|
||||||
className={{
|
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<DateInput
|
|
||||||
label='Tanggal Akhir'
|
|
||||||
name='end_date'
|
|
||||||
placeholder='Pilih Tanggal Akhir'
|
|
||||||
value={tableFilterState.end_date}
|
|
||||||
onChange={endDateChangeHandler}
|
|
||||||
className={{
|
|
||||||
wrapper: 'col-span-12 sm:col-span-4',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
<div className='flex flex-row gap-4'>
|
||||||
|
<DateInput
|
||||||
|
label='Tanggal Awal'
|
||||||
|
name='start_date'
|
||||||
|
placeholder='Pilih Tanggal Awal'
|
||||||
|
value={tableFilterState.start_date}
|
||||||
|
onChange={startDateChangeHandler}
|
||||||
|
/>
|
||||||
|
<DateInput
|
||||||
|
label='Tanggal Akhir'
|
||||||
|
name='end_date'
|
||||||
|
placeholder='Pilih Tanggal Akhir'
|
||||||
|
value={tableFilterState.end_date}
|
||||||
|
onChange={endDateChangeHandler}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!isSubmitted ? (
|
{!isSubmitted ? (
|
||||||
|
|||||||
@@ -15,10 +15,13 @@ export class LogisticApiService extends BaseApiService<
|
|||||||
area_id?: number,
|
area_id?: number,
|
||||||
supplier_id?: number,
|
supplier_id?: number,
|
||||||
product_id?: number,
|
product_id?: number,
|
||||||
|
product_category_id?: number,
|
||||||
received_date?: string,
|
received_date?: string,
|
||||||
po_date?: string,
|
po_date?: string,
|
||||||
start_date?: string,
|
start_date?: string,
|
||||||
end_date?: string,
|
end_date?: string,
|
||||||
|
sort_by?: string,
|
||||||
|
filter_by?: string,
|
||||||
page?: number,
|
page?: number,
|
||||||
limit?: number
|
limit?: number
|
||||||
): Promise<BaseApiResponse<LogisticPurchasePerSupplierReport> | undefined> {
|
): Promise<BaseApiResponse<LogisticPurchasePerSupplierReport> | undefined> {
|
||||||
@@ -30,10 +33,13 @@ export class LogisticApiService extends BaseApiService<
|
|||||||
area_id: area_id,
|
area_id: area_id,
|
||||||
supplier_id: supplier_id,
|
supplier_id: supplier_id,
|
||||||
product_id: product_id,
|
product_id: product_id,
|
||||||
|
product_category_id: product_category_id,
|
||||||
received_date: received_date,
|
received_date: received_date,
|
||||||
po_date: po_date,
|
po_date: po_date,
|
||||||
start_date: start_date,
|
start_date: start_date,
|
||||||
end_date: end_date,
|
end_date: end_date,
|
||||||
|
sort_by: sort_by,
|
||||||
|
filter_by: filter_by,
|
||||||
page: page,
|
page: page,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user