From 1a938b4218915c257c07b65da4f1fcf1d7af7e0c Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 10:31:16 +0700 Subject: [PATCH 01/15] refactor(FE): Use StatusBadge instead of PillBadge --- .../pages/expense/ExpenseStatusBadge.tsx | 35 +++++++++---------- .../pages/expense/RealizationStatusBadge.tsx | 25 +++++++------ 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/components/pages/expense/ExpenseStatusBadge.tsx b/src/components/pages/expense/ExpenseStatusBadge.tsx index a7fcb3e9..eee84224 100644 --- a/src/components/pages/expense/ExpenseStatusBadge.tsx +++ b/src/components/pages/expense/ExpenseStatusBadge.tsx @@ -1,6 +1,7 @@ -import PillBadge from '@/components/PillBadge'; +import StatusBadge from '@/components/helper/StatusBadge'; import { BaseApproval } from '@/types/api/api-general'; +import { Color } from '@/types/theme'; interface ExpenseStatusBadgeProps { approval?: BaseApproval; @@ -11,49 +12,45 @@ const ExpenseStatusBadge = ({ approval }: ExpenseStatusBadgeProps) => { const latestApprovalStepNumber = approval?.step_number; - let expenseStatusPillBadgeColor: - | 'yellow' - | 'green' - | 'gray' - | 'red' - | 'purple' - | 'blue' = 'gray'; + let expenseStatusBadgeColor: Color = 'neutral'; switch (latestApprovalStepNumber) { case 1: - expenseStatusPillBadgeColor = 'gray'; + expenseStatusBadgeColor = 'neutral'; break; case 2: - expenseStatusPillBadgeColor = 'purple'; + expenseStatusBadgeColor = 'info'; break; case 3: - expenseStatusPillBadgeColor = 'blue'; + expenseStatusBadgeColor = 'warning'; break; case 4: - expenseStatusPillBadgeColor = 'yellow'; + expenseStatusBadgeColor = 'error'; break; case 5: - expenseStatusPillBadgeColor = 'green'; + expenseStatusBadgeColor = 'success'; break; case 6: - expenseStatusPillBadgeColor = 'green'; + expenseStatusBadgeColor = 'success'; break; } if (isLatestApprovalRejected) { - expenseStatusPillBadgeColor = 'red'; + expenseStatusBadgeColor = 'error'; } return ( - ); }; diff --git a/src/components/pages/expense/RealizationStatusBadge.tsx b/src/components/pages/expense/RealizationStatusBadge.tsx index 720c1d03..d04d35c3 100644 --- a/src/components/pages/expense/RealizationStatusBadge.tsx +++ b/src/components/pages/expense/RealizationStatusBadge.tsx @@ -1,6 +1,7 @@ -import PillBadge from '@/components/PillBadge'; +import StatusBadge from '@/components/helper/StatusBadge'; import { BaseApproval } from '@/types/api/api-general'; +import { Color } from '@/types/theme'; interface RealizationStatusBadgeProps { approval?: BaseApproval; @@ -15,23 +16,21 @@ const RealizationStatusBadge = ({ approval }: RealizationStatusBadgeProps) => { ? 'Sudah Realisasi' : 'Belum Realisasi'; - let realizationStatusPillBadgeColor: - | 'yellow' - | 'green' - | 'gray' - | 'red' - | 'purple' - | 'blue' = isExpenseRealized ? 'green' : 'yellow'; + let realizationStatusBadgeColor: Color = isExpenseRealized + ? 'success' + : 'warning'; if (isLatestApprovalRejected) { - realizationStatusPillBadgeColor = 'red'; + realizationStatusBadgeColor = 'error'; } return ( - ); }; From 758a0cd9a77b0c0cfc2dc6eed6a5e712011fd711 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 10:46:58 +0700 Subject: [PATCH 02/15] refactor(FE): Update Add button styles and labels --- .../pages/production/recording/RecordingTable.tsx | 7 +++---- src/components/pages/purchase/PurchaseTable.tsx | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/pages/production/recording/RecordingTable.tsx b/src/components/pages/production/recording/RecordingTable.tsx index 36a4e69a..a67f44f9 100644 --- a/src/components/pages/production/recording/RecordingTable.tsx +++ b/src/components/pages/production/recording/RecordingTable.tsx @@ -380,12 +380,11 @@ const RecordingTable = () => { diff --git a/src/components/pages/purchase/PurchaseTable.tsx b/src/components/pages/purchase/PurchaseTable.tsx index d0c72dac..11543eca 100644 --- a/src/components/pages/purchase/PurchaseTable.tsx +++ b/src/components/pages/purchase/PurchaseTable.tsx @@ -319,12 +319,11 @@ const PurchaseTable = () => { From bb83acbe81ff2873022cb80964463583a336e691 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 11:11:28 +0700 Subject: [PATCH 03/15] refactor(FE): Render previews for multiple uniformities --- .../production/uniformity/UniformityTable.tsx | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/components/pages/production/uniformity/UniformityTable.tsx b/src/components/pages/production/uniformity/UniformityTable.tsx index a3530032..9bb79fa9 100644 --- a/src/components/pages/production/uniformity/UniformityTable.tsx +++ b/src/components/pages/production/uniformity/UniformityTable.tsx @@ -1129,15 +1129,12 @@ const UniformityTable = () => { }} >
- {selectedRowIds.length === 1 ? ( + {selectedUniformities.map((uniformity) => ( - ) : ( -
- {selectedRowIds.length} data dipilih -
- )} + ))}
@@ -1146,7 +1143,11 @@ const UniformityTable = () => { type='success' iconPosition='left' text={`Approve This Submission?`} - subtitleText={`Are you sure you want to approve this submission? (${selectedRowIds.length} data)`} + subtitleText={ + selectedRowIds.length === 1 + ? 'Are you sure you want to approve this submission?' + : `Are you sure you want to approve these submissions? (${selectedRowIds.length} data)` + } secondaryButton={{ text: 'Cancel', }} @@ -1161,7 +1162,12 @@ const UniformityTable = () => { }} >
- + {selectedUniformities.map((uniformity) => ( + + ))}
@@ -1185,15 +1191,12 @@ const UniformityTable = () => { }} >
- {selectedRowIds.length === 1 ? ( + {selectedUniformities.map((uniformity) => ( - ) : ( -
- {selectedRowIds.length} data dipilih -
- )} + ))}
@@ -1202,7 +1205,11 @@ const UniformityTable = () => { type='error' iconPosition='left' text={`Reject This Submission?`} - subtitleText={`Are you sure you want to reject this submission? (${selectedRowIds.length} data)`} + subtitleText={ + selectedRowIds.length === 1 + ? 'Are you sure you want to reject this submission?' + : `Are you sure you want to reject these submissions? (${selectedRowIds.length} data)` + } secondaryButton={{ text: 'Cancel', }} @@ -1217,15 +1224,12 @@ const UniformityTable = () => { }} >
- {selectedRowIds.length === 1 ? ( + {selectedUniformities.map((uniformity) => ( - ) : ( -
- {selectedRowIds.length} data dipilih -
- )} + ))}
From e5d6be446a099e7e648f1f0e3bd118a0e05a17ff Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 11:23:07 +0700 Subject: [PATCH 04/15] refactor(FE): Enable closing modals on backdrop click --- .../pages/production/uniformity/UniformityTable.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/pages/production/uniformity/UniformityTable.tsx b/src/components/pages/production/uniformity/UniformityTable.tsx index 9bb79fa9..39112b47 100644 --- a/src/components/pages/production/uniformity/UniformityTable.tsx +++ b/src/components/pages/production/uniformity/UniformityTable.tsx @@ -1058,7 +1058,7 @@ const UniformityTable = () => { iconPosition='left' text='Data Berhasil Ditambahkan' subtitleText='Data uniformity telah berhasil disimpan.' - closeOnBackdrop={false} + closeOnBackdrop={true} primaryButton={{ text: 'Ok', color: 'primary', @@ -1089,6 +1089,7 @@ const UniformityTable = () => { ref={singleDeleteModal.ref} type='error' iconPosition='left' + closeOnBackdrop={true} text={`Delete This Data?`} subtitleText='Are you sure you want to delete this data?' secondaryButton={{ @@ -1113,6 +1114,7 @@ const UniformityTable = () => { ref={singleApproveModal.ref} type='success' iconPosition='left' + closeOnBackdrop={true} text='Approve This Submission?' subtitleText='Are you sure you want to approve this submission?' secondaryButton={{ @@ -1142,6 +1144,7 @@ const UniformityTable = () => { ref={bulkApproveModal.ref} type='success' iconPosition='left' + closeOnBackdrop={true} text={`Approve This Submission?`} subtitleText={ selectedRowIds.length === 1 @@ -1175,6 +1178,7 @@ const UniformityTable = () => { ref={singleRejectModal.ref} type='error' iconPosition='left' + closeOnBackdrop={true} text='Reject This Submission?' subtitleText='Are you sure you want to reject this submission?' secondaryButton={{ @@ -1204,6 +1208,7 @@ const UniformityTable = () => { ref={bulkRejectModal.ref} type='error' iconPosition='left' + closeOnBackdrop={true} text={`Reject This Submission?`} subtitleText={ selectedRowIds.length === 1 From 12c7e566048e03aacd03ec1e7e9a9fee4a327dcb Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 3 Feb 2026 11:45:33 +0700 Subject: [PATCH 05/15] fix(FE): fixing line chart dashboard --- src/components/pages/dashboard/chart/DashboardLineChart.tsx | 2 +- src/components/pages/dashboard/export/DashboardExportCharts.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/pages/dashboard/chart/DashboardLineChart.tsx b/src/components/pages/dashboard/chart/DashboardLineChart.tsx index 58749cf2..7b8d35a1 100644 --- a/src/components/pages/dashboard/chart/DashboardLineChart.tsx +++ b/src/components/pages/dashboard/chart/DashboardLineChart.tsx @@ -67,7 +67,7 @@ const lineColors: Record = { act_fcr: '#10B981', std_fcr: '#10B981', act_fcr_cum: '#F52419', - std_fcr_cum: '#10B981', + std_fcr_cum: '#F52419', normal: '#10B981', abnormal: '#F52419', act_deplesi: '#10B981', diff --git a/src/components/pages/dashboard/export/DashboardExportCharts.tsx b/src/components/pages/dashboard/export/DashboardExportCharts.tsx index ba0b2fe2..3281dbf8 100644 --- a/src/components/pages/dashboard/export/DashboardExportCharts.tsx +++ b/src/components/pages/dashboard/export/DashboardExportCharts.tsx @@ -66,7 +66,7 @@ const lineColors: Record = { act_fcr: '#10B981', std_fcr: '#10B981', act_fcr_cum: '#F52419', - std_fcr_cum: '#10B981', + std_fcr_cum: '#F52419', normal: '#10B981', abnormal: '#F52419', act_deplesi: '#10B981', From 489e8a31f39b68b77a5947031f9bc02393cad0fc Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 11:46:45 +0700 Subject: [PATCH 06/15] refactor(FE): Make ConfirmationModal body scrollable and sticky --- src/components/modal/ConfirmationModal.tsx | 129 +++++++++++---------- 1 file changed, 70 insertions(+), 59 deletions(-) diff --git a/src/components/modal/ConfirmationModal.tsx b/src/components/modal/ConfirmationModal.tsx index 89b8fbd9..6c9255e0 100644 --- a/src/components/modal/ConfirmationModal.tsx +++ b/src/components/modal/ConfirmationModal.tsx @@ -122,10 +122,18 @@ const ConfirmationModal = ({ closeOnBackdrop={closeOnBackdrop} className={{ ...className, - modalBox: cn('rounded-xl p-4', className?.modalBox), + modalBox: cn( + 'rounded-xl p-4 flex flex-col gap-4 max-h-[90vh]', + className?.modalBox + ), }} > -
+
{iconPosition === 'center' ? ( <>
@@ -164,71 +172,74 @@ const ConfirmationModal = ({
)} +
- {children &&
{children}
} + {children && ( +
{children}
+ )} - {(secondaryButton || primaryButton) && ( -
- {secondaryButton && secondaryButton.text && ( - - )} + }} + className={cn( + 'p-2 rounded-xl text-sm', + secondaryButton?.className + )} + > + {secondaryButton?.text ?? 'Tidak'} + + )} - {primaryButton && primaryButton.text && ( - - )} -
- )} - + {primaryButton && primaryButton.text && ( + + )} + + )} ); }; From 43afd35e54b9ce8ad60205f45b90d1f482e378a0 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 11:56:25 +0700 Subject: [PATCH 07/15] refactor(FE): Update add buttons styling and labels --- src/components/pages/expense/ExpensesTable.tsx | 7 +++---- src/components/pages/inventory/movement/MovementTable.tsx | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/components/pages/expense/ExpensesTable.tsx b/src/components/pages/expense/ExpensesTable.tsx index d2d4754c..6d992e30 100644 --- a/src/components/pages/expense/ExpensesTable.tsx +++ b/src/components/pages/expense/ExpensesTable.tsx @@ -596,12 +596,11 @@ const ExpensesTable = () => { diff --git a/src/components/pages/inventory/movement/MovementTable.tsx b/src/components/pages/inventory/movement/MovementTable.tsx index 4a155c1c..c0d51a50 100644 --- a/src/components/pages/inventory/movement/MovementTable.tsx +++ b/src/components/pages/inventory/movement/MovementTable.tsx @@ -151,12 +151,11 @@ const MovementTable = () => { From 0febc9d8f31b30529c6f19f77a686778eaa3a466 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 3 Feb 2026 12:41:22 +0700 Subject: [PATCH 08/15] fix(FE): fixing line chart dashboard comparison --- .../dashboard/chart/DashboardLineChart.tsx | 80 ++++++++++--------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/src/components/pages/dashboard/chart/DashboardLineChart.tsx b/src/components/pages/dashboard/chart/DashboardLineChart.tsx index 7b8d35a1..bfb13d9a 100644 --- a/src/components/pages/dashboard/chart/DashboardLineChart.tsx +++ b/src/components/pages/dashboard/chart/DashboardLineChart.tsx @@ -659,44 +659,50 @@ const DashboardLineChart = ({ seriesData = comparisonChart?.series || []; } - return seriesData - .filter((series) => visibleSeries.has(series.id)) - .map((series, index) => { - const isStandard = series.id - .toString() - .toLowerCase() - .includes('std'); - // Use series.id directly as dataKey to match dataset fields - const dataKey = series.id.toString(); + return seriesData.map((series, originalIndex) => { + // Skip rendering if series is not visible + if (!visibleSeries.has(series.id)) { + return null; + } - return ( - - ); - }); + const isStandard = series.id + .toString() + .toLowerCase() + .includes('std'); + const dataKey = series.id.toString(); + + return ( + + ); + }); })()} From c102a4043c639d47639efd6cc5557e50798f0852 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 3 Feb 2026 13:40:46 +0700 Subject: [PATCH 09/15] fix(FE): fixing status badge color --- src/components/helper/StatusBadge.tsx | 2 ++ .../pages/closing/ClosingOverheadTable.tsx | 18 +++++++++--------- .../report/finance/tab/DebtSupplierTab.tsx | 11 +++++++++-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/components/helper/StatusBadge.tsx b/src/components/helper/StatusBadge.tsx index f9725fff..c90ddaee 100644 --- a/src/components/helper/StatusBadge.tsx +++ b/src/components/helper/StatusBadge.tsx @@ -28,6 +28,7 @@ const StatusBadge = ({ 'bg-error/20': color === 'error', 'bg-primary/20': color === 'info', 'bg-[#FF9A20]/12': color === 'warning', + 'bg-[#1166EF]/12': color === 'primary', }, className?.badge ), @@ -45,6 +46,7 @@ const StatusBadge = ({ 'text-error': color === 'error', 'text-primary': color === 'info', 'text-[#FF9A20]': color === 'warning', + 'text-[#1166EF]': color === 'primary', })} > diff --git a/src/components/pages/closing/ClosingOverheadTable.tsx b/src/components/pages/closing/ClosingOverheadTable.tsx index 0d51ae3b..a7a170eb 100644 --- a/src/components/pages/closing/ClosingOverheadTable.tsx +++ b/src/components/pages/closing/ClosingOverheadTable.tsx @@ -250,29 +250,29 @@ const ClosingOverheadTable = ({ body: 'p-4 shadow-button-soft border border-base-content/10 rounded-lg', }} > -
+

Pembelian Kandang

-
-
+
+
Populasi Akhir KANDANG{' '} Pemakaian Di FARM
-
-
+
+
Populasi Akhir Proyek
-
-
+
+
{formatNumber(chickinPopulation ?? 0)} {formatCurrency( @@ -281,8 +281,8 @@ const ClosingOverheadTable = ({ : 0 )}
-
-
+
+
{formatNumber(generalInformation?.population ?? 0)}
diff --git a/src/components/pages/report/finance/tab/DebtSupplierTab.tsx b/src/components/pages/report/finance/tab/DebtSupplierTab.tsx index 646cfb15..88e5a693 100644 --- a/src/components/pages/report/finance/tab/DebtSupplierTab.tsx +++ b/src/components/pages/report/finance/tab/DebtSupplierTab.tsx @@ -36,7 +36,6 @@ import SelectInputRadio from '@/components/input/SelectInputRadio'; import { useFinanceTabStore } from '@/stores/finance-tab/finance-tab.store'; import StatusBadge from '@/components/helper/StatusBadge'; import DebtSupplierSkeleton from '@/components/pages/report/finance/skeleton/DebtSupplierSkeleton'; -import DataStateSkeleton from '@/components/helper/skeleton/DataStateSkeleton'; const dueStatus: Record = { 'Sudah Jatuh Tempo': 'error', @@ -60,7 +59,15 @@ const getPillBadge = ( ? dueStatus[statusText] || 'neutral' : paymentStatus[statusText] || 'neutral'; - return ; + return ( + + ); }; interface DebtSupplierTabProps { From 40411b0417431a21d44dd8733f9ac222d70ebdcf Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 3 Feb 2026 14:12:08 +0700 Subject: [PATCH 10/15] fix(FE): fixing total text color debt supplier --- .../pages/report/finance/tab/DebtSupplierTab.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/pages/report/finance/tab/DebtSupplierTab.tsx b/src/components/pages/report/finance/tab/DebtSupplierTab.tsx index 88e5a693..5e7781bf 100644 --- a/src/components/pages/report/finance/tab/DebtSupplierTab.tsx +++ b/src/components/pages/report/finance/tab/DebtSupplierTab.tsx @@ -473,7 +473,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => { footer: () => { const value = supplier?.total.total_price; return ( -
+
{formatCurrency(value || 0)}
); @@ -495,7 +497,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => { footer: () => { const value = supplier?.total.payment_price; return ( -
+
{formatCurrency(value || 0)}
); @@ -517,7 +521,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => { footer: () => { const value = supplier?.total.debt_price; return ( -
+
{formatCurrency(value || 0)}
); From f31eb8db59f0b47b2dc7c358a3cb46fc50246f0b Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Feb 2026 14:20:32 +0700 Subject: [PATCH 11/15] refactor(FE): Show pending stock usage and depletions in detail --- .../recording/form/RecordingForm.tsx | 794 ++++++++++-------- 1 file changed, 421 insertions(+), 373 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 94f078c1..b8b6b1fc 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -48,6 +48,7 @@ import { UpdateLayingRecordingPayload, Recording, NextDayRecording, + RecordingStock, } from '@/types/api/production/recording'; import { type BaseApiResponse } from '@/types/api/api-general'; import { @@ -1103,14 +1104,51 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { [formik.values.stocks, type] ); + const getStockPendingInfo = useCallback( + (productWarehouseId: number) => { + if ((type === 'edit' || type === 'detail') && initialValues?.stocks) { + const existingStock = initialValues.stocks.find( + (s) => s.product_warehouse_id === productWarehouseId + ) as RecordingStock | undefined; + if (existingStock) { + return { + usageAmount: existingStock.usage_amount ?? 0, + pendingQty: existingStock.pending_qty ?? 0, + }; + } + } + return { + usageAmount: 0, + pendingQty: 0, + }; + }, + [initialValues, type] + ); + const getStockUsageAdornment = useCallback( (stockIdx: number) => { - if ((type as 'add' | 'edit' | 'detail') === 'detail') return null; const stock = formik.values.stocks?.[stockIdx]; if (!stock || !stock.product_warehouse_id) return null; + + const isDetail = (type as 'add' | 'edit' | 'detail') === 'detail'; const availableStock = getAvailableStock(stock.product_warehouse_id); const requestedUsage = Number(stock.qty) || 0; const remainingStock = availableStock - requestedUsage; + const { pendingQty } = getStockPendingInfo(stock.product_warehouse_id); + + if (isDetail) { + if (pendingQty > 0) { + return ( + + (tersedia: {formatNumber(requestedUsage)} | pending:{' '} + {formatNumber(pendingQty)} | + pakai: {formatNumber(requestedUsage + pendingQty)}) + + ); + } + return null; + } + if (requestedUsage > 0) { return ( @@ -1127,7 +1165,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ); }, - [formik.values.stocks, getAvailableStock, type] + [formik.values.stocks, getAvailableStock, getStockPendingInfo, type] ); const getProjectFlockBadgeAdornment = useCallback(() => { @@ -2550,8 +2588,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { : null } /> - {(type as 'add' | 'edit' | 'detail') !== 'detail' && - getStockUsageAdornment(idx)} + {getStockUsageAdornment(idx)}
{(type as 'add' | 'edit' | 'detail') !== 'detail' && ( @@ -2604,209 +2641,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { {/* Depletions Table */} - -
- - - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - - )} - - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - - )} - - - - {formik.values.depletions?.map((depletion, idx) => ( - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - - )} - - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - - )} - - ))} - -
- 0 - } - onChange={( - e: React.ChangeEvent - ) => { - if (e.target.checked) { - setSelectedDepletions( - formik.values.depletions?.map( - (_, idx) => idx - ) ?? [] - ); - } else { - setSelectedDepletions([]); - } - }} - classNames={{ - wrapper: 'flex justify-center', - checkbox: 'checkbox checkbox-sm', - }} - /> - KondisiJumlahAction
- - ) => { - if (e.target.checked) { - setSelectedDepletions([ - ...selectedDepletions, - idx, - ]); - } else { - setSelectedDepletions( - selectedDepletions.filter((i) => i !== idx) - ); - } - }} - classNames={{ - wrapper: 'flex justify-center', - checkbox: 'checkbox checkbox-sm', - }} - /> - - - product.value === depletion.product_warehouse_id - ) || null - } - onChange={(selectedOption) => { - const option = selectedOption as OptionType | null; - formik.setFieldValue( - `depletions.${idx}.product_warehouse_id`, - option?.value || 0 - ); - }} - options={getAvailableDepletionProductOptions(idx)} - placeholder='Pilih Kondisi' - isLoading={isLoadingDepletionProducts} - onMenuScrollToBottom={loadMoreDepletionProducts} - isError={ - isRepeaterInputError( - 'depletions', - 'product_warehouse_id', - idx - ).isError - } - errorMessage={ - isRepeaterInputError( - 'depletions', - 'product_warehouse_id', - idx - ).errorMessage - } - isDisabled={type === 'detail'} - className={{ - wrapper: 'w-full min-w-48', - }} - isSearchable - isClearable={type !== 'detail'} - /> - - - -
- -
-
-
- {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( -
- {selectedDepletions.length > 0 && ( - - )} - -
- )} -
- - {/* Eggs Table - Only for LAYING Category */} - {isLayingCategory && ( + {((type as 'add' | 'edit' | 'detail') !== 'detail' || + (formik.values.depletions?.length ?? 0) > 0) && ( { {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( 0 + formik.values.depletions?.length === + selectedDepletions.length && + formik.values.depletions?.length > 0 } onChange={( e: React.ChangeEvent ) => { if (e.target.checked) { - setSelectedEggs( - ( - formik.values as RecordingLayingFormValues - ).eggs?.map((_, idx) => idx) ?? [] + setSelectedDepletions( + formik.values.depletions?.map( + (_, idx) => idx + ) ?? [] ); } else { - setSelectedEggs([]); + setSelectedDepletions([]); } }} classNames={{ @@ -2846,201 +2683,412 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { /> )} - Kondisi Telur + Kondisi Jumlah - - Total Berat (Kilogram) - - - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( Action )} - {(formik.values as RecordingLayingFormValues).eggs?.map( - (egg, idx) => ( - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - - - ) => { - if (e.target.checked) { - setSelectedEggs([...selectedEggs, idx]); - } else { - setSelectedEggs( - selectedEggs.filter((i) => i !== idx) - ); - } - }} - classNames={{ - wrapper: 'flex justify-center', - checkbox: 'checkbox checkbox-sm', - }} - /> - - )} - - - product.value === egg.product_warehouse_id - ) || null - } - onChange={(selectedOption) => { - const option = - selectedOption as OptionType | null; - formik.setFieldValue( - `eggs.${idx}.product_warehouse_id`, - option?.value || 0 - ); + {formik.values.depletions?.map((depletion, idx) => ( + + {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( + + + ) => { + if (e.target.checked) { + setSelectedDepletions([ + ...selectedDepletions, + idx, + ]); + } else { + setSelectedDepletions( + selectedDepletions.filter((i) => i !== idx) + ); + } }} - options={getAvailableEggProductOptions(idx)} - placeholder='Pilih Kondisi Telur' - isLoading={isLoadingEggProducts} - onMenuScrollToBottom={loadMoreEggProducts} - isError={ - isRepeaterInputError( - 'eggs', - 'product_warehouse_id', - idx - ).isError - } - errorMessage={ - isRepeaterInputError( - 'eggs', - 'product_warehouse_id', - idx - ).errorMessage - } - isDisabled={type === 'detail'} - className={{ - wrapper: 'w-full min-w-48', + classNames={{ + wrapper: 'flex justify-center', + checkbox: 'checkbox checkbox-sm', }} - isSearchable - isClearable={type !== 'detail'} /> + )} + + + product.value === + depletion.product_warehouse_id + ) || null + } + onChange={(selectedOption) => { + const option = + selectedOption as OptionType | null; + formik.setFieldValue( + `depletions.${idx}.product_warehouse_id`, + option?.value || 0 + ); + }} + options={getAvailableDepletionProductOptions(idx)} + placeholder='Pilih Kondisi' + isLoading={isLoadingDepletionProducts} + onMenuScrollToBottom={loadMoreDepletionProducts} + isError={ + isRepeaterInputError( + 'depletions', + 'product_warehouse_id', + idx + ).isError + } + errorMessage={ + isRepeaterInputError( + 'depletions', + 'product_warehouse_id', + idx + ).errorMessage + } + isDisabled={type === 'detail'} + className={{ + wrapper: 'w-full min-w-48', + }} + isSearchable + isClearable={type !== 'detail'} + /> + + + + + {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - +
+ +
- - - - {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( - -
- -
- - )} - - ) - )} + )} + + ))}
{(type as 'add' | 'edit' | 'detail') !== 'detail' && (
- {selectedEggs.length > 0 && ( + {selectedDepletions.length > 0 && ( )}
)} )} + {/* Eggs Table - Only for LAYING Category */} + {isLayingCategory && + ((type as 'add' | 'edit' | 'detail') !== 'detail' || + ((formik.values as RecordingLayingFormValues).eggs?.length ?? 0) > + 0) && ( + +
+ + + + {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( + + )} + + + + {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( + + )} + + + + {(formik.values as RecordingLayingFormValues).eggs?.map( + (egg, idx) => ( + + {(type as 'add' | 'edit' | 'detail') !== + 'detail' && ( + + )} + + + + {(type as 'add' | 'edit' | 'detail') !== + 'detail' && ( + + )} + + ) + )} + +
+ 0 + } + onChange={( + e: React.ChangeEvent + ) => { + if (e.target.checked) { + setSelectedEggs( + ( + formik.values as RecordingLayingFormValues + ).eggs?.map((_, idx) => idx) ?? [] + ); + } else { + setSelectedEggs([]); + } + }} + classNames={{ + wrapper: 'flex justify-center', + checkbox: 'checkbox checkbox-sm', + }} + /> + Kondisi TelurJumlah + Total Berat (Kilogram) + + + + Action
+ + ) => { + if (e.target.checked) { + setSelectedEggs([...selectedEggs, idx]); + } else { + setSelectedEggs( + selectedEggs.filter((i) => i !== idx) + ); + } + }} + classNames={{ + wrapper: 'flex justify-center', + checkbox: 'checkbox checkbox-sm', + }} + /> + + + product.value === egg.product_warehouse_id + ) || null + } + onChange={(selectedOption) => { + const option = + selectedOption as OptionType | null; + formik.setFieldValue( + `eggs.${idx}.product_warehouse_id`, + option?.value || 0 + ); + }} + options={getAvailableEggProductOptions(idx)} + placeholder='Pilih Kondisi Telur' + isLoading={isLoadingEggProducts} + onMenuScrollToBottom={loadMoreEggProducts} + isError={ + isRepeaterInputError( + 'eggs', + 'product_warehouse_id', + idx + ).isError + } + errorMessage={ + isRepeaterInputError( + 'eggs', + 'product_warehouse_id', + idx + ).errorMessage + } + isDisabled={type === 'detail'} + className={{ + wrapper: 'w-full min-w-48', + }} + isSearchable + isClearable={type !== 'detail'} + /> + + + + + +
+ +
+
+
+ {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( +
+ {selectedEggs.length > 0 && ( + + )} + +
+ )} +
+ )} +
{recordingFormErrorMessage && (
From c24cf7ed1a63fa804fd629c95d8b667b808cb9aa Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 3 Feb 2026 14:39:34 +0700 Subject: [PATCH 12/15] fix(FE): adding standard fcr to growing production standard --- .../form/ProductionStandardForm.schema.ts | 2 +- .../form/ProductionStandardForm.tsx | 104 +++++++++++------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts index eb59a9c0..86951db9 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.schema.ts @@ -32,7 +32,7 @@ const GrowingRepeaterFormSchema = Yup.object({ target_hen_house_production: Yup.number().optional(), target_egg_weight: Yup.number().optional(), target_egg_mass: Yup.number().optional(), - standard_fcr: Yup.number().optional(), + standard_fcr: Yup.number().required('Wajib diisi!'), }).optional(), }); diff --git a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx index c445a840..1b490fbb 100644 --- a/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx +++ b/src/components/pages/master-data/production-standard/form/ProductionStandardForm.tsx @@ -386,14 +386,6 @@ const ProductionStandardForm = ({ `${row.original.production_standard_details?.target_egg_mass} kg`, enableSorting: false, }, - { - header: 'FCR', - accessorFn: (row) => - row.production_standard_details?.standard_fcr, - cell: ({ row }) => - `${row.original.production_standard_details?.standard_fcr} g`, - enableSorting: false, - }, ] : []; @@ -468,6 +460,13 @@ const ProductionStandardForm = ({ return [ ...baseColumns, ...productionColumns, + { + header: 'FCR', + accessorFn: (row) => row.production_standard_details?.standard_fcr, + cell: ({ row }) => + `${row.original.production_standard_details?.standard_fcr} g`, + enableSorting: false, + }, ...uniformityColumns, ...(formType !== 'detail' ? [actionColumn] : []), ]; @@ -753,24 +752,46 @@ const ProductionStandardForm = ({ e.preventDefault(); // For GROWING category, clear production_standard_details errors and set default values + // but preserve standard_fcr since it's used for both LAYING and GROWING if (formik.values.project_category === 'GROWING') { - // Set default values for production_standard_details + // Set default values for production_standard_details, preserving standard_fcr formik.values.details?.forEach((detail) => { detail.production_standard_details = { target_hen_day_production: 0, target_hen_house_production: 0, target_egg_weight: 0, target_egg_mass: 0, - standard_fcr: 0, + standard_fcr: + detail.production_standard_details?.standard_fcr || 0, }; }); - // Clear any errors related to production_standard_details + // Clear errors only for LAYING-specific fields in production_standard_details + // Preserve standard_fcr error since it's required for both categories const currentErrors = { ...formik.errors }; if (currentErrors.details && Array.isArray(currentErrors.details)) { const cleanedDetails = currentErrors.details .map((detailError) => { if (detailError && typeof detailError === 'object') { + const prodDetails = ( + detailError as { + production_standard_details?: ProductionDetailsErrors; + } + ).production_standard_details; + + // If there's standard_fcr error, preserve it + if (prodDetails && prodDetails.standard_fcr) { + const { production_standard_details, ...rest } = + detailError; + return { + ...rest, + production_standard_details: { + standard_fcr: prodDetails.standard_fcr, + }, + }; + } + + // Otherwise, remove entire production_standard_details errors const { production_standard_details, ...rest } = detailError; return Object.keys(rest).length > 0 ? rest : undefined; } @@ -896,7 +917,7 @@ const ProductionStandardForm = ({ gridTemplateColumns: formik.values.project_category === 'LAYING' ? 'repeat(10, minmax(auto, 1fr)) minmax(auto, auto)' - : 'repeat(4, minmax(auto, 1fr)) minmax(auto, auto)', + : 'repeat(5, minmax(auto, 1fr)) minmax(auto, auto)', }} > - + )} + - - )} + ) + ) && + getProductionDetailsTouched( + repeaterFormik.touched + .production_standard_details, + 'standard_fcr' + ) + } + /> Date: Tue, 3 Feb 2026 16:45:49 +0700 Subject: [PATCH 13/15] chore: remove unncessary data and fix pagination for single selected project flock kandang --- .../production-result/ProductionResultContent.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/pages/report/production-result/ProductionResultContent.tsx b/src/components/pages/report/production-result/ProductionResultContent.tsx index 28d334e8..d79d4c94 100644 --- a/src/components/pages/report/production-result/ProductionResultContent.tsx +++ b/src/components/pages/report/production-result/ProductionResultContent.tsx @@ -242,9 +242,6 @@ const ProductionResultContent = () => { console.error(error); toast.error('Gagal melakukan export laporan hasil produksi! Coba lagi.'); } - // await ProductionResultReportApi.exportProductionResultToPdf( - // projectFlockKandangs - // ); setIsLoadingExportingToPdf(false); }; @@ -268,7 +265,12 @@ const ProductionResultContent = () => { } setProjectFlockKandangs([projectFlockKandangResponse.data]); - setProjectFlockKandangMetadata(projectFlockKandangResponse.meta); + setProjectFlockKandangMetadata({ + page: 1, + limit: 10, + total_pages: 1, + total_results: 1, + }); setIsLoadingSearch(false); return; } From 2918500585b68631dcc1c1b99b9ec2296e226e96 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 4 Feb 2026 10:05:03 +0700 Subject: [PATCH 14/15] chore: add is_approved query param when fetching project flock --- .../production/transfer-to-laying/TransferToLayingFormModal.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/pages/production/transfer-to-laying/TransferToLayingFormModal.tsx b/src/components/pages/production/transfer-to-laying/TransferToLayingFormModal.tsx index 399468c7..78de70e1 100644 --- a/src/components/pages/production/transfer-to-laying/TransferToLayingFormModal.tsx +++ b/src/components/pages/production/transfer-to-laying/TransferToLayingFormModal.tsx @@ -99,6 +99,7 @@ const TransferToLayingFormModal = () => { { category: 'GROWING', transfer_context: 'transfer_to_laying', + is_approved: 'true', } ); @@ -116,6 +117,7 @@ const TransferToLayingFormModal = () => { 'search', { category: 'LAYING', + is_approved: 'true', } ); From c3f4c9b1ec8ea0014b2c05c068f53e04b11665f5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 4 Feb 2026 10:15:35 +0700 Subject: [PATCH 15/15] chore: remove keepPreviousData in useSWR config when fetching sapronak --- .../pages/closing/ClosingIncomingSapronaksTable.tsx | 5 +---- .../pages/closing/ClosingOutgoingSapronaksTable.tsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/pages/closing/ClosingIncomingSapronaksTable.tsx b/src/components/pages/closing/ClosingIncomingSapronaksTable.tsx index eda7e756..3d3a9d70 100644 --- a/src/components/pages/closing/ClosingIncomingSapronaksTable.tsx +++ b/src/components/pages/closing/ClosingIncomingSapronaksTable.tsx @@ -48,10 +48,7 @@ const ClosingIncomingSapronaksTable = ({ const { data: incomingSapronaks, isLoading: isLoadingIncomingSapronaks } = useSWR( `${ClosingApi.basePath}/${projectFlockId}/sapronak${getTableFilterQueryString()}&type=incoming&kandang_id=${kandangId ? `${kandangId}` : ''}`, - ClosingApi.getAllIncomingSapronakFetcher, - { - keepPreviousData: true, - } + ClosingApi.getAllIncomingSapronakFetcher ); const [open, setOpen] = useState(true); diff --git a/src/components/pages/closing/ClosingOutgoingSapronaksTable.tsx b/src/components/pages/closing/ClosingOutgoingSapronaksTable.tsx index ac918561..acbbc52d 100644 --- a/src/components/pages/closing/ClosingOutgoingSapronaksTable.tsx +++ b/src/components/pages/closing/ClosingOutgoingSapronaksTable.tsx @@ -48,10 +48,7 @@ const ClosingOutgoingSapronaksTable = ({ const { data: outgoingSapronaks, isLoading: isLoadingOutgoingSapronaks } = useSWR( `${ClosingApi.basePath}/${projectFlockId}/sapronak${getTableFilterQueryString()}&type=outgoing&kandang_id=${kandangId ? `${kandangId}` : ''}`, - ClosingApi.getAllOutgoingSapronakFetcher, - { - keepPreviousData: true, - } + ClosingApi.getAllOutgoingSapronakFetcher ); const [open, setOpen] = useState(true);