From 80fd8bb7ba654ff0153a84dc5675873e1a839936 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 9 Dec 2025 13:28:14 +0700 Subject: [PATCH] feat(FE-344,345): Add CosExpeditionReportTable component --- .../CosExpeditionReportTable.tsx | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 src/components/pages/closing/hpp-ekspedisi/CosExpeditionReportTable.tsx diff --git a/src/components/pages/closing/hpp-ekspedisi/CosExpeditionReportTable.tsx b/src/components/pages/closing/hpp-ekspedisi/CosExpeditionReportTable.tsx new file mode 100644 index 00000000..b5aac35f --- /dev/null +++ b/src/components/pages/closing/hpp-ekspedisi/CosExpeditionReportTable.tsx @@ -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[] = useMemo( + () => [ + { + id: 'id', + accessorKey: 'id', + header: 'No', + cell: (props) => { + const isFooter = '_isFooter' in props.row.original; + if (isFooter) { + return ( +
+ {props.row.original.expedition_name} +
+ ); + } + 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 ( +
+ {formatCurrency(value)} +
+ ); + }, + }, + ], + [] + ); + + return ( + <> +
+
+

HPP Ekspedisi

+ + 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', + }} + /> + + + + + ); +}; + +export default CosExpeditionReportTable;