From fd4b584ccd0537fa965980cfb30e819c29223d67 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 21 Jan 2026 13:23:31 +0700 Subject: [PATCH 1/7] refactor(FE): Use kilograms for egg weight fields --- .../pages/production/recording/form/RecordingForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 17a1d020..30859656 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -2759,7 +2759,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} Kondisi Telur Jumlah - Berat (gram) + Total Berat (Kilogram) {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( Action )} @@ -2880,7 +2880,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { className={{ wrapper: 'w-full min-w-24', }} - placeholder='Masukkan berat telur (gram)...' + placeholder='Masukkan total berat telur (Kilogram)...' /> {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( From 507f53ace8cdbf3f069b854dfefad1052074a58b Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 21 Jan 2026 13:29:35 +0700 Subject: [PATCH 2/7] refactor(FE): Use projectFlockKandangId for next-day recording --- .../recording/form/RecordingForm.tsx | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 30859656..10558973 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -552,23 +552,17 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { ); const nextDayRecordingUrl = useMemo(() => { - if (!selectedProjectFlock) return null; - const projectFlockId = - typeof selectedProjectFlock.value === 'string' - ? parseInt(selectedProjectFlock.value, 10) - : selectedProjectFlock.value; - return `${RecordingApi.basePath}/next-day?project_flock_id=${projectFlockId}`; - }, [selectedProjectFlock]); + if (!projectFlockKandangLookup) return null; + const projectFlockKandangId = projectFlockKandangLookup.id; + return `${RecordingApi.basePath}/next-day?project_flock_kandang_id=${projectFlockKandangId}`; + }, [projectFlockKandangLookup]); const { data: nextDayRecordingData } = useSWR( nextDayRecordingUrl, nextDayRecordingUrl ? () => { - const projectFlockId = - typeof selectedProjectFlock!.value === 'string' - ? parseInt(selectedProjectFlock!.value, 10) - : selectedProjectFlock!.value; - return RecordingApi.nextDayRecording(projectFlockId); + const projectFlockKandangId = projectFlockKandangLookup!.id; + return RecordingApi.nextDayRecording(projectFlockKandangId); } : null ); From 99fc3f8cae97e4eecd756995560e5900117479f1 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 21 Jan 2026 13:45:12 +0700 Subject: [PATCH 3/7] refactor(FE): Standardize unit labels and number formatting --- .../recording/form/RecordingForm.tsx | 73 ++++++++----------- 1 file changed, 31 insertions(+), 42 deletions(-) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 10558973..5120bab2 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -156,39 +156,39 @@ const productionStandardColumns: ColumnDef[] = [ }, { accessorKey: 'egg_production_standard_detail.target_hen_house_production', - header: 'Target Hen House (%)', + header: 'Target Hen House (btr)', cell: (props) => - `${ + formatNumber( (props.row.original.egg_production_standard_detail ?.target_hen_house_production as number) || 0 - }%`, + ), }, { accessorKey: 'egg_production_standard_detail.target_egg_weight', - header: 'Target Egg Weight (gram)', + header: 'Target Egg Weight (g)', cell: (props) => - formatNumber( + `${ (props.row.original.egg_production_standard_detail ?.target_egg_weight as number) || 0 - ), + } g`, }, { accessorKey: 'egg_production_standard_detail.target_egg_mass', - header: 'Target Egg Mass (gram)', + header: 'Target Egg Mass (kg)', cell: (props) => - formatNumber( + `${ (props.row.original.egg_production_standard_detail ?.target_egg_mass as number) || 0 - ), + } kg`, }, { accessorKey: 'egg_production_standard_detail.standard_fcr', - header: 'Standard FCR', + header: 'Standard FCR (g)', cell: (props) => - formatNumber( + `${ (props.row.original.egg_production_standard_detail ?.standard_fcr as number) || 0 - ), + } g`, }, ]; @@ -2107,38 +2107,33 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { - FCR + FCR (g) {initialValues.fcr_value != null - ? formatNumber(initialValues.fcr_value) + ? `${formatNumber(initialValues.fcr_value)} g` : '-'} {initialValues.project_flock?.fcr?.fcr_std != null - ? formatNumber( - initialValues.project_flock?.fcr?.fcr_std - ) + ? `${formatNumber(initialValues.project_flock?.fcr?.fcr_std)} g` : '-'} - Feed Intake (KG) + Feed Intake (g) {initialValues.feed_intake != null - ? formatNumber(initialValues.feed_intake) + ? `${formatNumber(initialValues.feed_intake)} g` : '-'} {initialValues.project_flock?.production_standart ?.feed_intake_std != null - ? formatNumber( - initialValues.project_flock?.production_standart - ?.feed_intake_std - ) + ? `${formatNumber(initialValues.project_flock?.production_standart?.feed_intake_std)} g` : '-'} @@ -2218,51 +2213,43 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { - Egg Mass + Egg Mass (kg) {initialValues.egg_mass != null - ? formatNumber(initialValues.egg_mass) + ? `${formatNumber(initialValues.egg_mass)} kg` : '-'} {initialValues.project_flock?.production_standart ?.egg_mass_std != null - ? formatNumber( - initialValues.project_flock - ?.production_standart?.egg_mass_std - ) + ? `${formatNumber(initialValues.project_flock?.production_standart?.egg_mass_std)} kg` : '-'} - - Egg Weight (KG) - + Egg Weight (g) {initialValues.egg_weight != null - ? formatNumber(initialValues.egg_weight) + ? `${formatNumber(initialValues.egg_weight)} g` : '-'} {initialValues.project_flock?.production_standart ?.egg_weight_std != null - ? formatNumber( - initialValues.project_flock - ?.production_standart?.egg_weight_std - ) + ? `${formatNumber(initialValues.project_flock?.production_standart?.egg_weight_std)} g` : '-'} - Hen Day + Hen Day (%) {initialValues.hen_day != null - ? formatNumber(initialValues.hen_day) + ? `${formatNumber(initialValues.hen_day)}%` : '-'} @@ -2274,18 +2261,20 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { - Hen House + + Hen House (btr) + {initialValues.hen_house != null - ? formatNumber(initialValues.hen_house) + ? `${formatNumber(initialValues.hen_house)} btr` : '-'} {initialValues.project_flock?.production_standart ?.hen_house_std != null - ? `${initialValues.project_flock?.production_standart?.hen_house_std}%` + ? `${formatNumber(initialValues.project_flock?.production_standart?.hen_house_std)} btr` : '-'} From 4d7bbaf77197d3c356f9092cf5698de3f6571eb2 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 21 Jan 2026 14:15:09 +0700 Subject: [PATCH 4/7] feat(FE): Show product UOM suffix in recording form --- .../recording/form/RecordingForm.tsx | 59 +++++++++++++++++++ .../api/inventory/product-warehouse.d.ts | 2 + 2 files changed, 61 insertions(+) diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 5120bab2..7365c6ca 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -1174,6 +1174,47 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { [stockProducts] ); + const getProductUomSuffix = useCallback( + (productWarehouseId: number, dataSource: 'stock' | 'depletion' | 'egg') => { + if (type !== 'add' && initialValues) { + let items; + if (dataSource === 'stock') { + items = initialValues.stocks; + } else if (dataSource === 'depletion') { + items = initialValues.depletions; + } else if (dataSource === 'egg') { + items = initialValues.eggs; + } + + if (items) { + const item = items.find( + (i) => i.product_warehouse_id === productWarehouseId + ); + if (item?.product_warehouse?.product?.uom?.name) { + return item.product_warehouse.product.uom.name; + } + } + } + + let rawData; + if (dataSource === 'stock') { + rawData = stockProducts; + } else if (dataSource === 'depletion') { + rawData = depletionProductsData; + } else if (dataSource === 'egg') { + rawData = eggProductsData; + } + + if (!isResponseSuccess(rawData)) return null; + + const data = rawData.data as unknown as ProductWarehouse[]; + const productWarehouse = data.find((pw) => pw.id === productWarehouseId); + + return productWarehouse?.product.uom.name || null; + }, + [stockProducts, depletionProductsData, eggProductsData, initialValues, type] + ); + const hasExceededStock = useMemo(() => { if ((type as 'add' | 'edit' | 'detail') === 'detail') return false; return ( @@ -2451,6 +2492,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { wrapper: 'w-full min-w-24', }} placeholder='Masukkan jumlah pakai' + inputSuffix={ + stock.product_warehouse_id + ? getProductUomSuffix( + stock.product_warehouse_id, + 'stock' + ) + : null + } /> {(type as 'add' | 'edit' | 'detail') !== 'detail' && getStockUsageAdornment(idx)} @@ -2646,6 +2695,14 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { wrapper: 'w-full min-w-24', }} placeholder='Masukkan jumlah deplesi' + inputSuffix={ + depletion.product_warehouse_id + ? getProductUomSuffix( + depletion.product_warehouse_id, + 'depletion' + ) + : null + } /> {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( @@ -2839,6 +2896,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { wrapper: 'w-full min-w-24', }} placeholder='Masukkan jumlah telur' + inputSuffix={'Butir'} /> @@ -2864,6 +2922,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { wrapper: 'w-full min-w-24', }} placeholder='Masukkan total berat telur (Kilogram)...' + inputSuffix='Kilogram' /> {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( diff --git a/src/types/api/inventory/product-warehouse.d.ts b/src/types/api/inventory/product-warehouse.d.ts index eda8d1b8..8bed1aba 100644 --- a/src/types/api/inventory/product-warehouse.d.ts +++ b/src/types/api/inventory/product-warehouse.d.ts @@ -1,11 +1,13 @@ import { BaseMetadata } from '@/types/api/api-general'; import { Warehouse } from '@/types/api/master-data/warehouse'; import { Product } from '@/types/api/master-data/product'; +import { Uom } from '@/types/api/master-data/uom'; export type BaseProductWarehouse = { id: number; product_id: number; warehouse_id: number; + uom: Uom; quantity: number; product: Product; warehouse: Warehouse; From 149b14e0f87feb60005c476383a24fb19d1bc4e2 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 21 Jan 2026 14:18:14 +0700 Subject: [PATCH 5/7] fix: add form validation for configuration form --- .../MasterConfigurationContent.tsx | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/figma-make/components/pages/master-data/configuration/MasterConfigurationContent.tsx b/src/figma-make/components/pages/master-data/configuration/MasterConfigurationContent.tsx index 1358d6ba..9fa75c33 100644 --- a/src/figma-make/components/pages/master-data/configuration/MasterConfigurationContent.tsx +++ b/src/figma-make/components/pages/master-data/configuration/MasterConfigurationContent.tsx @@ -69,6 +69,7 @@ export function MasterConfigurationContent() { } ); + const [isFormInvalid, setIsFormInvalid] = useState(false); const [showModal, setShowModal] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [configurationToDelete, setConfigurationToDelete] = useState< @@ -173,6 +174,26 @@ export function MasterConfigurationContent() { return; } + if ( + Number(configurationForm.percentage_threshold_enough) >= 100 || + Number(configurationForm.percentage_threshold_bad) >= 100 + ) { + setIsFormInvalid(true); + toast.error('Persentase threshold tidak boleh lebih dari 100'); + return; + } + + if ( + Number(configurationForm.percentage_threshold_enough) <= + Number(configurationForm.percentage_threshold_bad) + 1 + ) { + setIsFormInvalid(true); + toast.error( + 'Persentase threshold "kurang" harus lebih kecil dari persentase threshold "cukup"' + ); + return; + } + setLoading(true); try { @@ -443,14 +464,18 @@ export function MasterConfigurationContent() { type='number' id='percentageThresholdBad' value={configurationForm.percentage_threshold_bad} - onChange={(e) => + onChange={(e) => { + setIsFormInvalid(false); + setConfigurationForm({ ...configurationForm, percentage_threshold_bad: e.target.value, - }) - } + }); + }} placeholder='Kurang' - className='w-20' + className={cn('w-20', { + 'border-red-500': isFormInvalid, + })} disabled={loading} max={100} /> @@ -476,14 +501,17 @@ export function MasterConfigurationContent() { type='number' id='percentageThresholdEnough' value={configurationForm.percentage_threshold_enough} - onChange={(e) => + onChange={(e) => { + setIsFormInvalid(false); setConfigurationForm({ ...configurationForm, percentage_threshold_enough: e.target.value, - }) - } + }); + }} placeholder='Cukup' - className='w-20' + className={cn('w-20', { + 'border-red-500': isFormInvalid, + })} disabled={loading} min={Number(configurationForm.percentage_threshold_bad) + 1} max={100} From 362ae16c7d3b33c49191d9037357aad553be4bcd Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 21 Jan 2026 14:19:58 +0700 Subject: [PATCH 6/7] chore: set empty string for phase_id filter if ALL phase is selected --- .../components/pages/reports/DailyChecklistReportsContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/figma-make/components/pages/reports/DailyChecklistReportsContent.tsx b/src/figma-make/components/pages/reports/DailyChecklistReportsContent.tsx index 61558d4f..f1c32198 100644 --- a/src/figma-make/components/pages/reports/DailyChecklistReportsContent.tsx +++ b/src/figma-make/components/pages/reports/DailyChecklistReportsContent.tsx @@ -292,7 +292,7 @@ export function DailyChecklistReportsContent() { }; const phaseChangeHandler = (value: string) => { - updateFilter('phase_id', value); + updateFilter('phase_id', value === 'ALL' ? '' : value); }; const employeeChangeHandler = (value: string) => { From 426b6bfc85134eaab312d2e15da459b86df92714 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Wed, 21 Jan 2026 14:38:21 +0700 Subject: [PATCH 7/7] chore: update chart and chart text color --- .../components/pages/dashboard/Dashboard.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/figma-make/components/pages/dashboard/Dashboard.tsx b/src/figma-make/components/pages/dashboard/Dashboard.tsx index f6d12d79..8953ccf6 100644 --- a/src/figma-make/components/pages/dashboard/Dashboard.tsx +++ b/src/figma-make/components/pages/dashboard/Dashboard.tsx @@ -83,10 +83,7 @@ export function Dashboard() { dateFrom && dateTo ? `${DailyChecklistApi.basePath}/summary?date_from=${dateFrom}&date_to=${dateTo}&kandang_id=${kandangFilter === 'ALL' ? '' : kandangFilter}&category=${categoryFilter === 'ALL' ? '' : categoryFilter}` : '', - httpClientFetcher, - { - keepPreviousData: true, - } + httpClientFetcher ); const { options: kandangOptions, isLoadingOptions: isLoadingKandangs } = @@ -311,14 +308,14 @@ export function Dashboard() { {chartData?.map((entry, index) => ( ))} @@ -370,7 +367,7 @@ export function Dashboard() { {employeePerformance?.map((emp, index) => (