Fix company field changes erasing data (hopefully)

This commit is contained in:
2025-03-02 16:09:55 -05:00
parent 98e3b89d46
commit 56c3f0534d

View File

@@ -1799,6 +1799,7 @@ export const ValidationStep = <T extends string>({
// Track which changes have been reverted
const [revertedChanges, setRevertedChanges] = useState<Set<string>>(new Set());
const [isProductSearchDialogOpen, setIsProductSearchDialogOpen] = useState(false);
const prevGlobalSelectionsRef = useRef(globalSelections);
// Fetch product lines when company is selected
const { data: productLines } = useQuery({
@@ -1838,66 +1839,25 @@ export const ValidationStep = <T extends string>({
staleTime: 30000, // Cache for 30 seconds
});
// Apply global selections to initial data and validate
const initialDataWithGlobals = useMemo(() => {
if (!globalSelections) return initialData;
// Find the field definitions for our global selection fields
const supplierField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'supplier');
const companyField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'company');
const lineField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'line');
const sublineField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'subline');
// Helper function to safely set a field value and update options if needed
const setFieldValue = (field: Field<T> | undefined, value: string | undefined, options?: SelectOption[]) => {
if (!field || !value) return undefined;
if (field.fieldType.type === 'select') {
// Use provided options if available, otherwise use field's default options
const fieldOptions = options || (field.fieldType as SelectFieldType).options;
// First try to find by value (ID)
const optionByValue = fieldOptions.find(opt => opt.value === value);
if (optionByValue) {
return optionByValue.value;
}
// Then try to find by label (name)
const optionByLabel = fieldOptions.find(opt => opt.label.toLowerCase() === value.toLowerCase());
if (optionByLabel) {
return optionByLabel.value;
}
// Helper function to safely set a field value and update options if needed
const setFieldValue = (field: Field<T> | undefined, value: string | undefined, options?: SelectOption[]) => {
if (!field || !value) return undefined;
if (field.fieldType.type === 'select') {
// Use provided options if available, otherwise use field's default options
const fieldOptions = options || (field.fieldType as SelectFieldType).options;
// First try to find by value (ID)
const optionByValue = fieldOptions.find(opt => opt.value === value);
if (optionByValue) {
return optionByValue.value;
}
return value;
};
// Apply global selections to each row
const newData = initialData.map(row => {
const newRow = { ...row };
// Apply each global selection if it exists
if (globalSelections.supplier) {
const supplierValue = setFieldValue(supplierField as Field<T>, globalSelections.supplier);
if (supplierValue) newRow.supplier = supplierValue;
// Then try to find by label (name)
const optionByLabel = fieldOptions.find(opt => opt.label.toLowerCase() === value.toLowerCase());
if (optionByLabel) {
return optionByLabel.value;
}
if (globalSelections.company) {
const companyValue = setFieldValue(companyField as Field<T>, globalSelections.company);
if (companyValue) newRow.company = companyValue;
}
if (globalSelections.line && productLines) {
const lineValue = setFieldValue(lineField as Field<T>, globalSelections.line, productLines);
if (lineValue) newRow.line = lineValue;
}
if (globalSelections.subline && sublines) {
const sublineValue = setFieldValue(sublineField as Field<T>, globalSelections.subline, sublines);
if (sublineValue) newRow.subline = sublineValue;
}
return newRow;
});
return newData;
}, [initialData, globalSelections, fields, productLines, sublines]);
}
return value;
};
// Update field options with fetched data
const fieldsWithUpdatedOptions = useMemo(() => {
@@ -1948,15 +1908,79 @@ export const ValidationStep = <T extends string>({
});
}, [fields, productLines, sublines, globalSelections?.company, globalSelections?.line]);
const [data, setData] = useState<RowData<T>[]>(initialDataWithGlobals);
// Initialize data with initialData
const [data, setData] = useState<RowData<T>[]>(initialData);
// Run validation when component mounts or when global selections change
// Apply global selections when they change
useEffect(() => {
if (!globalSelections || JSON.stringify(globalSelections) === JSON.stringify(prevGlobalSelectionsRef.current)) {
return;
}
// Find the field definitions for changed global selection fields
const supplierField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'supplier');
const companyField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'company');
const lineField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'line');
const sublineField = Array.from(fields as ReadonlyFields<T>).find(f => f.key === 'subline');
// Identify which selections have changed
const changedSelections: Partial<GlobalSelections> = {};
if (globalSelections.supplier !== prevGlobalSelectionsRef.current?.supplier) {
changedSelections.supplier = globalSelections.supplier;
}
if (globalSelections.company !== prevGlobalSelectionsRef.current?.company) {
changedSelections.company = globalSelections.company;
}
if (globalSelections.line !== prevGlobalSelectionsRef.current?.line) {
changedSelections.line = globalSelections.line;
}
if (globalSelections.subline !== prevGlobalSelectionsRef.current?.subline) {
changedSelections.subline = globalSelections.subline;
}
// Only update data if there are actual changes
if (Object.keys(changedSelections).length > 0) {
setData(currentData =>
currentData.map(row => {
const newRow = { ...row };
// Only apply fields that have changed
if (changedSelections.supplier) {
const supplierValue = setFieldValue(supplierField as Field<T>, changedSelections.supplier);
if (supplierValue) newRow.supplier = supplierValue;
}
if (changedSelections.company) {
const companyValue = setFieldValue(companyField as Field<T>, changedSelections.company);
if (companyValue) newRow.company = companyValue;
}
if (changedSelections.line && productLines) {
const lineValue = setFieldValue(lineField as Field<T>, changedSelections.line, productLines);
if (lineValue) newRow.line = lineValue;
}
if (changedSelections.subline && sublines) {
const sublineValue = setFieldValue(sublineField as Field<T>, changedSelections.subline, sublines);
if (sublineValue) newRow.subline = sublineValue;
}
return newRow;
})
);
}
// Update the ref to current globalSelections
prevGlobalSelectionsRef.current = globalSelections;
}, [globalSelections, fields, productLines, sublines]);
// Run validation when component mounts or when fields change
useEffect(() => {
const validateData = async () => {
// Cast the fields to the expected type for validation
const validationFields = fieldsWithUpdatedOptions as unknown as Fields<T>;
const validatedData = await addErrorsAndRunHooks(
initialDataWithGlobals,
data,
validationFields,
rowHook,
tableHook
@@ -1964,7 +1988,7 @@ export const ValidationStep = <T extends string>({
setData(validatedData as RowData<T>[]);
};
validateData();
}, [initialDataWithGlobals, fieldsWithUpdatedOptions, rowHook, tableHook]);
}, [fieldsWithUpdatedOptions, rowHook, tableHook]);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({})
const [filterByErrors, setFilterByErrors] = useState(false)