mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(US-114): enhance auto-calculation logic in RecordingForm to handle manual edits
This commit is contained in:
@@ -45,6 +45,9 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
// Track which average weight field is being edited to prevent auto-calculation override
|
// Track which average weight field is being edited to prevent auto-calculation override
|
||||||
const [editingAverageIndex, setEditingAverageIndex] = useState<number | null>(null);
|
const [editingAverageIndex, setEditingAverageIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
|
// Track which rows have been manually edited to prevent auto-calculation override
|
||||||
|
const [manuallyEditedRows, setManuallyEditedRows] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
// State for Location search and selection
|
// State for Location search and selection
|
||||||
const [locationSearchValue, setLocationSearchValue] = useState('');
|
const [locationSearchValue, setLocationSearchValue] = useState('');
|
||||||
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(null);
|
const [selectedLocation, setSelectedLocation] = useState<OptionType | null>(null);
|
||||||
@@ -223,10 +226,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
// Auto-calculate average weight when weight or qty changes (but not when editing average weight manually)
|
// Auto-calculate average weight when weight or qty changes (but not when editing average weight manually)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Only run auto-calculation if no field is being edited
|
||||||
if (formik.values.body_weights && editingAverageIndex === null) {
|
if (formik.values.body_weights && editingAverageIndex === null) {
|
||||||
const updatedBodyWeights = formik.values.body_weights.map((weight, idx) => {
|
const updatedBodyWeights = formik.values.body_weights.map((weight, idx) => {
|
||||||
// Skip auto-calculation for the field being manually edited
|
// Skip the field that's being edited or has been manually edited
|
||||||
if (idx === editingAverageIndex) {
|
if (idx === editingAverageIndex || manuallyEditedRows.has(idx)) {
|
||||||
return weight;
|
return weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +238,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
...weight,
|
...weight,
|
||||||
average_weight:
|
average_weight:
|
||||||
weight.qty > 0 && weight.weight > 0
|
weight.qty > 0 && weight.weight > 0
|
||||||
? Math.round(weight.weight / weight.qty)
|
? parseFloat((weight.weight / weight.qty).toFixed(2))
|
||||||
: 0,
|
: 0,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@@ -243,11 +247,13 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const hasChanges = updatedBodyWeights.some(
|
const hasChanges = updatedBodyWeights.some(
|
||||||
(updated, idx) =>
|
(updated, idx) =>
|
||||||
idx !== editingAverageIndex && // Skip the field being edited
|
idx !== editingAverageIndex && // Skip the field being edited
|
||||||
|
!manuallyEditedRows.has(idx) && // Skip manually edited rows
|
||||||
updated.average_weight !==
|
updated.average_weight !==
|
||||||
(formik.values.body_weights[idx]?.average_weight || 0)
|
(formik.values.body_weights[idx]?.average_weight || 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
|
// Use false to prevent triggering validation and other side effects
|
||||||
formik.setFieldValue('body_weights', updatedBodyWeights, false);
|
formik.setFieldValue('body_weights', updatedBodyWeights, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,6 +261,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
formik.values.body_weights?.map((w) => w.weight),
|
formik.values.body_weights?.map((w) => w.weight),
|
||||||
formik.values.body_weights?.map((w) => w.qty),
|
formik.values.body_weights?.map((w) => w.qty),
|
||||||
editingAverageIndex, // Include editing index in dependencies
|
editingAverageIndex, // Include editing index in dependencies
|
||||||
|
manuallyEditedRows, // Include manually edited rows in dependencies
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// EVENT HANDLERS - Body Weights
|
// EVENT HANDLERS - Body Weights
|
||||||
@@ -274,11 +281,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const handleWeightChange = (idx: number, value: number) => {
|
const handleWeightChange = (idx: number, value: number) => {
|
||||||
formik.setFieldValue(`body_weights.${idx}.weight`, value);
|
formik.setFieldValue(`body_weights.${idx}.weight`, value);
|
||||||
|
|
||||||
|
// Reset manual edit flag when weight changes (user wants auto-calculation)
|
||||||
|
setManuallyEditedRows(prev => {
|
||||||
|
const newSet = new Set(prev);
|
||||||
|
newSet.delete(idx);
|
||||||
|
return newSet;
|
||||||
|
});
|
||||||
|
|
||||||
const currentWeight = formik.values.body_weights?.[idx];
|
const currentWeight = formik.values.body_weights?.[idx];
|
||||||
if (currentWeight) {
|
if (currentWeight) {
|
||||||
const qty = currentWeight.qty;
|
const qty = currentWeight.qty;
|
||||||
if (qty > 0 && value > 0) {
|
if (qty > 0 && value > 0) {
|
||||||
const averageWeight = Math.round(value / qty);
|
const averageWeight = parseFloat((value / qty).toFixed(2));
|
||||||
formik.setFieldValue(`body_weights.${idx}.average_weight`, averageWeight);
|
formik.setFieldValue(`body_weights.${idx}.average_weight`, averageWeight);
|
||||||
} else {
|
} else {
|
||||||
formik.setFieldValue(`body_weights.${idx}.average_weight`, 0);
|
formik.setFieldValue(`body_weights.${idx}.average_weight`, 0);
|
||||||
@@ -290,11 +304,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
const handleQtyChange = (idx: number, value: number) => {
|
const handleQtyChange = (idx: number, value: number) => {
|
||||||
formik.setFieldValue(`body_weights.${idx}.qty`, value);
|
formik.setFieldValue(`body_weights.${idx}.qty`, value);
|
||||||
|
|
||||||
|
// Reset manual edit flag when qty changes (user wants auto-calculation)
|
||||||
|
setManuallyEditedRows(prev => {
|
||||||
|
const newSet = new Set(prev);
|
||||||
|
newSet.delete(idx);
|
||||||
|
return newSet;
|
||||||
|
});
|
||||||
|
|
||||||
const currentWeight = formik.values.body_weights?.[idx];
|
const currentWeight = formik.values.body_weights?.[idx];
|
||||||
if (currentWeight) {
|
if (currentWeight) {
|
||||||
const weight = currentWeight.weight;
|
const weight = currentWeight.weight;
|
||||||
if (value > 0 && weight > 0) {
|
if (value > 0 && weight > 0) {
|
||||||
const averageWeight = Math.round(weight / value);
|
const averageWeight = parseFloat((weight / value).toFixed(2));
|
||||||
formik.setFieldValue(`body_weights.${idx}.average_weight`, averageWeight);
|
formik.setFieldValue(`body_weights.${idx}.average_weight`, averageWeight);
|
||||||
} else {
|
} else {
|
||||||
formik.setFieldValue(`body_weights.${idx}.average_weight`, 0);
|
formik.setFieldValue(`body_weights.${idx}.average_weight`, 0);
|
||||||
@@ -320,12 +341,20 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
|
|
||||||
// Create wrapper handlers that match NumberInput's onChange signature
|
// Create wrapper handlers that match NumberInput's onChange signature
|
||||||
const handleWeightChangeWrapper = (idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleWeightChangeWrapper = (idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = parseFloat(e.target.value.replace(/[^\d,.-]/g, '').replace(/,/g, '')) || 0;
|
// Parse the value more carefully to handle decimal numbers properly
|
||||||
|
const rawValue = e.target.value.replace(/[^\d,.-]/g, '');
|
||||||
|
// Convert comma thousand separator to nothing, but keep decimal point
|
||||||
|
const normalizedValue = rawValue.replace(/,/g, '');
|
||||||
|
const value = parseFloat(normalizedValue) || 0;
|
||||||
handleWeightChange(idx, value);
|
handleWeightChange(idx, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleQtyChangeWrapper = (idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleQtyChangeWrapper = (idx: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const value = parseFloat(e.target.value.replace(/[^\d,.-]/g, '').replace(/,/g, '')) || 0;
|
// Parse the value more carefully to handle decimal numbers properly
|
||||||
|
const rawValue = e.target.value.replace(/[^\d,.-]/g, '');
|
||||||
|
// Convert comma thousand separator to nothing, but keep decimal point
|
||||||
|
const normalizedValue = rawValue.replace(/,/g, '');
|
||||||
|
const value = parseFloat(normalizedValue) || 0;
|
||||||
handleQtyChange(idx, value);
|
handleQtyChange(idx, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -333,11 +362,18 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
// Set focus state to prevent auto-calculation override
|
// Set focus state to prevent auto-calculation override
|
||||||
setEditingAverageIndex(idx);
|
setEditingAverageIndex(idx);
|
||||||
|
|
||||||
const value = parseFloat(e.target.value.replace(/[^\d,.-]/g, '').replace(/,/g, '')) || 0;
|
// Mark this row as manually edited
|
||||||
|
setManuallyEditedRows(prev => new Set(prev).add(idx));
|
||||||
|
|
||||||
|
// Parse the value more carefully to handle decimal numbers properly
|
||||||
|
const rawValue = e.target.value.replace(/[^\d,.-]/g, '');
|
||||||
|
// Convert comma thousand separator to nothing, but keep decimal point
|
||||||
|
const normalizedValue = rawValue.replace(/,/g, '');
|
||||||
|
const value = parseFloat(normalizedValue) || 0;
|
||||||
handleAverageWeightChange(idx, value);
|
handleAverageWeightChange(idx, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAverageWeightBlur = () => {
|
const handleAverageWeightBlur = (idx: number) => {
|
||||||
// Clear focus state when user leaves the field to re-enable auto-calculation
|
// Clear focus state when user leaves the field to re-enable auto-calculation
|
||||||
setEditingAverageIndex(null);
|
setEditingAverageIndex(null);
|
||||||
};
|
};
|
||||||
@@ -700,7 +736,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => {
|
|||||||
value={bw.average_weight || 0}
|
value={bw.average_weight || 0}
|
||||||
onChange={handleAverageWeightChangeWrapper(idx)}
|
onChange={handleAverageWeightChangeWrapper(idx)}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
handleAverageWeightBlur();
|
handleAverageWeightBlur(idx);
|
||||||
formik.handleBlur(e);
|
formik.handleBlur(e);
|
||||||
}}
|
}}
|
||||||
maskType='weight'
|
maskType='weight'
|
||||||
|
|||||||
Reference in New Issue
Block a user