feat(FE-344,345): Add CosExpeditionReportTable component

This commit is contained in:
rstubryan
2025-12-09 13:28:14 +07:00
parent 44b9f94cec
commit 80fd8bb7ba
@@ -0,0 +1,154 @@
'use client';
import React, { useMemo } from 'react';
import { ColumnDef } from '@tanstack/react-table';
import Table from '@/components/Table';
import Card from '@/components/Card';
import { formatCurrency } from '@/lib/helper';
import {
BaseClosingCosExpedition,
BaseCosExpedition,
} from '@/types/api/closing/closing';
interface CosExpeditionReportTableProps {
type?: 'detail';
initialValues?: BaseClosingCosExpedition;
}
interface FooterCosExpeditionRow extends BaseCosExpedition {
_isFooter: true;
}
const CosExpeditionReportTable = ({
type = 'detail',
initialValues,
}: CosExpeditionReportTableProps) => {
const cosExpeditionData: BaseCosExpedition[] = useMemo(() => {
return initialValues?.cos_expeditions || [];
}, [initialValues]);
const totals = useMemo(() => {
if (cosExpeditionData.length === 0) {
return {
totalHpp: 0,
};
}
const totalHpp = cosExpeditionData.reduce(
(sum, item) => sum + (item.hpp || 0),
0
);
return {
totalHpp,
};
}, [cosExpeditionData]);
const footerData = useMemo((): FooterCosExpeditionRow[] => {
if (cosExpeditionData.length === 0) return [];
const footerRow: FooterCosExpeditionRow = {
id: -999,
expedition_name: 'Total HPP Ekspedisi',
hpp: totals.totalHpp,
_isFooter: true,
};
return [footerRow];
}, [cosExpeditionData, totals]);
const cosExpeditionColumns: ColumnDef<BaseCosExpedition>[] = useMemo(
() => [
{
id: 'id',
accessorKey: 'id',
header: 'No',
cell: (props) => {
const isFooter = '_isFooter' in props.row.original;
if (isFooter) {
return (
<div className='font-semibold text-gray-900 col-span-2'>
{props.row.original.expedition_name}
</div>
);
}
return props.getValue() || '-';
},
},
{
id: 'expedition_name',
accessorKey: 'expedition_name',
header: 'Nama Ekspedisi',
cell: (props) => {
const isFooter = '_isFooter' in props.row.original;
if (isFooter) {
return null;
}
return props.getValue() || '-';
},
},
{
id: 'hpp',
accessorKey: 'hpp',
header: 'HPP Ekspedisi',
cell: (props) => {
const value = props.getValue() as number;
const isFooter = '_isFooter' in props.row.original;
return (
<div
className={
isFooter
? 'text-right font-semibold text-gray-900'
: 'text-right'
}
>
{formatCurrency(value)}
</div>
);
},
},
],
[]
);
return (
<>
<section className='w-full'>
<div className='p-4'>
<h2 className='text-xl font-semibold mb-4'>HPP Ekspedisi</h2>
<Card
className={{
wrapper: 'w-full bg-base-100',
body: 'p-0',
}}
>
<Table
data={cosExpeditionData}
columns={cosExpeditionColumns}
footerData={footerData}
renderFooter={cosExpeditionData.length > 0}
className={{
tableWrapperClassName: 'overflow-x-auto',
tableClassName: 'w-full table-auto text-sm',
headerRowClassName: 'border-b border-b-gray-200',
headerColumnClassName:
'px-4 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end whitespace-nowrap',
bodyRowClassName:
'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
bodyColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
tableFooterClassName:
'bg-gray-100 font-semibold border border-gray-200',
footerRowClassName: 'border-t-2 border-gray-300',
footerColumnClassName:
'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
}}
/>
</Card>
</div>
</section>
</>
);
};
export default CosExpeditionReportTable;