mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
refactor(FE-327): change SalesReportTable to use new API fields
This commit is contained in:
@@ -8,6 +8,8 @@ import Card from '@/components/Card';
|
|||||||
import Badge from '@/components/Badge';
|
import Badge from '@/components/Badge';
|
||||||
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
import { formatCurrency, formatNumber, formatDate } from '@/lib/helper';
|
||||||
import { BaseClosingSales, BaseSales } from '@/types/api/closing/closing';
|
import { BaseClosingSales, BaseSales } from '@/types/api/closing/closing';
|
||||||
|
import { Product } from '@type/api/master-data/product';
|
||||||
|
import { Customer } from '@type/api/master-data/customer';
|
||||||
|
|
||||||
interface SalesReportTableProps {
|
interface SalesReportTableProps {
|
||||||
type?: 'detail';
|
type?: 'detail';
|
||||||
@@ -109,34 +111,6 @@ const generateCustomHeaders = (template: {
|
|||||||
return rows;
|
return rows;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: TEMPORARY - Remove this when backend API returns English field names
|
|
||||||
const mapIndonesianDataToEnglish = (data: BaseClosingSales): BaseSales[] => {
|
|
||||||
if (!data || !data.penjualan || !Array.isArray(data.penjualan)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
return data.penjualan.map((item: any) => ({
|
|
||||||
id: item.id,
|
|
||||||
realization_date: item.tanggal_realisasi,
|
|
||||||
week_age: item.umur_minggu,
|
|
||||||
age_label: item.umur_label,
|
|
||||||
delivery_order_number: item.no_do,
|
|
||||||
product: item.produk,
|
|
||||||
product_category: item.jenis_produk,
|
|
||||||
customer: item.customer,
|
|
||||||
quantity: item.qty,
|
|
||||||
weight: item.kg,
|
|
||||||
average: item.avg,
|
|
||||||
price: item.harga,
|
|
||||||
total: item.total,
|
|
||||||
kandang: item.kandang,
|
|
||||||
kandang_id: item.kandang_id,
|
|
||||||
payment_status: item.status_pembayaran,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
// END TODO
|
|
||||||
|
|
||||||
const SalesReportTable = ({
|
const SalesReportTable = ({
|
||||||
type = 'detail',
|
type = 'detail',
|
||||||
initialValues,
|
initialValues,
|
||||||
@@ -144,13 +118,8 @@ const SalesReportTable = ({
|
|||||||
const [activeTabId, setActiveTabId] = useState<string>('penjualan');
|
const [activeTabId, setActiveTabId] = useState<string>('penjualan');
|
||||||
|
|
||||||
const salesBroilerData: BaseSales[] = useMemo(() => {
|
const salesBroilerData: BaseSales[] = useMemo(() => {
|
||||||
if (activeTabId === 'penjualan' && initialValues) {
|
if (activeTabId === 'penjualan' && initialValues && initialValues.sales) {
|
||||||
// TODO: TEMPORARY - Remove this when backend API returns English field names
|
return initialValues.sales;
|
||||||
if (initialValues.penjualan && Array.isArray(initialValues.penjualan)) {
|
|
||||||
return mapIndonesianDataToEnglish(initialValues);
|
|
||||||
}
|
|
||||||
// END TODO
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}, [initialValues, activeTabId]);
|
}, [initialValues, activeTabId]);
|
||||||
@@ -169,7 +138,7 @@ const SalesReportTable = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const totalQuantity = salesBroilerData.reduce(
|
const totalQuantity = salesBroilerData.reduce(
|
||||||
(sum, item) => sum + (item.quantity || 0),
|
(sum, item) => sum + (item.qty || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const totalWeight = salesBroilerData.reduce(
|
const totalWeight = salesBroilerData.reduce(
|
||||||
@@ -188,7 +157,7 @@ const SalesReportTable = ({
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const totalPartner = salesBroilerData.reduce(
|
const totalPartner = salesBroilerData.reduce(
|
||||||
(sum, item) => sum + (item.total || 0),
|
(sum, item) => sum + (item.total_price || 0),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -218,14 +187,14 @@ const SalesReportTable = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'age_label',
|
id: 'age',
|
||||||
accessorKey: 'age_label',
|
accessorKey: 'age',
|
||||||
header: 'Umur',
|
header: 'Umur',
|
||||||
cell: (props) => props.getValue() || '-',
|
cell: (props) => props.getValue() || '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'delivery_order_number',
|
id: 'do_number',
|
||||||
accessorKey: 'delivery_order_number',
|
accessorKey: 'do_number',
|
||||||
header: 'No. DO',
|
header: 'No. DO',
|
||||||
cell: (props) => props.getValue() || '-',
|
cell: (props) => props.getValue() || '-',
|
||||||
},
|
},
|
||||||
@@ -233,17 +202,23 @@ const SalesReportTable = ({
|
|||||||
id: 'product',
|
id: 'product',
|
||||||
accessorKey: 'product',
|
accessorKey: 'product',
|
||||||
header: 'Produk',
|
header: 'Produk',
|
||||||
cell: (props) => props.getValue() || '-',
|
cell: (props) => {
|
||||||
|
const product = props.getValue() as Product;
|
||||||
|
return product?.name || '-';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'customer',
|
id: 'customer',
|
||||||
accessorKey: 'customer',
|
accessorKey: 'customer',
|
||||||
header: 'Customer',
|
header: 'Customer',
|
||||||
cell: (props) => props.getValue() || '-',
|
cell: (props) => {
|
||||||
|
const customer = props.getValue() as Customer;
|
||||||
|
return customer?.name || '-';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'quantity',
|
id: 'qty',
|
||||||
accessorKey: 'quantity',
|
accessorKey: 'qty',
|
||||||
header: 'Kuantitas',
|
header: 'Kuantitas',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
@@ -270,8 +245,8 @@ const SalesReportTable = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'average',
|
id: 'avg_weight',
|
||||||
accessorKey: 'average',
|
accessorKey: 'avg_weight',
|
||||||
header: 'AVG (Kg)',
|
header: 'AVG (Kg)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
@@ -289,26 +264,16 @@ const SalesReportTable = ({
|
|||||||
header: 'Harga Mitra (Rp)',
|
header: 'Harga Mitra (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
const isSummary = props.row.id === 'summary';
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
return (
|
|
||||||
<div className={isSummary ? 'text-right' : ''}>
|
|
||||||
{formatCurrency(value)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'total_mitra',
|
id: 'total_mitra',
|
||||||
accessorKey: 'total',
|
accessorKey: 'total_price',
|
||||||
header: 'Total Mitra (Rp)',
|
header: 'Total Mitra (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
const isSummary = props.row.id === 'summary';
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
return (
|
|
||||||
<div className={isSummary ? 'text-right' : ''}>
|
|
||||||
{formatCurrency(value)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -317,26 +282,16 @@ const SalesReportTable = ({
|
|||||||
header: 'Harga Act (Rp)',
|
header: 'Harga Act (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
const isSummary = props.row.id === 'summary';
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
return (
|
|
||||||
<div className={isSummary ? 'text-right' : ''}>
|
|
||||||
{formatCurrency(value)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'total_act',
|
id: 'total_act',
|
||||||
accessorKey: 'total',
|
accessorKey: 'total_price',
|
||||||
header: 'Total Act (Rp)',
|
header: 'Total Act (Rp)',
|
||||||
cell: (props) => {
|
cell: (props) => {
|
||||||
const value = props.getValue() as number;
|
const value = props.getValue() as number;
|
||||||
const isSummary = props.row.id === 'summary';
|
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||||
return (
|
|
||||||
<div className={isSummary ? 'text-right' : ''}>
|
|
||||||
{formatCurrency(value)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -379,16 +334,16 @@ const SalesReportTable = ({
|
|||||||
const headerTemplate = {
|
const headerTemplate = {
|
||||||
groups: [
|
groups: [
|
||||||
{ label: 'Tanggal Realisasi', field: 'realization_date', rowSpan: 2 },
|
{ label: 'Tanggal Realisasi', field: 'realization_date', rowSpan: 2 },
|
||||||
{ label: 'Umur', field: 'age_label', rowSpan: 2 },
|
{ label: 'Umur', field: 'age', rowSpan: 2 },
|
||||||
{ label: 'No. DO', field: 'delivery_order_number', rowSpan: 2 },
|
{ label: 'No. DO', field: 'do_number', rowSpan: 2 },
|
||||||
{ label: 'Produk', field: 'product', rowSpan: 2 },
|
{ label: 'Produk', field: 'product', rowSpan: 2 },
|
||||||
{ label: 'Customer', field: 'customer', rowSpan: 2 },
|
{ label: 'Customer', field: 'customer', rowSpan: 2 },
|
||||||
{
|
{
|
||||||
label: 'Jumlah',
|
label: 'Jumlah',
|
||||||
colSpan: 2,
|
colSpan: 2,
|
||||||
subLabels: ['Kuantitas', 'Kg'],
|
subLabels: ['Qty', 'Kg'],
|
||||||
},
|
},
|
||||||
{ label: 'AVG (Kg)', field: 'average', rowSpan: 2 },
|
{ label: 'AVG (Kg)', field: 'avg_weight', rowSpan: 2 },
|
||||||
{ label: 'Harga Mitra (Rp)', field: 'price_partner', rowSpan: 2 },
|
{ label: 'Harga Mitra (Rp)', field: 'price_partner', rowSpan: 2 },
|
||||||
{ label: 'Total Mitra (Rp)', field: 'total_mitra', rowSpan: 2 },
|
{ label: 'Total Mitra (Rp)', field: 'total_mitra', rowSpan: 2 },
|
||||||
{ label: 'Harga Act (Rp)', field: 'price_act', rowSpan: 2 },
|
{ label: 'Harga Act (Rp)', field: 'price_act', rowSpan: 2 },
|
||||||
@@ -482,78 +437,6 @@ const SalesReportTable = ({
|
|||||||
variant='lifted'
|
variant='lifted'
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<section className='w-ful'>
|
|
||||||
<Card
|
|
||||||
collapsible={true}
|
|
||||||
defaultCollapsed={true}
|
|
||||||
className={{ wrapper: 'w-full bg-base-100' }}
|
|
||||||
title='(Latest) API Response Sample BE for Sales Report Data'
|
|
||||||
>
|
|
||||||
<pre>
|
|
||||||
{JSON.stringify(
|
|
||||||
{
|
|
||||||
code: 200,
|
|
||||||
status: 'success',
|
|
||||||
message: 'Retrieved sales report successfully',
|
|
||||||
data: {
|
|
||||||
project_type: 'GROWING',
|
|
||||||
flock_id: '1',
|
|
||||||
period: 10,
|
|
||||||
sales: [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
realization_date: '2025-12-05T02:22:17.443165Z',
|
|
||||||
age: 20,
|
|
||||||
do_number: 'SO-DO-10001',
|
|
||||||
product: {
|
|
||||||
id: 1,
|
|
||||||
name: 'Laptop Gaming X500',
|
|
||||||
product_price: 15000000,
|
|
||||||
selling_price: 16500000.5,
|
|
||||||
uom: {
|
|
||||||
id: 1,
|
|
||||||
name: 'KG',
|
|
||||||
},
|
|
||||||
flags: ['Best Seller', 'New Arrival'],
|
|
||||||
product_category: {
|
|
||||||
id: 5,
|
|
||||||
name: 'Elektronik',
|
|
||||||
code: 'DOC',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
customer: {
|
|
||||||
id: 12345,
|
|
||||||
name: 'PT. Solusi Teknologi Nusantara',
|
|
||||||
type: 'Perusahaan',
|
|
||||||
account_number: 'ACC1234567890',
|
|
||||||
balance: 5000000.75,
|
|
||||||
pic: {
|
|
||||||
id: 101,
|
|
||||||
name: 'Budi Santoso',
|
|
||||||
email: 'budi.santoso@example.com',
|
|
||||||
role: 'Manajer Akun',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
qty: 6348,
|
|
||||||
weight: 19142,
|
|
||||||
avg_weight: 3.02,
|
|
||||||
price: 26419,
|
|
||||||
total_price: 505712498,
|
|
||||||
kandang: {
|
|
||||||
id: 1,
|
|
||||||
name: 'cibeber 1',
|
|
||||||
},
|
|
||||||
payment_status: 'Paid',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
)}
|
|
||||||
</pre>
|
|
||||||
</Card>
|
|
||||||
</section>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user