From 56c3f0534d9b6a0bb62ef46011f5bb74aa6f4767 Mon Sep 17 00:00:00 2001 From: Matt Date: Sun, 2 Mar 2025 16:09:55 -0500 Subject: [PATCH] Fix company field changes erasing data (hopefully) --- .../steps/ValidationStep/ValidationStep.tsx | 148 ++++++++++-------- 1 file changed, 86 insertions(+), 62 deletions(-) diff --git a/inventory/src/lib/react-spreadsheet-import/src/steps/ValidationStep/ValidationStep.tsx b/inventory/src/lib/react-spreadsheet-import/src/steps/ValidationStep/ValidationStep.tsx index 4993114..a486071 100644 --- a/inventory/src/lib/react-spreadsheet-import/src/steps/ValidationStep/ValidationStep.tsx +++ b/inventory/src/lib/react-spreadsheet-import/src/steps/ValidationStep/ValidationStep.tsx @@ -1799,6 +1799,7 @@ export const ValidationStep = ({ // Track which changes have been reverted const [revertedChanges, setRevertedChanges] = useState>(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 = ({ 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).find(f => f.key === 'supplier'); - const companyField = Array.from(fields as ReadonlyFields).find(f => f.key === 'company'); - const lineField = Array.from(fields as ReadonlyFields).find(f => f.key === 'line'); - const sublineField = Array.from(fields as ReadonlyFields).find(f => f.key === 'subline'); - - // Helper function to safely set a field value and update options if needed - const setFieldValue = (field: Field | 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 | 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, 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, globalSelections.company); - if (companyValue) newRow.company = companyValue; - } - - if (globalSelections.line && productLines) { - const lineValue = setFieldValue(lineField as Field, globalSelections.line, productLines); - if (lineValue) newRow.line = lineValue; - } - - if (globalSelections.subline && sublines) { - const sublineValue = setFieldValue(sublineField as Field, 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 = ({ }); }, [fields, productLines, sublines, globalSelections?.company, globalSelections?.line]); - const [data, setData] = useState[]>(initialDataWithGlobals); + // Initialize data with initialData + const [data, setData] = useState[]>(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).find(f => f.key === 'supplier'); + const companyField = Array.from(fields as ReadonlyFields).find(f => f.key === 'company'); + const lineField = Array.from(fields as ReadonlyFields).find(f => f.key === 'line'); + const sublineField = Array.from(fields as ReadonlyFields).find(f => f.key === 'subline'); + + // Identify which selections have changed + const changedSelections: Partial = {}; + 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, changedSelections.supplier); + if (supplierValue) newRow.supplier = supplierValue; + } + + if (changedSelections.company) { + const companyValue = setFieldValue(companyField as Field, changedSelections.company); + if (companyValue) newRow.company = companyValue; + } + + if (changedSelections.line && productLines) { + const lineValue = setFieldValue(lineField as Field, changedSelections.line, productLines); + if (lineValue) newRow.line = lineValue; + } + + if (changedSelections.subline && sublines) { + const sublineValue = setFieldValue(sublineField as Field, 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; const validatedData = await addErrorsAndRunHooks( - initialDataWithGlobals, + data, validationFields, rowHook, tableHook @@ -1964,7 +1988,7 @@ export const ValidationStep = ({ setData(validatedData as RowData[]); }; validateData(); - }, [initialDataWithGlobals, fieldsWithUpdatedOptions, rowHook, tableHook]); + }, [fieldsWithUpdatedOptions, rowHook, tableHook]); const [rowSelection, setRowSelection] = useState({}) const [filterByErrors, setFilterByErrors] = useState(false)