mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-361,363): Adapt PurchasesPerSupplier to new report shape
This commit is contained in:
@@ -14,10 +14,7 @@ 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';
|
||||||
import { formatCurrency, formatDate } from '@/lib/helper';
|
import { formatCurrency, formatDate } from '@/lib/helper';
|
||||||
import {
|
import { LogisticPurchasePerSupplierReport } from '@/types/api/report/logistic-stock';
|
||||||
LogisticPurchasePerSupplier,
|
|
||||||
LogisticPurchasePerSupplierItems,
|
|
||||||
} from '@/types/api/report/logistic-stock';
|
|
||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
import { useTableFilter } from '@/services/hooks/useTableFilter';
|
||||||
import Pagination from '@/components/Pagination';
|
import Pagination from '@/components/Pagination';
|
||||||
@@ -211,11 +208,14 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const data: LogisticPurchasePerSupplier[] = isResponseSuccess(
|
const data: LogisticPurchasePerSupplierReport['rows'] = useMemo(
|
||||||
purchasePerSupplier
|
() =>
|
||||||
)
|
isResponseSuccess(purchasePerSupplier)
|
||||||
? (purchasePerSupplier?.data as unknown as LogisticPurchasePerSupplier[])
|
? (purchasePerSupplier?.data
|
||||||
: [];
|
?.rows as LogisticPurchasePerSupplierReport['rows']) || []
|
||||||
|
: [],
|
||||||
|
[purchasePerSupplier]
|
||||||
|
);
|
||||||
|
|
||||||
const meta =
|
const meta =
|
||||||
isResponseSuccess(purchasePerSupplier) && 'meta' in purchasePerSupplier
|
isResponseSuccess(purchasePerSupplier) && 'meta' in purchasePerSupplier
|
||||||
@@ -245,6 +245,36 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface GroupedSupplierData {
|
||||||
|
id: number;
|
||||||
|
supplier: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
items: LogisticPurchasePerSupplierReport['rows'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group data by supplier for display
|
||||||
|
const groupedData = useMemo(() => {
|
||||||
|
const groups: { [key: number]: GroupedSupplierData } = {};
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const supplierId = item.supplier?.id;
|
||||||
|
if (supplierId && !groups[supplierId]) {
|
||||||
|
groups[supplierId] = {
|
||||||
|
id: supplierId,
|
||||||
|
supplier: item.supplier,
|
||||||
|
items: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (groups[supplierId]) {
|
||||||
|
groups[supplierId].items.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.values(groups);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
const handlePrevPage = () => {
|
const handlePrevPage = () => {
|
||||||
if (currentPage > 1) {
|
if (currentPage > 1) {
|
||||||
setCurrentPage(currentPage - 1);
|
setCurrentPage(currentPage - 1);
|
||||||
@@ -253,20 +283,23 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
|
|
||||||
const getTableColumns = (
|
const getTableColumns = (
|
||||||
totals: Totals
|
totals: Totals
|
||||||
): ColumnDef<LogisticPurchasePerSupplierItems>[] => {
|
): ColumnDef<LogisticPurchasePerSupplierReport['rows'][0]>[] => {
|
||||||
const tableColumns: ColumnDef<LogisticPurchasePerSupplierItems>[] = [
|
const tableColumns: ColumnDef<
|
||||||
|
LogisticPurchasePerSupplierReport['rows'][0]
|
||||||
|
>[] = [
|
||||||
{
|
{
|
||||||
id: 'no',
|
id: 'no',
|
||||||
header: 'No',
|
header: 'No',
|
||||||
cell: (props) => props.row.index + 1,
|
cell: (props) => props.row.index + 1,
|
||||||
footer: () => <div className='font-semibold text-gray-900'>Total</div>,
|
footer: () => <div className='font-semibold text-gray-900'>Total</div>,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: 'received_date',
|
id: 'received_date',
|
||||||
header: 'Tanggal Terima',
|
header: 'Tanggal Terima',
|
||||||
accessorKey: 'received_date',
|
accessorKey: 'receive_date',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.received_date;
|
const value = props.row.original.receive_date;
|
||||||
return formatDate(value, 'DD MMM YYYY');
|
return formatDate(value, 'DD MMM YYYY');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -300,10 +333,10 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'destination_warehouse',
|
id: 'destination_warehouse',
|
||||||
header: 'Tujuan',
|
header: 'Tujuan',
|
||||||
accessorKey: 'destination_warehouse',
|
accessorKey: 'warehouse.name',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.destination_warehouse;
|
const warehouse = props.row.original.warehouse;
|
||||||
return value || '-';
|
return warehouse?.name || '-';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -323,9 +356,9 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'price',
|
id: 'price',
|
||||||
header: 'Harga Beli (Rp)',
|
header: 'Harga Beli (Rp)',
|
||||||
accessorKey: 'price',
|
accessorKey: 'unit_price',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.price;
|
const value = props.row.original.unit_price;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
@@ -337,9 +370,9 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'purchase_amount',
|
id: 'purchase_amount',
|
||||||
header: 'Value Harga Beli (Rp)',
|
header: 'Value Harga Beli (Rp)',
|
||||||
|
accessorKey: 'purchase_value',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const item = props.row.original;
|
const value = props.row.original.purchase_value;
|
||||||
const value = (item.price || 0) * (item.qty || 0);
|
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
@@ -351,9 +384,9 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'transport',
|
id: 'transport',
|
||||||
header: 'Transport (Rp)',
|
header: 'Transport (Rp)',
|
||||||
accessorKey: 'transport_per_item',
|
accessorKey: 'transport_unit_price',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.transport_per_item;
|
const value = props.row.original.transport_unit_price;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
@@ -365,9 +398,9 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'value_transport',
|
id: 'value_transport',
|
||||||
header: 'Value Transport (Rp)',
|
header: 'Value Transport (Rp)',
|
||||||
accessorKey: 'transport_total',
|
accessorKey: 'transport_value',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.transport_total;
|
const value = props.row.original.transport_value;
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
@@ -379,10 +412,9 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'total',
|
id: 'total',
|
||||||
header: 'Jumlah (Rp)',
|
header: 'Jumlah (Rp)',
|
||||||
|
accessorKey: 'total_amount',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const item = props.row.original;
|
const value = props.row.original.total_amount;
|
||||||
const value =
|
|
||||||
(item.price || 0) * (item.qty || 0) + (item.transport_total || 0);
|
|
||||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
},
|
},
|
||||||
footer: () => (
|
footer: () => (
|
||||||
@@ -394,18 +426,18 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
{
|
{
|
||||||
id: 'expedition_vendor_name',
|
id: 'expedition_vendor_name',
|
||||||
header: 'Ekspedisi',
|
header: 'Ekspedisi',
|
||||||
accessorKey: 'expedition_vendor_name',
|
accessorKey: 'expedition',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.expedition_vendor_name;
|
const value = props.row.original.expedition;
|
||||||
return value || '-';
|
return value || '-';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'travel_number',
|
id: 'travel_number',
|
||||||
header: 'Surat Jalan',
|
header: 'Surat Jalan',
|
||||||
accessorKey: 'travel_number',
|
accessorKey: 'delivery_number',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.row.original.travel_number;
|
const value = props.row.original.delivery_number;
|
||||||
return value || '-';
|
return value || '-';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -544,29 +576,25 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
Tidak ada data yang dapat ditampilkan...
|
Tidak ada data yang dapat ditampilkan...
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
data.map((supplier) => {
|
groupedData.map((supplier) => {
|
||||||
const totalQty = supplier.items.reduce(
|
const totalQty = supplier.items.reduce(
|
||||||
(sum, item) => sum + (item.qty || 0),
|
(sum, item) => sum + (item.qty || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const totalPrice = supplier.items.reduce(
|
const totalPrice = supplier.items.reduce(
|
||||||
(sum, item) => sum + (item.price || 0) * (item.qty || 0),
|
(sum, item) => sum + (item.purchase_value || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const totalTransport = supplier.items.reduce(
|
const totalTransport = supplier.items.reduce(
|
||||||
(sum, item) =>
|
(sum, item) => sum + (item.transport_value || 0),
|
||||||
sum + (item.transport_per_item || 0) * (item.qty || 0),
|
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const totalValueTransport = supplier.items.reduce(
|
const totalValueTransport = supplier.items.reduce(
|
||||||
(sum, item) => sum + (item.transport_total || 0),
|
(sum, item) => sum + (item.transport_value || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const totalJumlah = supplier.items.reduce(
|
const totalJumlah = supplier.items.reduce(
|
||||||
(sum, item) =>
|
(sum, item) => sum + (item.total_amount || 0),
|
||||||
sum +
|
|
||||||
(item.price || 0) * (item.qty || 0) +
|
|
||||||
(item.transport_total || 0),
|
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -587,7 +615,7 @@ const PurchasesPerSupplierTab = () => {
|
|||||||
key={supplier.id}
|
key={supplier.id}
|
||||||
title={supplier.supplier.name}
|
title={supplier.supplier.name}
|
||||||
subtitle={`Total Pembelian: ${formatCurrency(totalPurchase)}`}
|
subtitle={`Total Pembelian: ${formatCurrency(totalPurchase)}`}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full', body: 'py-6! p-0' }}
|
||||||
collapsible={true}
|
collapsible={true}
|
||||||
>
|
>
|
||||||
<Table
|
<Table
|
||||||
|
|||||||
Reference in New Issue
Block a user