From a26099b5074dcde4584b05cc5f8f203cd1ece4b5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 9 Dec 2025 15:32:17 +0700 Subject: [PATCH 1/5] feat(FE-347): create ClosingProductionData type --- src/types/api/closing.d.ts | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/types/api/closing.d.ts b/src/types/api/closing.d.ts index 3f7ba816..f5ea7047 100644 --- a/src/types/api/closing.d.ts +++ b/src/types/api/closing.d.ts @@ -53,3 +53,38 @@ export type ClosingIncomingSapronak = { }; export type ClosingOutgoingSapronak = ClosingIncomingSapronak; + +export type ClosingProductionData = { + purchase: { + initial_population: number; + claim_culling: number; + final_population: number; + feed_in_kg: number; + feed_used_kg: number; + feed_used_per_head_kg: number; + }; + sales: { + sales_kg: number; + sales_head: number; + average_weight_kg: number; + average_price_per_kg: number; + }; + performance: { + depletion_head: number; + depletion_percentage: number; + age_days: number; + mortality_std: number; + mortality_act: number; + deff_mortality: number; + fcr_std: number; + fcr_act: number; + deff_fcr: number; + adg: number; + ip: number; + }; + variance: { + variance_head: number; + variance_head_percentage: number; + variance_feed_kg: number; + }; +}; From abf2735b86a3523a5cde360049dfed97282bdcb2 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 9 Dec 2025 15:46:12 +0700 Subject: [PATCH 2/5] feat(FE-347): add getProductionData method --- src/services/api/closing.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/services/api/closing.ts b/src/services/api/closing.ts index 041108d0..f3281dba 100644 --- a/src/services/api/closing.ts +++ b/src/services/api/closing.ts @@ -6,6 +6,7 @@ import { ClosingGeneralInformation, ClosingIncomingSapronak, ClosingOutgoingSapronak, + ClosingProductionData, } from '@/types/api/closing'; import { httpClient, httpClientFetcher } from '@/services/http/client'; import { BaseApiResponse } from '@/types/api/api-general'; @@ -49,6 +50,22 @@ export class ClosingApiService extends BaseApiService { return undefined; } } + + async getProductionData(id: number) { + try { + const getProductionDataPath = `${this.basePath}/${id}/production-data`; + const getProductionDataRes = await httpClient< + BaseApiResponse + >(getProductionDataPath); + + return getProductionDataRes; + } catch (error) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + return undefined; + } + } } export const ClosingApi = new ClosingApiService('/closing'); From 8b8702b1b87c335f09f5f756600dfdc30ecae0be Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 9 Dec 2025 15:51:33 +0700 Subject: [PATCH 3/5] feat(FE-346): create ClosingProductionDataTabContent component --- .../ClosingProductionDataTabContent.tsx | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 src/components/pages/closing/ClosingProductionDataTabContent.tsx diff --git a/src/components/pages/closing/ClosingProductionDataTabContent.tsx b/src/components/pages/closing/ClosingProductionDataTabContent.tsx new file mode 100644 index 00000000..ba8a12ed --- /dev/null +++ b/src/components/pages/closing/ClosingProductionDataTabContent.tsx @@ -0,0 +1,268 @@ +'use client'; + +import useSWR from 'swr'; +import { ClosingApi } from '@/services/api/closing'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { formatNumber } from '@/lib/helper'; + +interface ClosingProductionDataTabContentProps { + projectFlockId: number; +} + +const ClosingProductionDataTabContent = ({ + projectFlockId, +}: ClosingProductionDataTabContentProps) => { + const { data: productionData, isLoading } = useSWR( + `${ClosingApi.basePath}/${projectFlockId}/production-data`, + () => ClosingApi.getProductionData(projectFlockId) + ); + + if (isLoading) { + return ( +
+ +
+ ); + } + + if (!productionData || !isResponseSuccess(productionData)) { + return ( +
+ Gagal memuat data produksi. +
+ ); + } + + const { purchase, sales, performance, variance } = productionData.data; + + // Helper for consistent row styling + const DataRow = ({ + label, + value, + unit = '', + valueClassName = 'font-bold text-gray-800', + unitClassName = 'text-gray-500 w-12 text-right', + }: { + label: string; + value: string | number; + unit?: string; + valueClassName?: string; + unitClassName?: string; + }) => ( +
+ {label} +
+ {value} + {unit && {unit}} +
+
+ ); + + // Helper for rows with two values (e.g., Deplesi: Ekor & %) + const DoubleDataRow = ({ + label, + value1, + unit1, + value2, + unit2, + value1ClassName = 'font-bold text-gray-800', + value2ClassName = 'font-bold text-blue-500', + }: { + label: string; + value1: string | number; + unit1: string; + value2: string | number; + unit2: string; + value1ClassName?: string; + value2ClassName?: string; + }) => ( +
+ {label} +
+
+ {value1} + {unit1} +
+
+ {value2} + {unit2} +
+
+
+ ); + + return ( +
+

Data Produksi

+ +
+ {/* Left Column */} +
+ {/* Purchase Section */} +
+

+ Pembelian +

+
+ + + + + + +
+
+ + {/* Sales Section */} +
+

+ Penjualan +

+
+ + + + +
+
+
+ + {/* Divider Line (Absolute centered) */} +
+ + {/* Right Column */} +
+ {/* Performance Section */} +
+

+ Performance +

+
+ + + + + + + + + + +
+
+ + {/* Variance Section (Pushed to bottom) */} +
+

Selisih

+
+ + + +
+
+
+
+
+ ); +}; + +export default ClosingProductionDataTabContent; From 1567a4016f937d754a6107c033e3a2c970323a7e Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 9 Dec 2025 15:55:32 +0700 Subject: [PATCH 4/5] feat(FE-347): use ClosingProductionDataTabContent in dataProduksi tab --- src/components/pages/closing/ClosingDetail.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/pages/closing/ClosingDetail.tsx b/src/components/pages/closing/ClosingDetail.tsx index 147b3fbd..f917cfd8 100644 --- a/src/components/pages/closing/ClosingDetail.tsx +++ b/src/components/pages/closing/ClosingDetail.tsx @@ -6,9 +6,10 @@ import { Icon } from '@iconify/react'; import Button from '@/components/Button'; import Tabs from '@/components/Tabs'; import ClosingGeneralInformationTable from '@/components/pages/closing/ClosingGeneralInformationTable'; +import ClosingSapronakTabContent from '@/components/pages/closing/ClosingSapronakTabContent'; +import ClosingProductionDataTabContent from '@/components/pages/closing/ClosingProductionDataTabContent'; import { ClosingGeneralInformation } from '@/types/api/closing'; -import ClosingSapronakTabContent from './ClosingSapronakTabContent'; interface ClosingDetailProps { id: number; @@ -48,7 +49,7 @@ const ClosingDetail: React.FC = ({ id, initialValue }) => { { id: 'dataProduksi', label: 'Data Produksi', - content: 'Data Produksi', + content: , }, { id: 'keuangan', From 65b60cc464ebe0542a61bf7325c14a591f6055d4 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 15 Dec 2025 11:13:18 +0700 Subject: [PATCH 5/5] chore(FE-347): update closings API endpoint '/closings' --- src/services/api/closing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/api/closing.ts b/src/services/api/closing.ts index f3281dba..e2c604cc 100644 --- a/src/services/api/closing.ts +++ b/src/services/api/closing.ts @@ -68,4 +68,4 @@ export class ClosingApiService extends BaseApiService { } } -export const ClosingApi = new ClosingApiService('/closing'); +export const ClosingApi = new ClosingApiService('/closings');