'use client' import { useState, useEffect, useCallback, useMemo } from 'react' import { CATEGORY_VENDORS, countNonEWRVendors, isEWR, isOutsideEWR, type VendorInfo, } from './cookie-banner-vendors' /** * CookieBannerOverlay — DSGVO/CNIL-konformer Cookie-Banner mit "Nur EU/EWR" Toggle. * * Alle 4 Kategorien sind auf der ersten Ebene sichtbar (DSK OH Telemedien 2022). * Vendor-Details aufklappbar per Kategorie. EWR-Toggle blockiert Non-EU-Anbieter * auch bei aktivierter Kategorie — einzigartiges CMP-Feature. */ const STORAGE_KEY = 'bp-sdk-cookie-consent' interface ConsentState { necessary: boolean statistics: boolean marketing: boolean functional: boolean ewrOnly: boolean blockedVendors: string[] timestamp: string } function getStoredConsent(): ConsentState | null { if (typeof window === 'undefined') return null try { const raw = localStorage.getItem(STORAGE_KEY) if (!raw) return null return JSON.parse(raw) } catch { return null } } export function CookieBannerOverlay() { const [isOpen, setIsOpen] = useState(false) const [consent, setConsent] = useState({ necessary: true, statistics: false, marketing: false, functional: false, ewrOnly: false, blockedVendors: [], timestamp: '', }) const nonEWRCount = useMemo(() => countNonEWRVendors(), []) const blockedVendors = useMemo(() => { if (!consent.ewrOnly) return [] const blocked: string[] = [] for (const [key, cat] of Object.entries(CATEGORY_VENDORS)) { const catEnabled = key === 'necessary' || consent[key as keyof ConsentState] if (!catEnabled) continue for (const v of cat.vendors) { if (isOutsideEWR(v.country)) blocked.push(v.name) } } return blocked }, [consent]) useEffect(() => { const stored = getStoredConsent() if (!stored) setIsOpen(true) else setConsent(stored) }, []) useEffect(() => { const handler = () => setIsOpen(true) window.addEventListener('openCookieBanner', handler) return () => window.removeEventListener('openCookieBanner', handler) }, []) const saveConsent = useCallback((state: ConsentState) => { const blocked: string[] = [] if (state.ewrOnly) { for (const [key, cat] of Object.entries(CATEGORY_VENDORS)) { const catEnabled = key === 'necessary' || state[key as keyof ConsentState] if (!catEnabled) continue for (const v of cat.vendors) { if (isOutsideEWR(v.country)) blocked.push(v.name) } } } const withMeta = { ...state, blockedVendors: blocked, timestamp: new Date().toISOString() } localStorage.setItem(STORAGE_KEY, JSON.stringify(withMeta)) setConsent(withMeta) setIsOpen(false) window.dispatchEvent(new CustomEvent('sdkCookieConsentUpdated', { detail: withMeta })) }, []) if (!isOpen) return null return ( <>
{/* Header with EWR toggle */}

Cookie-Einstellungen

Waehlen Sie, welche Cookie-Kategorien Sie zulassen moechten.

setConsent(prev => ({ ...prev, ewrOnly: !prev.ewrOnly }))} blockedCount={blockedVendors.length} nonEWRCount={nonEWRCount} />
{/* Categories — always visible (CNIL/DSK compliant) */}
{Object.entries(CATEGORY_VENDORS).map(([key, cat]) => ( key !== 'necessary' && setConsent(prev => ({ ...prev, [key]: v }))} /> ))}
{/* Buttons — two equal-weight options */}
) } export function CookieBannerFAB() { const [hasConsent, setHasConsent] = useState(false) useEffect(() => { setHasConsent(!!getStoredConsent()) const handler = () => setHasConsent(true) window.addEventListener('sdkCookieConsentUpdated', handler) return () => window.removeEventListener('sdkCookieConsentUpdated', handler) }, []) if (!hasConsent) return null return ( ) } // ─── EWR Toggle with Info Button ────────────────────────── function EWRToggle({ checked, onChange, blockedCount, nonEWRCount }: { checked: boolean; onChange: () => void; blockedCount: number; nonEWRCount: number }) { const [showInfo, setShowInfo] = useState(false) return (
Nur EU/EWR
{checked && blockedCount > 0 && ( {blockedCount} blockiert )} {showInfo && (
Nur EU/EWR-Anbieter

Erlaubt nur Anbieter mit Sitz im EWR (EU + Island, Liechtenstein, Norwegen) oder der Schweiz. {nonEWRCount} Anbieter ausserhalb werden blockiert — auch bei aktivierter Cookie-Kategorie.

)}
) } // ─── Category Section with Vendor Table ─────────────────── function CategorySection({ label, description, vendors, checked, disabled, ewrOnly, onChange }: { label: string; description: string; vendors: VendorInfo[]; checked: boolean disabled?: boolean; ewrOnly: boolean; onChange: (v: boolean) => void }) { const [expanded, setExpanded] = useState(false) const nonEuVendors = vendors.filter(v => isOutsideEWR(v.country)) const blockedCount = ewrOnly && checked ? nonEuVendors.length : 0 const activeCount = checked ? vendors.length - blockedCount : 0 return (
{expanded && (
{vendors.map((v, i) => { const blocked = ewrOnly && checked && isOutsideEWR(v.country) const active = checked && !blocked return ( ) })}
Verarbeiter Cookies Dauer Land
{blocked ? ( ) : active ? ( ) : ( )} {v.name} {v.cookies} {v.retention} {isOutsideEWR(v.country) ? ( {v.country} ) : ( {v.country} )}
)}
) }