mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
refactor(FE-114): enhance body weight calculations in RecordingForm with auto-update for average weight
This commit is contained in:
@@ -77,22 +77,46 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
: '',
|
||||
feed_data: (values.feed_data ?? []).map((p) => ({
|
||||
feed_id: p.feed_id,
|
||||
feed_qty: typeof p.feed_qty === 'number' ? p.feed_qty : parseFloat(String(p.feed_qty)) || 0,
|
||||
feed_stock: typeof p.feed_stock === 'number' ? p.feed_stock : parseFloat(String(p.feed_stock)) || 0,
|
||||
feed_qty:
|
||||
typeof p.feed_qty === 'number'
|
||||
? p.feed_qty
|
||||
: parseFloat(String(p.feed_qty)) || 0,
|
||||
feed_stock:
|
||||
typeof p.feed_stock === 'number'
|
||||
? p.feed_stock
|
||||
: parseFloat(String(p.feed_stock)) || 0,
|
||||
})),
|
||||
body_weight: (values.body_weight ?? []).map((b) => ({
|
||||
chicken_weight: typeof b.chicken_weight === 'number' ? b.chicken_weight : parseFloat(String(b.chicken_weight)) || 0,
|
||||
chicken_count: typeof b.chicken_count === 'number' ? b.chicken_count : parseFloat(String(b.chicken_count)) || 0,
|
||||
average_chicken_weight: typeof b.average_chicken_weight === 'number' ? b.average_chicken_weight : parseFloat(String(b.average_chicken_weight)) || 0,
|
||||
chicken_weight:
|
||||
typeof b.chicken_weight === 'number'
|
||||
? b.chicken_weight
|
||||
: parseFloat(String(b.chicken_weight)) || 0,
|
||||
chicken_count:
|
||||
typeof b.chicken_count === 'number'
|
||||
? b.chicken_count
|
||||
: parseFloat(String(b.chicken_count)) || 0,
|
||||
average_chicken_weight:
|
||||
typeof b.average_chicken_weight === 'number'
|
||||
? b.average_chicken_weight
|
||||
: parseFloat(String(b.average_chicken_weight)) || 0,
|
||||
})),
|
||||
vaccination: (values.vaccination ?? []).map((v) => ({
|
||||
vaccine_id: v.vaccine_id,
|
||||
total_stock: typeof v.total_stock === 'number' ? v.total_stock : parseFloat(String(v.total_stock)) || 0,
|
||||
used_stock: typeof v.used_stock === 'number' ? v.used_stock : parseFloat(String(v.used_stock)) || 0,
|
||||
total_stock:
|
||||
typeof v.total_stock === 'number'
|
||||
? v.total_stock
|
||||
: parseFloat(String(v.total_stock)) || 0,
|
||||
used_stock:
|
||||
typeof v.used_stock === 'number'
|
||||
? v.used_stock
|
||||
: parseFloat(String(v.used_stock)) || 0,
|
||||
})),
|
||||
mortality: (values.mortality ?? []).map((m) => ({
|
||||
condition: m.condition,
|
||||
count: typeof m.count === 'number' ? m.count : parseFloat(String(m.count)) || 0,
|
||||
count:
|
||||
typeof m.count === 'number'
|
||||
? m.count
|
||||
: parseFloat(String(m.count)) || 0,
|
||||
})),
|
||||
};
|
||||
|
||||
@@ -283,6 +307,33 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
}
|
||||
}, [initialValues, projectFlocks]);
|
||||
|
||||
// Auto-calculate average weight when chicken weight or count changes
|
||||
useEffect(() => {
|
||||
if (formik.values.body_weight) {
|
||||
const updatedBodyWeight = formik.values.body_weight.map((weight) => ({
|
||||
...weight,
|
||||
average_chicken_weight:
|
||||
weight.chicken_count > 0
|
||||
? Math.round(weight.chicken_weight / weight.chicken_count)
|
||||
: 0,
|
||||
}));
|
||||
|
||||
// Only update if values are different to avoid infinite loops
|
||||
const hasChanges = updatedBodyWeight.some(
|
||||
(updated, idx) =>
|
||||
updated.average_chicken_weight !==
|
||||
formik.values.body_weight[idx]?.average_chicken_weight
|
||||
);
|
||||
|
||||
if (hasChanges) {
|
||||
formik.setFieldValue('body_weight', updatedBodyWeight);
|
||||
}
|
||||
}
|
||||
}, [
|
||||
formik.values.body_weight?.map((w) => w.chicken_weight),
|
||||
formik.values.body_weight?.map((w) => w.chicken_count),
|
||||
]);
|
||||
|
||||
// EVENT HANDLERS - Select Inputs
|
||||
const locationChangeHandler = (val: OptionType | OptionType[] | null) => {
|
||||
const locationValue = (val as OptionType)?.value;
|
||||
@@ -363,6 +414,28 @@ 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;
|
||||
|
||||
formik.setFieldValue(
|
||||
`body_weight.${idx}.average_chicken_weight`,
|
||||
newAverage
|
||||
);
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
const removeBodyWeight = (idx: number) => {
|
||||
const updatedBodyWeight = formik.values.body_weight?.filter(
|
||||
(_, i) => i !== idx
|
||||
@@ -865,7 +938,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
required
|
||||
name={`body_weight.${idx}.chicken_weight`}
|
||||
value={weight.chicken_weight}
|
||||
onChange={formik.handleChange}
|
||||
onChange={handleBodyWeightChange(
|
||||
'chicken_weight',
|
||||
idx
|
||||
)}
|
||||
onBlur={formik.handleBlur}
|
||||
maskType='weight'
|
||||
weightUnit='gram'
|
||||
@@ -896,7 +972,10 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
required
|
||||
name={`body_weight.${idx}.chicken_count`}
|
||||
value={weight.chicken_count}
|
||||
onChange={formik.handleChange}
|
||||
onChange={handleBodyWeightChange(
|
||||
'chicken_count',
|
||||
idx
|
||||
)}
|
||||
onBlur={formik.handleBlur}
|
||||
maskType='number'
|
||||
decimals={0}
|
||||
@@ -922,35 +1001,46 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<NumberInput
|
||||
required
|
||||
name={`body_weight.${idx}.average_chicken_weight`}
|
||||
value={weight.average_chicken_weight}
|
||||
onChange={formik.handleChange}
|
||||
onBlur={formik.handleBlur}
|
||||
maskType='weight'
|
||||
weightUnit='gram'
|
||||
decimals={0}
|
||||
min={0}
|
||||
isError={
|
||||
isRepeaterInputError(
|
||||
'body_weight',
|
||||
'average_chicken_weight',
|
||||
idx
|
||||
).isError
|
||||
}
|
||||
errorMessage={
|
||||
isRepeaterInputError(
|
||||
'body_weight',
|
||||
'average_chicken_weight',
|
||||
idx
|
||||
).errorMessage
|
||||
}
|
||||
readOnly={type === 'detail'}
|
||||
className={{
|
||||
wrapper: 'w-full min-w-24',
|
||||
}}
|
||||
/>
|
||||
<div className='relative'>
|
||||
<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}
|
||||
onBlur={formik.handleBlur}
|
||||
maskType='weight'
|
||||
weightUnit='gram'
|
||||
decimals={0}
|
||||
min={0}
|
||||
isError={
|
||||
isRepeaterInputError(
|
||||
'body_weight',
|
||||
'average_chicken_weight',
|
||||
idx
|
||||
).isError
|
||||
}
|
||||
errorMessage={
|
||||
isRepeaterInputError(
|
||||
'body_weight',
|
||||
'average_chicken_weight',
|
||||
idx
|
||||
).errorMessage
|
||||
}
|
||||
readOnly={true}
|
||||
disabled={true}
|
||||
className={{
|
||||
wrapper: 'w-full min-w-24',
|
||||
}}
|
||||
placeholder='0'
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
{type !== 'detail' && (
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user