From a673cb0ce49bc7c46697a40b248e079c7b82d5a8 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Wed, 11 Mar 2026 08:50:28 +0100 Subject: [PATCH] fix(sdk): Prevent auto-save from overwriting completed profile status The auto-save timers (SDK context + backend) were firing after completeAndSaveProfile(), resetting isComplete back to false. Fix: skip auto-save when currentStep===99 (completed), cancel pending timers before completing, and await backend save before updating SDK context. Co-Authored-By: Claude Opus 4.6 --- .../app/sdk/company-profile/page.tsx | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/admin-compliance/app/sdk/company-profile/page.tsx b/admin-compliance/app/sdk/company-profile/page.tsx index 9c80ce5..96965e0 100644 --- a/admin-compliance/app/sdk/company-profile/page.tsx +++ b/admin-compliance/app/sdk/company-profile/page.tsx @@ -2486,6 +2486,9 @@ export default function CompanyProfilePage() { return } + // Don't auto-save drafts if profile is already completed (step 99) + if (currentStep === 99) return + // Debounce: sync to SDK context after 500ms of inactivity if (autoSaveRef.current) clearTimeout(autoSaveRef.current) autoSaveRef.current = setTimeout(() => { @@ -2500,7 +2503,7 @@ export default function CompanyProfilePage() { if (autoSaveRef.current) clearTimeout(autoSaveRef.current) } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formData]) + }, [formData, currentStep]) // Shared payload builder for draft saves and final save (DRY) const buildProfilePayload = (isComplete: boolean) => ({ @@ -2578,6 +2581,9 @@ export default function CompanyProfilePage() { useEffect(() => { if (!initialLoadDone.current) return + // Don't auto-save drafts if profile is already completed + if (currentStep === 99) return + const hasData = formData.companyName || (formData.industry && formData.industry.length > 0) if (!hasData) return @@ -2601,7 +2607,7 @@ export default function CompanyProfilePage() { if (backendAutoSaveRef.current) clearTimeout(backendAutoSaveRef.current) } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formData]) + }, [formData, currentStep]) const [draftSaveStatus, setDraftSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle') const draftSaveTimerRef = React.useRef | null>(null) @@ -2646,17 +2652,17 @@ export default function CompanyProfilePage() { } const completeAndSaveProfile = async () => { + // Cancel any pending auto-save timers to prevent them from overwriting isComplete + if (autoSaveRef.current) clearTimeout(autoSaveRef.current) + if (backendAutoSaveRef.current) clearTimeout(backendAutoSaveRef.current) + const completeProfile: CompanyProfile = { ...formData, isComplete: true, completedAt: new Date(), } as CompanyProfile - setCompanyProfile(completeProfile) - dispatch({ type: 'COMPLETE_STEP', payload: 'company-profile' }) - dispatch({ type: 'SET_STATE', payload: { projectVersion: (state.projectVersion || 0) + 1 } }) - - // Also persist to dedicated backend endpoint + // Persist to backend FIRST (with isComplete=true) try { await fetch(profileApiUrl(), { method: 'POST', @@ -2667,6 +2673,11 @@ export default function CompanyProfilePage() { console.error('Failed to save company profile to backend:', err) } + // Then update SDK context (after backend is done, no race condition) + setCompanyProfile(completeProfile) + dispatch({ type: 'COMPLETE_STEP', payload: 'company-profile' }) + dispatch({ type: 'SET_STATE', payload: { projectVersion: (state.projectVersion || 0) + 1 } }) + setCurrentStep(99) // Show summary }