mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE): Refactor DeliveryOrderProductTable to support delivery
order rendering
This commit is contained in:
@@ -2,10 +2,11 @@ import { DeliveryOrderProductFormValues } from '@/components/pages/marketing/for
|
||||
import Button from '@/components/Button';
|
||||
import Card from '@/components/Card';
|
||||
import { Icon } from '@iconify/react';
|
||||
import { useRef } from 'react';
|
||||
import { useRef, useMemo } from 'react';
|
||||
import { formatCurrency, formatDate, formatNumber } from '@/lib/helper';
|
||||
import DeliveryOrderExport from '@/components/pages/marketing/pdf/DeliveryOrderExport';
|
||||
import { Marketing } from '@/types/api/marketing/marketing';
|
||||
import { Marketing, BaseDelivery } from '@/types/api/marketing/marketing';
|
||||
import { Warehouse } from '@/types/api/master-data/warehouse';
|
||||
|
||||
type DeliveryOrderProductTableProps = {
|
||||
data: DeliveryOrderProductFormValues[];
|
||||
@@ -42,7 +43,31 @@ const DeliveryOrderProductTable = ({
|
||||
|
||||
const approvalStepNumber = marketing?.latest_approval?.step_number;
|
||||
|
||||
const renderTableContent = (item: DeliveryOrderProductFormValues) => {
|
||||
const hasDeliveryOrder = useMemo(() => {
|
||||
return (
|
||||
marketing?.delivery_order &&
|
||||
marketing.delivery_order.length > 0 &&
|
||||
marketing.delivery_order.some(
|
||||
(doItem) => doItem.deliveries && doItem.deliveries.length > 0
|
||||
)
|
||||
);
|
||||
}, [marketing?.delivery_order]);
|
||||
|
||||
const deliveryItems = useMemo(() => {
|
||||
if (!hasDeliveryOrder) return [];
|
||||
return (
|
||||
marketing?.delivery_order?.flatMap((doItem) =>
|
||||
doItem.deliveries.map((delivery) => ({
|
||||
...delivery,
|
||||
do_number: doItem.do_number,
|
||||
delivery_date: doItem.delivery_date,
|
||||
warehouse: doItem.warehouse,
|
||||
}))
|
||||
) ?? []
|
||||
);
|
||||
}, [marketing?.delivery_order, hasDeliveryOrder]);
|
||||
|
||||
const renderSalesOrderContent = (item: DeliveryOrderProductFormValues) => {
|
||||
const doItem = marketing?.delivery_order?.find(
|
||||
(doItem) => doItem.do_number === item.do_number
|
||||
);
|
||||
@@ -185,50 +210,217 @@ const DeliveryOrderProductTable = ({
|
||||
);
|
||||
};
|
||||
|
||||
const renderDeliveryOrderContent = (
|
||||
item: BaseDelivery & {
|
||||
do_number: string;
|
||||
delivery_date: string;
|
||||
warehouse: Warehouse;
|
||||
}
|
||||
) => {
|
||||
const parentDoItem = marketing?.delivery_order?.find(
|
||||
(doItem) => doItem.do_number === item.do_number
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<tr className='border-b border-tools-table-outline border-base-content/5'>
|
||||
<th className='w-1/3 text-start not-first:font-medium text-base-content/50 text-sm px-4 py-3'>
|
||||
Label
|
||||
</th>
|
||||
<th className='text-start font-medium text-base-content/50 text-sm px-4 py-3'>
|
||||
<div className='flex w-full flex-row gap-1 items-center justify-between h-full'>
|
||||
<div>Value</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<>
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Gudang</td>
|
||||
<td className='text-sm px-4 py-3'>{item.warehouse?.name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Produk</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{item.product_warehouse?.product?.name}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Qty</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{item.qty
|
||||
? `${formatNumber(item.qty)} ${item.product_warehouse?.product?.uom?.name ?? ''}`
|
||||
: '-'}
|
||||
</td>
|
||||
</tr>
|
||||
{Number(item.avg_weight ?? 0) > 0 && (
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Avg Bobot</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{formatNumber(Number(item.avg_weight))} Kg
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{Number(item.total_weight ?? 0) > 0 && (
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Total Bobot</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{formatNumber(Number(item.total_weight))}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Total Harga Satuan</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{formatCurrency(item.unit_price)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Total Penjualan</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{formatCurrency(item.total_price)}
|
||||
</td>
|
||||
</tr>
|
||||
</>
|
||||
<tr className='border-b border-t border-tools-table-outline border-base-content/5'>
|
||||
<th className='w-1/3 text-start not-first:font-medium text-base-content/50 text-sm px-4 py-3'>
|
||||
Label
|
||||
</th>
|
||||
<th className='text-start font-medium text-base-content/50 text-sm px-4 py-3'>
|
||||
<div className='flex w-full flex-row gap-1 items-center justify-between h-full'>
|
||||
<div>Value</div>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<>
|
||||
{approvalStepNumber !== 1 && (
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Tanggal Pengiriman</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
{item.delivery_date
|
||||
? formatDate(item.delivery_date, 'DD MMM YYYY')
|
||||
: '-'}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{item.do_number && (
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>No. Pengiriman</td>
|
||||
<td className='text-sm px-4 py-3'>{item.do_number}</td>
|
||||
</tr>
|
||||
)}
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>No. Polisi</td>
|
||||
<td className='text-sm px-4 py-3'>{item.vehicle_number}</td>
|
||||
</tr>
|
||||
{parentDoItem && (
|
||||
<tr>
|
||||
<td className='text-sm px-4 py-3'>Dokumen Pengiriman</td>
|
||||
<td className='text-sm px-4 py-3'>
|
||||
<DeliveryOrderExport
|
||||
data={marketing}
|
||||
deliveryOrder={parentDoItem}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='size-full flex flex-col relative overflow-x-hidden gap-3'>
|
||||
{data.map((item) => (
|
||||
<div key={`table-${item.id}`}>
|
||||
{formType === 'success' ? (
|
||||
<div className='rounded-lg border border-tools-table-outline border-base-content/5'>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>{renderTableContent(item)}</tbody>
|
||||
</table>
|
||||
{hasDeliveryOrder
|
||||
? deliveryItems.map((item, index) => (
|
||||
<div key={`do-table-${item.product_warehouse?.id}-${index}`}>
|
||||
{formType === 'success' ? (
|
||||
<div className='rounded-lg border border-tools-table-outline border-base-content/5'>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>
|
||||
{renderDeliveryOrderContent(item)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<Card
|
||||
key={`do-table-${item.product_warehouse?.id}-${index}`}
|
||||
title={item.product_warehouse?.product?.name || 'Produk'}
|
||||
collapsible={true}
|
||||
defaultCollapsed={false}
|
||||
variant='bordered'
|
||||
className={{
|
||||
wrapper: 'w-full rounded-lg',
|
||||
body: 'p-0',
|
||||
title: 'px-2 py-1.5 font-normal text-sm',
|
||||
collapsible: 'rounded-lg',
|
||||
}}
|
||||
>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>
|
||||
{renderDeliveryOrderContent(item)}
|
||||
</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Card
|
||||
key={`table-${item.id}`}
|
||||
title={
|
||||
item.marketing_product?.product_warehouse?.label || 'Produk'
|
||||
}
|
||||
collapsible={true}
|
||||
defaultCollapsed={false}
|
||||
variant='bordered'
|
||||
className={{
|
||||
wrapper: 'w-full rounded-lg',
|
||||
body: 'p-0',
|
||||
title: 'px-2 py-1.5 font-normal text-sm',
|
||||
collapsible: 'rounded-lg',
|
||||
}}
|
||||
>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>{renderTableContent(item)}</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
))
|
||||
: data.map((item) => (
|
||||
<div key={`table-${item.id}`}>
|
||||
{formType === 'success' ? (
|
||||
<div className='rounded-lg border border-tools-table-outline border-base-content/5'>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>
|
||||
{renderSalesOrderContent(item)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
) : (
|
||||
<Card
|
||||
key={`table-${item.id}`}
|
||||
title={
|
||||
item.marketing_product?.product_warehouse?.label ||
|
||||
'Produk'
|
||||
}
|
||||
collapsible={true}
|
||||
defaultCollapsed={false}
|
||||
variant='bordered'
|
||||
className={{
|
||||
wrapper: 'w-full rounded-lg',
|
||||
body: 'p-0',
|
||||
title: 'px-2 py-1.5 font-normal text-sm',
|
||||
collapsible: 'rounded-lg',
|
||||
}}
|
||||
>
|
||||
<table
|
||||
style={{
|
||||
borderRadius: '0.5rem',
|
||||
}}
|
||||
className='border-none w-full'
|
||||
>
|
||||
<tbody className='w-full'>
|
||||
{renderSalesOrderContent(item)}
|
||||
</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user