From 29e6998a28bee518b0896f96a278c07c7f2c1e9b Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Tue, 3 Mar 2026 22:35:11 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20compliance-scope=20=E2=80=94=20Infinite-?= =?UTF-8?q?Render-Loop=20+=20Sticky-Footer-Overlap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit useEffect[dispatch, sdkState.complianceScope] → dispatch → sdkState-Update → Effect wieder auslösen → setScopeState → dispatch → ... (endlos) Fix: Load-Effect mit [] (einmalig on mount), CSS-Kommentar für eslint. Sticky bottom-6 Footer lag über Wizard-Navigationsbuttons ohne padding-Puffer. Fix: tab content pb-28 damit Zurück/Weiter/Auswertung-starten erreichbar bleiben. Co-Authored-By: Claude Opus 4.6 --- .../app/(sdk)/sdk/compliance-scope/page.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/admin-compliance/app/(sdk)/sdk/compliance-scope/page.tsx b/admin-compliance/app/(sdk)/sdk/compliance-scope/page.tsx index 9dd35a1..037d11e 100644 --- a/admin-compliance/app/(sdk)/sdk/compliance-scope/page.tsx +++ b/admin-compliance/app/(sdk)/sdk/compliance-scope/page.tsx @@ -49,21 +49,21 @@ export default function ComplianceScopePage() { const [isLoading, setIsLoading] = useState(true) const [isEvaluating, setIsEvaluating] = useState(false) - // Load from SDK context first (persisted via State API), then localStorage as fallback + // Load from SDK context first (persisted via State API), then localStorage as fallback. + // Runs ONCE on mount only — empty deps breaks the dispatch→sdkState→setScopeState→dispatch loop. useEffect(() => { try { // Priority 1: SDK context (loaded from PostgreSQL via State API) - if (sdkState.complianceScope && sdkState.complianceScope.answers?.length > 0) { - setScopeState(sdkState.complianceScope) - // Also update localStorage for offline fallback - localStorage.setItem(STORAGE_KEY, JSON.stringify(sdkState.complianceScope)) + const ctxScope = sdkState.complianceScope + if (ctxScope && ctxScope.answers?.length > 0) { + setScopeState(ctxScope) + localStorage.setItem(STORAGE_KEY, JSON.stringify(ctxScope)) } else { // Priority 2: localStorage fallback const stored = localStorage.getItem(STORAGE_KEY) if (stored) { const parsed = JSON.parse(stored) as ComplianceScopeState setScopeState(parsed) - // Sync to SDK context for backend persistence dispatch({ type: 'SET_COMPLIANCE_SCOPE', payload: parsed }) } } @@ -72,7 +72,8 @@ export default function ComplianceScopePage() { } finally { setIsLoading(false) } - }, [dispatch, sdkState.complianceScope]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) // Save to localStorage and SDK context whenever state changes useEffect(() => { @@ -248,8 +249,8 @@ export default function ComplianceScopePage() { - {/* Tab Content */} -
+ {/* Tab Content — pb-28 verhindert dass sticky Footer die unteren Buttons verdeckt */} +
{activeTab === 'overview' && (