diff --git a/frontend/src/pages/portal/PortalPrivacy.tsx b/frontend/src/pages/portal/PortalPrivacy.tsx index 61b148b9..23c5148d 100644 --- a/frontend/src/pages/portal/PortalPrivacy.tsx +++ b/frontend/src/pages/portal/PortalPrivacy.tsx @@ -56,6 +56,15 @@ export default function PortalPrivacy() { }, }); + // Kurzlebigen Download-Token (60s) für den PDF-Link. Hooks MÜSSEN vor jedem + // early-return stehen (Rules of Hooks) – sonst weiße Seite beim ersten Render. + const [pdfToken, setPdfToken] = useState(null); + useEffect(() => { + let cancelled = false; + authApi.getDownloadToken().then((t) => { if (!cancelled) setPdfToken(t); }); + return () => { cancelled = true; }; + }, []); + const handleToggle = (consent: CustomerConsent) => { const newStatus: ConsentStatus = consent.status === 'GRANTED' ? 'WITHDRAWN' : 'GRANTED'; updateMutation.mutate({ consentType: consent.consentType, status: newStatus }); @@ -95,14 +104,6 @@ export default function PortalPrivacy() { const privacyPolicyHtml = data?.data?.privacyPolicyHtml || ''; const allGranted = consents.every((c) => c.status === 'GRANTED'); - // Kurzlebigen Download-Token (60s) für den PDF-Link. - const [pdfToken, setPdfToken] = useState(null); - useEffect(() => { - let cancelled = false; - authApi.getDownloadToken().then((t) => { if (!cancelled) setPdfToken(t); }); - return () => { cancelled = true; }; - }, []); - return (