refactor(FE-114): enhance form UI by adding required field indicators for multiple inputs

This commit is contained in:
rstubryan
2025-10-22 13:55:12 +07:00
parent 9c114628c7
commit c249585bc2
2 changed files with 254 additions and 55 deletions
@@ -418,27 +418,96 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
formik.setFieldValue('body_weight', newBodyWeight);
};
const handleBodyWeightChange =
(fieldName: string, idx: number) =>
(e: React.ChangeEvent<HTMLInputElement>) => {
formik.handleChange(e);
setTimeout(() => {
const currentWeight = formik.values.body_weight?.[idx];
if (currentWeight) {
const newAverage =
currentWeight.chicken_count > 0
? Math.round(
currentWeight.chicken_weight / currentWeight.chicken_count
)
: 0;
// Handle calculation when chicken_weight changes
const handleChickenWeightChange = useCallback(
(idx: number, value: number) => {
formik.setFieldValue(`body_weight.${idx}.chicken_weight`, value);
const currentWeight = formik.values.body_weight?.[idx];
if (currentWeight) {
const chickenCount = currentWeight.chicken_count;
if (chickenCount > 0 && value > 0) {
const averageWeight = Math.round(value / chickenCount);
formik.setFieldValue(
`body_weight.${idx}.average_chicken_weight`,
newAverage
averageWeight
);
} else {
formik.setFieldValue(`body_weight.${idx}.average_chicken_weight`, '');
}
}, 0);
};
}
},
[formik]
);
// Handle calculation when chicken_count changes
const handleChickenCountChange = useCallback(
(idx: number, value: number) => {
formik.setFieldValue(`body_weight.${idx}.chicken_count`, value);
const currentWeight = formik.values.body_weight?.[idx];
if (currentWeight) {
const chickenWeight = currentWeight.chicken_weight;
if (chickenWeight > 0 && value > 0) {
const averageWeight = Math.round(chickenWeight / value);
formik.setFieldValue(
`body_weight.${idx}.average_chicken_weight`,
averageWeight
);
} else {
formik.setFieldValue(`body_weight.${idx}.average_chicken_weight`, '');
}
}
},
[formik]
);
// Handle calculation when average_weight changes
const handleAverageWeightChange = useCallback(
(idx: number, value: number) => {
formik.setFieldValue(`body_weight.${idx}.average_chicken_weight`, value);
const currentWeight = formik.values.body_weight?.[idx];
if (currentWeight) {
const chickenCount = currentWeight.chicken_count;
if (chickenCount > 0 && value > 0) {
const totalWeight = value * chickenCount;
formik.setFieldValue(
`body_weight.${idx}.chicken_weight`,
totalWeight
);
} else if (value === 0) {
formik.setFieldValue(`body_weight.${idx}.chicken_weight`, '');
}
}
},
[formik]
);
// Create wrapper handlers that match NumberInput's onChange signature
const handleChickenWeightChangeWrapper = useCallback(
(idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = parseFloat(e.target.value) || 0;
handleChickenWeightChange(idx, value);
},
[handleChickenWeightChange]
);
const handleChickenCountChangeWrapper = useCallback(
(idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = parseFloat(e.target.value) || 0;
handleChickenCountChange(idx, value);
},
[handleChickenCountChange]
);
const handleAverageWeightChangeWrapper = useCallback(
(idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const value = parseFloat(e.target.value) || 0;
handleAverageWeightChange(idx, value);
},
[handleAverageWeightChange]
);
const removeBodyWeight = (idx: number) => {
const updatedBodyWeight = formik.values.body_weight?.filter(
@@ -712,9 +781,25 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</div>
</th>
)}
<th>Nama Pakan</th>
<th>
Nama Pakan
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>Total Stock pada saat ini</th>
<th>Jumlah Stock yang digunakan</th>
<th>
Jumlah Stock yang digunakan
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
{type !== 'detail' && <th>Action</th>}
</tr>
</thead>
@@ -945,9 +1030,33 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</div>
</th>
)}
<th>Berat (Gram)</th>
<th>Jumlah Ayam</th>
<th>Rata-rata berat Ayam</th>
<th>
Berat (Gram)
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>
Jumlah Ayam
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>
Rata-rata berat Ayam
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
{type !== 'detail' && <th>Action</th>}
</tr>
</thead>
@@ -981,10 +1090,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
required
name={`body_weight.${idx}.chicken_weight`}
value={weight.chicken_weight}
onChange={handleBodyWeightChange(
'chicken_weight',
idx
)}
onChange={handleChickenWeightChangeWrapper(idx)}
onBlur={formik.handleBlur}
maskType='weight'
weightUnit='gram'
@@ -1015,10 +1121,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
required
name={`body_weight.${idx}.chicken_count`}
value={weight.chicken_count}
onChange={handleBodyWeightChange(
'chicken_count',
idx
)}
onChange={handleChickenCountChangeWrapper(idx)}
onBlur={formik.handleBlur}
maskType='number'
decimals={0}
@@ -1048,15 +1151,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
<NumberInput
required
name={`body_weight.${idx}.average_chicken_weight`}
value={
weight.chicken_count > 0
? Math.round(
weight.chicken_weight /
weight.chicken_count
)
: 0
}
onChange={formik.handleChange}
value={weight.average_chicken_weight || ''}
onChange={handleAverageWeightChangeWrapper(idx)}
onBlur={formik.handleBlur}
maskType='weight'
weightUnit='gram'
@@ -1076,12 +1172,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
idx
).errorMessage
}
readOnly={true}
disabled={true}
readOnly={type === 'detail'}
className={{
wrapper: 'w-full min-w-24',
}}
placeholder='0'
placeholder=''
/>
</div>
</td>
@@ -1175,9 +1270,25 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</div>
</th>
)}
<th>Name Vaksin</th>
<th>
Name Vaksin
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>Total Stock pada saat ini</th>
<th>Jumlah Stock yang digunakan</th>
<th>
Jumlah Stock yang digunakan
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
{type !== 'detail' && <th>Action</th>}
</tr>
</thead>
@@ -1418,8 +1529,24 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
</div>
</th>
)}
<th>Kondisi/Alasan Mortalitas</th>
<th>Jumlah</th>
<th>
Kondisi/Alasan Mortalitas
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
<th>
Jumlah
<span
className='tooltip tooltip-error tooltip-bottom z-[9999]'
data-tip='required'
>
<span className='text-error'>*</span>
</span>
</th>
{type !== 'detail' && <th>Action</th>}
</tr>
</thead>