Merge branch 'fix/master-data-production-standard' into 'development'

[FIX/FE] Adding FCR Master Data Production Standard Growing

See merge request mbugroup/lti-web-client!305
This commit is contained in:
Rivaldi A N S
2026-02-03 09:32:21 +00:00
5 changed files with 92 additions and 57 deletions
+2
View File
@@ -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',
})}
>
<circle r='6' cx='6' cy='6' fill='currentColor' />
@@ -250,29 +250,29 @@ const ClosingOverheadTable = ({
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 gap-3 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'>
<div className='flex flex-col flex-1 gap-1.5'>
<div className='flex flex-row gap-1.5 text-center 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'>
<hr className='w-full h-fit m-0 p-0 text-base-content/65' />
<div className='flex flex-row gap-1.5 text-center 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'>
<div className='flex flex-col flex-1 gap-1.5'>
<div className='flex flex-row gap-1.5 text-center items-center justify-center font-medium'>
{formatNumber(chickinPopulation ?? 0)}
<Icon icon='heroicons:x-mark' className='inline' />
{formatCurrency(
@@ -281,8 +281,8 @@ const ClosingOverheadTable = ({
: 0
)}
</div>
<hr className='w-full h-1' />
<div className='flex flex-row items-center justify-center font-medium'>
<hr className='w-full h-fit m-0 p-0 text-base-content/65' />
<div className='flex flex-row gap-1.5 text-center items-center justify-center font-medium'>
{formatNumber(generalInformation?.population ?? 0)}
</div>
</div>
@@ -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(),
});
@@ -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)',
}}
>
<NumberInput
@@ -1042,39 +1063,38 @@ const ProductionStandardForm = ({
)
}
/>
<NumberInput
name='production_standard_details.standard_fcr'
label='FCR'
placeholder='1'
value={
repeaterFormik.values
.production_standard_details?.standard_fcr
}
onChange={repeaterFormik.handleChange}
onBlur={repeaterFormik.handleBlur}
bottomLabel='Gram (g)'
errorMessage={getProductionDetailsError(
</>
)}
<NumberInput
name='production_standard_details.standard_fcr'
label='FCR'
placeholder='1'
value={
repeaterFormik.values.production_standard_details
?.standard_fcr
}
onChange={repeaterFormik.handleChange}
onBlur={repeaterFormik.handleBlur}
bottomLabel='Gram (g)'
errorMessage={getProductionDetailsError(
repeaterFormik.errors.production_standard_details,
'standard_fcr'
)}
isError={
Boolean(
getProductionDetailsError(
repeaterFormik.errors
.production_standard_details,
'standard_fcr'
)}
isError={
Boolean(
getProductionDetailsError(
repeaterFormik.errors
.production_standard_details,
'standard_fcr'
)
) &&
getProductionDetailsTouched(
repeaterFormik.touched
.production_standard_details,
'standard_fcr'
)
}
/>
</>
)}
)
) &&
getProductionDetailsTouched(
repeaterFormik.touched
.production_standard_details,
'standard_fcr'
)
}
/>
<NumberInput
name='production_standard_uniformity_details.target_mean_bw'
label='Mean BW'
@@ -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<string, Color> = {
'Sudah Jatuh Tempo': 'error',
@@ -60,7 +59,15 @@ const getPillBadge = (
? dueStatus[statusText] || 'neutral'
: paymentStatus[statusText] || 'neutral';
return <StatusBadge color={color as Color} text={statusText} />;
return (
<StatusBadge
color={color as Color}
text={statusText}
className={{
badge: 'w-fit',
}}
/>
);
};
interface DebtSupplierTabProps {
@@ -466,7 +473,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
footer: () => {
const value = supplier?.total.total_price;
return (
<div className={`text-right ${value || 0 < 0 ? 'text-red-500' : ''}`}>
<div
className={`text-right ${value && value < 0 ? 'text-red-500' : ''}`}
>
{formatCurrency(value || 0)}
</div>
);
@@ -488,7 +497,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
footer: () => {
const value = supplier?.total.payment_price;
return (
<div className={`text-right ${value || 0 < 0 ? 'text-red-500' : ''}`}>
<div
className={`text-right ${value && value < 0 ? 'text-red-500' : ''}`}
>
{formatCurrency(value || 0)}
</div>
);
@@ -510,7 +521,9 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
footer: () => {
const value = supplier?.total.debt_price;
return (
<div className={`text-right ${value || 0 < 0 ? 'text-red-500' : ''}`}>
<div
className={`text-right ${value && value < 0 ? 'text-red-500' : ''}`}
>
{formatCurrency(value || 0)}
</div>
);