diff --git a/client/src/components/shop-info/shop-info.container.jsx b/client/src/components/shop-info/shop-info.container.jsx index afcd7968d..a820dce69 100644 --- a/client/src/components/shop-info/shop-info.container.jsx +++ b/client/src/components/shop-info/shop-info.container.jsx @@ -23,13 +23,24 @@ export default function ShopInfoContainer() { }); const notification = useNotification(); - const combinedFeatureConfig = { - ...FEATURE_CONFIGS.general, - ...FEATURE_CONFIGS.responsibilitycenters - }; + const combineFeatureConfigs = (...configs) => + (configs || []) + .filter(Boolean) + .flatMap((cfg) => Object.entries(cfg)) + .reduce((acc, [featureName, fieldPaths]) => { + if (!Array.isArray(fieldPaths)) return acc; + acc[featureName] = [...(acc[featureName] ?? []), ...fieldPaths]; + return acc; + }, {}); + + const combinedFeatureConfig = combineFeatureConfigs(FEATURE_CONFIGS.general, FEATURE_CONFIGS.responsibilitycenters); // Use form data preservation for all shop-info features - const { createSubmissionHandler } = useFormDataPreservation(form, data?.bodyshops[0], combinedFeatureConfig); + const { createSubmissionHandler, preserveHiddenFormData } = useFormDataPreservation( + form, + data?.bodyshops[0], + combinedFeatureConfig + ); const handleFinish = createSubmissionHandler((values) => { setSaveLoading(true); @@ -51,8 +62,11 @@ export default function ShopInfoContainer() { }); useEffect(() => { - if (data) form.resetFields(); - }, [form, data]); + if (!data) return; + form.resetFields(); + // After reset, re-apply hidden field preservation so values aren't wiped + preserveHiddenFormData(); + }, [data, form, preserveHiddenFormData]); if (error) return ; if (loading) return ; diff --git a/client/src/components/shop-info/useFormDataPreservation.js b/client/src/components/shop-info/useFormDataPreservation.js index 310ff0202..93978962e 100644 --- a/client/src/components/shop-info/useFormDataPreservation.js +++ b/client/src/components/shop-info/useFormDataPreservation.js @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { HasFeatureAccess } from "./../feature-wrapper/feature-wrapper.component"; /** @@ -8,73 +8,57 @@ import { HasFeatureAccess } from "./../feature-wrapper/feature-wrapper.component * @param {Object} featureConfig - Configuration object defining which features and their associated fields to preserve */ export const useFormDataPreservation = (form, bodyshop, featureConfig) => { - const getNestedValue = (obj, path) => { - return path.reduce((current, key) => current?.[key], obj); - }; - + // Safe nested getters/setters using path arrays + const getNestedValue = (obj, path) => path?.reduce((acc, key) => acc?.[key], obj); const setNestedValue = (obj, path, value) => { const lastKey = path[path.length - 1]; - const parentPath = path.slice(0, -1); - - const parent = parentPath.reduce((current, key) => { - if (!current[key]) current[key] = {}; - return current[key]; + const parent = path.slice(0, -1).reduce((curr, key) => { + if (!curr[key] || typeof curr[key] !== "object") curr[key] = {}; + return curr[key]; }, obj); - parent[lastKey] = value; }; - const preserveHiddenFormData = useCallback(() => { - const preservationData = {}; - let hasDataToPreserve = false; - + // Paths for features that are NOT accessible + const disabledPaths = useMemo(() => { + const result = []; + if (!featureConfig) return result; Object.entries(featureConfig).forEach(([featureName, fieldPaths]) => { const hasAccess = HasFeatureAccess({ featureName, bodyshop }); + if (hasAccess || !Array.isArray(fieldPaths)) return; + fieldPaths.forEach((p) => Array.isArray(p) && p.length && result.push(p)); + }); + return result; + }, [featureConfig, bodyshop]); - if (!hasAccess) { - fieldPaths.forEach((fieldPath) => { - const currentValues = form.getFieldsValue(); - let value = getNestedValue(currentValues, fieldPath); + const preserveHiddenFormData = useCallback(() => { + const currentValues = form.getFieldsValue(); + const preservationData = {}; + let hasAny = false; - if (value === undefined || value === null) { - value = getNestedValue(bodyshop, fieldPath); - } - - if (value !== undefined && value !== null) { - setNestedValue(preservationData, fieldPath, value); - hasDataToPreserve = true; - } - }); + disabledPaths.forEach((path) => { + let value = getNestedValue(currentValues, path); + if (value == null) value = getNestedValue(bodyshop, path); + if (value != null) { + setNestedValue(preservationData, path, value); + hasAny = true; } }); - if (hasDataToPreserve) { - form.setFieldsValue(preservationData); - } - }, [form, featureConfig, bodyshop]); + if (hasAny) form.setFieldsValue(preservationData); + }, [form, bodyshop, disabledPaths]); const getCompleteFormValues = () => { - const currentFormValues = form.getFieldsValue(); - const completeValues = { ...currentFormValues }; + const currentValues = form.getFieldsValue(); + const complete = { ...currentValues }; - Object.entries(featureConfig).forEach(([featureName, fieldPaths]) => { - const hasAccess = HasFeatureAccess({ featureName, bodyshop }); - - if (!hasAccess) { - fieldPaths.forEach((fieldPath) => { - let value = getNestedValue(currentFormValues, fieldPath); - if (value === undefined || value === null) { - value = getNestedValue(bodyshop, fieldPath); - } - - if (value !== undefined && value !== null) { - setNestedValue(completeValues, fieldPath, value); - } - }); - } + disabledPaths.forEach((path) => { + let value = getNestedValue(currentValues, path); + if (value == null) value = getNestedValue(bodyshop, path); + if (value != null) setNestedValue(complete, path, value); }); - return completeValues; + return complete; }; const createSubmissionHandler = (originalHandler) => { @@ -103,8 +87,8 @@ export const FEATURE_CONFIGS = { ["md_responsibility_centers", "profits"], ["md_responsibility_centers", "defaults"], ["md_responsibility_centers", "dms_defaults"], - ["md_responsibility_centers", "taxes", "itemexemptcode"], - ["md_responsibility_centers", "taxes", "invoiceexemptcode"], + ["md_responsibility_centers", "taxes"], + ["md_responsibility_centers", "cieca_pfl"], ["md_responsibility_centers", "ar"], ["md_responsibility_centers", "refund"], ["md_responsibility_centers", "sales_tax_codes"],