mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
refactor(FE-344): Add Cost of Revenue Expedition table
This commit is contained in:
@@ -10,20 +10,24 @@ import ClosingGeneralInformationTable from '@/components/pages/closing/ClosingGe
|
||||
import {
|
||||
ClosingGeneralInformation,
|
||||
BaseClosingSales,
|
||||
BaseClosingCostOfRevenueExpedition,
|
||||
} from '@/types/api/closing';
|
||||
import ClosingSapronakTabContent from './ClosingSapronakTabContent';
|
||||
import SalesReportTable from './sale/SalesReportTable';
|
||||
import CostOfRevenueExpeditionReportTable from './hpp-ekspedisi/CostOfRevenueExpeditionReportTable';
|
||||
|
||||
interface ClosingDetailProps {
|
||||
id: number;
|
||||
initialValue?: ClosingGeneralInformation;
|
||||
salesData?: BaseClosingSales;
|
||||
costOfRevenueExpeditionData?: BaseClosingCostOfRevenueExpedition;
|
||||
}
|
||||
|
||||
const ClosingDetail: React.FC<ClosingDetailProps> = ({
|
||||
id,
|
||||
initialValue,
|
||||
salesData,
|
||||
costOfRevenueExpeditionData,
|
||||
}) => {
|
||||
const [activeTab, setActiveTab] = useState<string>('sapronak');
|
||||
|
||||
@@ -52,7 +56,11 @@ const ClosingDetail: React.FC<ClosingDetailProps> = ({
|
||||
{
|
||||
id: 'hppEkspedisi',
|
||||
label: 'HPP Ekspedisi',
|
||||
content: 'HPP Ekspedisi',
|
||||
content: (
|
||||
<CostOfRevenueExpeditionReportTable
|
||||
initialValues={costOfRevenueExpeditionData}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'dataProduksi',
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
'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;
|
||||
}
|
||||
|
||||
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 cosExpeditionColumns: ColumnDef<BaseCosExpedition>[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'id',
|
||||
accessorKey: 'id',
|
||||
header: 'No',
|
||||
cell: (props) => {
|
||||
return <div>{props.row.index + 1}</div>;
|
||||
},
|
||||
footer: () => (
|
||||
<div className='font-semibold text-gray-900'>Total HPP Ekspedisi</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'expedition_name',
|
||||
accessorKey: 'expedition_name',
|
||||
header: 'Nama Ekspedisi',
|
||||
cell: (props) => props.getValue() || '-',
|
||||
},
|
||||
{
|
||||
id: 'hpp',
|
||||
accessorKey: 'hpp',
|
||||
header: 'HPP Ekspedisi',
|
||||
cell: (props) => {
|
||||
const value = props.getValue() as number;
|
||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||
},
|
||||
footer: () => (
|
||||
<div className='text-right font-semibold text-gray-900'>
|
||||
{formatCurrency(totals.totalHpp)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
],
|
||||
[totals]
|
||||
);
|
||||
|
||||
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}
|
||||
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;
|
||||
@@ -0,0 +1,123 @@
|
||||
'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 {
|
||||
BaseClosingCostOfRevenueExpedition,
|
||||
BaseCostOfRevenueExpedition,
|
||||
} from '@/types/api/closing';
|
||||
|
||||
interface CostOfRevenueExpeditionReportTableProps {
|
||||
type?: 'detail';
|
||||
initialValues?: BaseClosingCostOfRevenueExpedition;
|
||||
}
|
||||
|
||||
const CostOfRevenueExpeditionReportTable = ({
|
||||
type = 'detail',
|
||||
initialValues,
|
||||
}: CostOfRevenueExpeditionReportTableProps) => {
|
||||
const costOfRevenueExpeditionData: BaseCostOfRevenueExpedition[] =
|
||||
useMemo(() => {
|
||||
return initialValues?.cos_expeditions || [];
|
||||
}, [initialValues]);
|
||||
|
||||
const totals = useMemo(() => {
|
||||
if (costOfRevenueExpeditionData.length === 0) {
|
||||
return {
|
||||
totalHpp: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const totalHpp = costOfRevenueExpeditionData.reduce(
|
||||
(sum, item) => sum + (item.hpp || 0),
|
||||
0
|
||||
);
|
||||
|
||||
return {
|
||||
totalHpp,
|
||||
};
|
||||
}, [costOfRevenueExpeditionData]);
|
||||
|
||||
const costOfRevenueExpeditionColumns: ColumnDef<BaseCostOfRevenueExpedition>[] =
|
||||
useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'id',
|
||||
accessorKey: 'id',
|
||||
header: 'No',
|
||||
cell: (props) => {
|
||||
return <div>{props.row.index + 1}</div>;
|
||||
},
|
||||
footer: () => (
|
||||
<div className='font-semibold text-gray-900'>
|
||||
Total HPP Ekspedisi
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'expedition_name',
|
||||
accessorKey: 'expedition_name',
|
||||
header: 'Nama Ekspedisi',
|
||||
cell: (props) => props.getValue() || '-',
|
||||
},
|
||||
{
|
||||
id: 'hpp',
|
||||
accessorKey: 'hpp',
|
||||
header: 'HPP Ekspedisi',
|
||||
cell: (props) => {
|
||||
const value = props.getValue() as number;
|
||||
return <div className='text-right'>{formatCurrency(value)}</div>;
|
||||
},
|
||||
footer: () => (
|
||||
<div className='text-right font-semibold text-gray-900'>
|
||||
{formatCurrency(totals.totalHpp)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
],
|
||||
[totals]
|
||||
);
|
||||
|
||||
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={costOfRevenueExpeditionData}
|
||||
columns={costOfRevenueExpeditionColumns}
|
||||
renderFooter={costOfRevenueExpeditionData.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 CostOfRevenueExpeditionReportTable;
|
||||
Vendored
+16
@@ -47,6 +47,22 @@ export type BaseClosing = {
|
||||
|
||||
export type Closing = BaseMetadata & BaseClosing;
|
||||
|
||||
export type BaseCostOfRevenueExpedition = {
|
||||
id: number;
|
||||
expedition_name: string;
|
||||
hpp: number;
|
||||
};
|
||||
|
||||
export type BaseClosingCostOfRevenueExpedition = {
|
||||
project_type: string;
|
||||
flock_id: number;
|
||||
period: number;
|
||||
cos_expeditions: BaseCostOfRevenueExpedition[];
|
||||
};
|
||||
|
||||
export type ClosingCostOfRevenueExpedition = BaseMetadata &
|
||||
BaseClosingCostOfRevenueExpedition;
|
||||
|
||||
export type BaseClosingGeneralInformation = BaseClosing & {
|
||||
flock_id: number;
|
||||
period: number;
|
||||
|
||||
Reference in New Issue
Block a user