mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
fix(FE): fixing closing overhead per kandang
This commit is contained in:
@@ -66,7 +66,13 @@ const ClosingDetail: React.FC<ClosingDetailProps> = ({
|
|||||||
{
|
{
|
||||||
id: 'overhead',
|
id: 'overhead',
|
||||||
label: 'Overhead',
|
label: 'Overhead',
|
||||||
content: <ClosingOverheadTabContent projectFlockId={id} />,
|
content: (
|
||||||
|
<ClosingOverheadTabContent
|
||||||
|
projectFlockId={id}
|
||||||
|
generalInformation={initialValue}
|
||||||
|
kandangData={kandangData}
|
||||||
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'hppEkspedisi',
|
id: 'hppEkspedisi',
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { formatNumber } from '@/lib/helper';
|
||||||
import { ClosingGeneralInformation } from '@/types/api/closing';
|
import { ClosingGeneralInformation } from '@/types/api/closing';
|
||||||
import { ProjectFlock } from '@/types/api/production/project-flock';
|
import { ProjectFlock } from '@/types/api/production/project-flock';
|
||||||
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
@@ -56,8 +57,8 @@ const ClosingGeneralInformationTable = ({
|
|||||||
<td>:</td>
|
<td>:</td>
|
||||||
<td>
|
<td>
|
||||||
{!kandangData
|
{!kandangData
|
||||||
? (initialValue?.population ?? 0)
|
? formatNumber(initialValue?.population || 0)
|
||||||
: (chickinPopulation ?? 0)}{' '}
|
: formatNumber(chickinPopulation || 0)}{' '}
|
||||||
Ekor
|
Ekor
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
import ClosingOverheadTable from '@/components/pages/closing/ClosingOverheadTable';
|
import ClosingOverheadTable from '@/components/pages/closing/ClosingOverheadTable';
|
||||||
|
import { ClosingGeneralInformation } from '@/types/api/closing';
|
||||||
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
|
|
||||||
interface ClosingOverheadTabContentProps {
|
interface ClosingOverheadTabContentProps {
|
||||||
projectFlockId: number;
|
projectFlockId: number;
|
||||||
|
generalInformation?: ClosingGeneralInformation;
|
||||||
|
kandangData?: ProjectFlockKandang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClosingOverheadTabContent = ({
|
const ClosingOverheadTabContent = ({
|
||||||
projectFlockId,
|
projectFlockId,
|
||||||
|
generalInformation,
|
||||||
|
kandangData,
|
||||||
}: ClosingOverheadTabContentProps) => {
|
}: ClosingOverheadTabContentProps) => {
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col gap-4'>
|
<div className='flex flex-col gap-4'>
|
||||||
{projectFlockId && (
|
{projectFlockId && (
|
||||||
<ClosingOverheadTable projectFlockId={projectFlockId} />
|
<ClosingOverheadTable
|
||||||
|
projectFlockId={projectFlockId}
|
||||||
|
generalInformation={generalInformation}
|
||||||
|
kandangData={kandangData}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,13 @@ import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
|||||||
import { isResponseSuccess } from '@/lib/api-helper';
|
import { isResponseSuccess } from '@/lib/api-helper';
|
||||||
import { cn, formatCurrency, formatDate, formatNumber } from '@/lib/helper';
|
import { cn, formatCurrency, formatDate, formatNumber } from '@/lib/helper';
|
||||||
import { ClosingApi } from '@/services/api/closing';
|
import { ClosingApi } from '@/services/api/closing';
|
||||||
import { Overhead, OverheadTotal } from '@/types/api/closing';
|
import {
|
||||||
|
ClosingGeneralInformation,
|
||||||
|
Overhead,
|
||||||
|
OverheadTotal,
|
||||||
|
} from '@/types/api/closing';
|
||||||
|
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
|
||||||
|
import { Icon } from '@iconify/react';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { useSearchParams } from 'next/navigation';
|
import { useSearchParams } from 'next/navigation';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
@@ -11,16 +17,30 @@ import useSWR from 'swr';
|
|||||||
|
|
||||||
interface ClosingOverheadTableProps {
|
interface ClosingOverheadTableProps {
|
||||||
projectFlockId: number;
|
projectFlockId: number;
|
||||||
|
generalInformation?: ClosingGeneralInformation;
|
||||||
|
kandangData?: ProjectFlockKandang;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClosingOverheadTable = ({
|
const ClosingOverheadTable = ({
|
||||||
projectFlockId,
|
projectFlockId,
|
||||||
|
generalInformation,
|
||||||
|
kandangData,
|
||||||
}: ClosingOverheadTableProps) => {
|
}: ClosingOverheadTableProps) => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const kandangId = searchParams.get('kandangId');
|
const kandangId = searchParams.get('kandangId');
|
||||||
|
|
||||||
const { data: overhead, isLoading: isLoadingOverhead } = useSWR(
|
const { data: overhead, isLoading: isLoadingOverhead } = useSWR(
|
||||||
`${ClosingApi.basePath}/${projectFlockId}${kandangId ? `/${kandangId}` : ''}/overhead`,
|
`${ClosingApi.basePath}/${projectFlockId}/overhead`,
|
||||||
|
() => ClosingApi.getOverhead(projectFlockId),
|
||||||
|
{
|
||||||
|
keepPreviousData: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: overheadKandang, isLoading: isLoadingOverheadKandang } = useSWR(
|
||||||
|
kandangId
|
||||||
|
? `${ClosingApi.basePath}/${projectFlockId}/${kandangId}/overhead`
|
||||||
|
: undefined,
|
||||||
() =>
|
() =>
|
||||||
ClosingApi.getOverhead(
|
ClosingApi.getOverhead(
|
||||||
projectFlockId,
|
projectFlockId,
|
||||||
@@ -31,6 +51,26 @@ const ClosingOverheadTable = ({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const chickinPopulation = useMemo(() => {
|
||||||
|
if (kandangData) {
|
||||||
|
return kandangData?.chickins?.reduce(
|
||||||
|
(acc, chickin) => acc + chickin.usage_qty,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}, [kandangData]);
|
||||||
|
|
||||||
|
const kandangTotal = useMemo(() => {
|
||||||
|
if (!isResponseSuccess(overhead)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const total =
|
||||||
|
((chickinPopulation ?? 0) * overhead.data.total.actual_total_amount) /
|
||||||
|
(generalInformation?.population ?? 0);
|
||||||
|
return total;
|
||||||
|
}, [overhead, chickinPopulation, generalInformation]);
|
||||||
|
|
||||||
// Helper function to create columns with footer support
|
// Helper function to create columns with footer support
|
||||||
const createColumns = (
|
const createColumns = (
|
||||||
total?: OverheadTotal,
|
total?: OverheadTotal,
|
||||||
@@ -44,17 +84,13 @@ const ClosingOverheadTable = ({
|
|||||||
{
|
{
|
||||||
id: 'budget_quantity',
|
id: 'budget_quantity',
|
||||||
header: 'Jumlah',
|
header: 'Jumlah',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatNumber(props.budget_quantity),
|
||||||
props.budget_quantity ? formatNumber(props.budget_quantity) : '-',
|
|
||||||
footer: total ? () => formatNumber(total.budget_quantity) : '',
|
footer: total ? () => formatNumber(total.budget_quantity) : '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'budget_unit_price',
|
id: 'budget_unit_price',
|
||||||
header: 'Harga Satuan',
|
header: 'Harga Satuan',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.budget_unit_price),
|
||||||
props.budget_unit_price
|
|
||||||
? formatCurrency(props.budget_unit_price)
|
|
||||||
: '-',
|
|
||||||
footer: '',
|
footer: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -78,34 +114,25 @@ const ClosingOverheadTable = ({
|
|||||||
id: 'actual_date',
|
id: 'actual_date',
|
||||||
header: 'Tanggal',
|
header: 'Tanggal',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) =>
|
||||||
props.actual_date
|
formatDate(props.actual_date, 'DD MMM, YYYY'),
|
||||||
? formatDate(props.actual_date, 'DD MMM, YYYY')
|
|
||||||
: '-',
|
|
||||||
footer: '',
|
footer: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_quantity',
|
id: 'actual_quantity',
|
||||||
header: 'Jumlah',
|
header: 'Jumlah',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatNumber(props.actual_quantity),
|
||||||
props.actual_quantity ? formatNumber(props.actual_quantity) : '-',
|
|
||||||
footer: total ? () => formatNumber(total.actual_quantity) : '',
|
footer: total ? () => formatNumber(total.actual_quantity) : '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_unit_price',
|
id: 'actual_unit_price',
|
||||||
header: 'Harga Satuan',
|
header: 'Harga Satuan',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.actual_unit_price),
|
||||||
props.actual_unit_price
|
|
||||||
? formatCurrency(props.actual_unit_price)
|
|
||||||
: '-',
|
|
||||||
footer: '',
|
footer: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_total_amount',
|
id: 'actual_total_amount',
|
||||||
header: 'Total',
|
header: 'Total',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.actual_total_amount),
|
||||||
props.actual_total_amount
|
|
||||||
? formatCurrency(props.actual_total_amount)
|
|
||||||
: '-',
|
|
||||||
footer: total
|
footer: total
|
||||||
? () => formatCurrency(total.actual_total_amount)
|
? () => formatCurrency(total.actual_total_amount)
|
||||||
: '',
|
: '',
|
||||||
@@ -118,35 +145,25 @@ const ClosingOverheadTable = ({
|
|||||||
{
|
{
|
||||||
id: 'actual_date',
|
id: 'actual_date',
|
||||||
header: 'Tanggal',
|
header: 'Tanggal',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatDate(props.actual_date, 'DD MMM, YYYY'),
|
||||||
props.actual_date
|
|
||||||
? formatDate(props.actual_date, 'DD MMM, YYYY')
|
|
||||||
: '-',
|
|
||||||
footer: '',
|
footer: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_quantity',
|
id: 'actual_quantity',
|
||||||
header: 'Jumlah',
|
header: 'Jumlah',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatNumber(props.actual_quantity),
|
||||||
props.actual_quantity ? formatNumber(props.actual_quantity) : '-',
|
|
||||||
footer: total ? () => formatNumber(total.actual_quantity) : '',
|
footer: total ? () => formatNumber(total.actual_quantity) : '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_unit_price',
|
id: 'actual_unit_price',
|
||||||
header: 'Harga Satuan',
|
header: 'Harga Satuan',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.actual_unit_price),
|
||||||
props.actual_unit_price
|
|
||||||
? formatCurrency(props.actual_unit_price)
|
|
||||||
: '-',
|
|
||||||
footer: '',
|
footer: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actual_total_amount',
|
id: 'actual_total_amount',
|
||||||
header: 'Total',
|
header: 'Total',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.actual_total_amount),
|
||||||
props.actual_total_amount
|
|
||||||
? formatCurrency(props.actual_total_amount)
|
|
||||||
: '-',
|
|
||||||
footer: total ? () => formatCurrency(total.actual_total_amount) : '',
|
footer: total ? () => formatCurrency(total.actual_total_amount) : '',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -171,8 +188,7 @@ const ClosingOverheadTable = ({
|
|||||||
{
|
{
|
||||||
id: 'cost_per_bird',
|
id: 'cost_per_bird',
|
||||||
header: 'Rp/Ekor',
|
header: 'Rp/Ekor',
|
||||||
accessorFn: (props) =>
|
accessorFn: (props) => formatCurrency(props.cost_per_bird),
|
||||||
props.cost_per_bird ? formatCurrency(props.cost_per_bird) : '-',
|
|
||||||
footer: total ? () => formatCurrency(total.cost_per_bird) : '',
|
footer: total ? () => formatCurrency(total.cost_per_bird) : '',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -183,11 +199,15 @@ const ClosingOverheadTable = ({
|
|||||||
() =>
|
() =>
|
||||||
isResponseSuccess(overhead)
|
isResponseSuccess(overhead)
|
||||||
? createColumns(
|
? createColumns(
|
||||||
overhead.data?.total,
|
kandangId
|
||||||
|
? isResponseSuccess(overheadKandang)
|
||||||
|
? overheadKandang.data?.total
|
||||||
|
: undefined
|
||||||
|
: overhead.data?.total,
|
||||||
kandangId ? Number(kandangId) : undefined
|
kandangId ? Number(kandangId) : undefined
|
||||||
)
|
)
|
||||||
: createColumns(),
|
: createColumns(),
|
||||||
[overhead]
|
[overhead, kandangId, overheadKandang]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -203,7 +223,13 @@ const ClosingOverheadTable = ({
|
|||||||
>
|
>
|
||||||
<Table<Overhead>
|
<Table<Overhead>
|
||||||
data={
|
data={
|
||||||
isResponseSuccess(overhead) ? (overhead.data?.overheads ?? []) : []
|
kandangId
|
||||||
|
? isResponseSuccess(overheadKandang)
|
||||||
|
? (overheadKandang.data?.overheads ?? [])
|
||||||
|
: []
|
||||||
|
: isResponseSuccess(overhead)
|
||||||
|
? (overhead.data?.overheads ?? [])
|
||||||
|
: []
|
||||||
}
|
}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
className={{
|
className={{
|
||||||
@@ -220,6 +246,60 @@ const ClosingOverheadTable = ({
|
|||||||
: false
|
: false
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
{kandangId && (
|
||||||
|
<Card
|
||||||
|
className={{
|
||||||
|
wrapper: 'w-full',
|
||||||
|
body: 'p-4 shadow-button-soft border border-base-content/10 rounded-lg',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='flex flex-row gap-4 w-full justify-center items-stretch'>
|
||||||
|
<div className='flex flex-row items-center justify-between'>
|
||||||
|
<h2 className='text-base font-bold'>Pembelian Kandang </h2>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col items-center justify-center'>
|
||||||
|
<Icon icon='heroicons:equals' className='inline' />
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col flex-1'>
|
||||||
|
<div className='flex flex-row items-center justify-center font-medium'>
|
||||||
|
Populasi Akhir KANDANG{' '}
|
||||||
|
<Icon icon='heroicons:x-mark' className='inline' /> Pemakaian
|
||||||
|
Di FARM
|
||||||
|
</div>
|
||||||
|
<hr className='w-full h-1' />
|
||||||
|
<div className='flex flex-row items-center justify-center font-medium'>
|
||||||
|
Populasi Akhir Proyek
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col items-center justify-center'>
|
||||||
|
<Icon icon='heroicons:equals' className='inline' />
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col flex-1'>
|
||||||
|
<div className='flex flex-row items-center justify-center font-medium'>
|
||||||
|
{formatNumber(chickinPopulation ?? 0)}
|
||||||
|
<Icon icon='heroicons:x-mark' className='inline' />
|
||||||
|
{formatCurrency(
|
||||||
|
isResponseSuccess(overhead)
|
||||||
|
? overhead.data?.total.actual_total_amount
|
||||||
|
: 0
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<hr className='w-full h-1' />
|
||||||
|
<div className='flex flex-row items-center justify-center font-medium'>
|
||||||
|
{formatNumber(generalInformation?.population ?? 0)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col items-center justify-center'>
|
||||||
|
<Icon icon='heroicons:equals' className='inline' />
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-row items-center justify-between'>
|
||||||
|
<h2 className='text-base font-bold'>
|
||||||
|
{formatNumber(kandangTotal || 0)}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user