'use client' import { useState, useEffect, useCallback } from 'react' import { CATEGORY_VENDORS, countNonEWRVendors, isEWR, isOutsideEWR, } from '@/components/sdk/cookie-banner-vendors' /** * Cookie Banner Live-Vorschau — simulates a real website with the banner. * * Purpose: Test the full consent flow end-to-end: * 1. Visitor lands on simulated website → banner appears * 2. Visitor makes consent choice (accept/reject/custom + EWR toggle) * 3. Consent is recorded via Banner API (POST /banner/consent) * 4. Admin can verify in /sdk/consent-management and /sdk/einwilligungen * * This page runs OUTSIDE the SDK layout to simulate a real website experience. */ // Use Next.js API proxy to avoid SSL cert issues with direct backend calls const API_BASE = '/api/sdk/v1/banner' const SITE_ID = 'preview-test-site' const TENANT_ID = '9282a473-5c95-4b3a-bf78-0ecc0ec71d3e' interface ConsentRecord { id: string categories: string[] ewrOnly: boolean blockedVendors: string[] timestamp: string device_fingerprint: string } function generateFingerprint(): string { const nav = typeof navigator !== 'undefined' ? navigator : null const seed = [ nav?.userAgent || '', nav?.language || '', screen?.width || 0, screen?.height || 0, new Date().getTimezoneOffset(), ].join('|') let hash = 0 for (let i = 0; i < seed.length; i++) { hash = ((hash << 5) - hash + seed.charCodeAt(i)) | 0 } return `fp-${Math.abs(hash).toString(36)}-${Date.now().toString(36)}` } export default function CookieBannerPreviewPage() { const [consent, setConsent] = useState(null) const [showBanner, setShowBanner] = useState(true) const [ewrOnly, setEwrOnly] = useState(false) const [categories, setCategories] = useState({ necessary: true, statistics: false, marketing: false, functional: false }) const [saving, setSaving] = useState(false) const [apiResult, setApiResult] = useState(null) const [fingerprint] = useState(() => generateFingerprint()) // Check for existing consent on this simulated site useEffect(() => { async function check() { try { const res = await fetch( `${API_BASE}/banner/consent?site_id=${SITE_ID}&device_fingerprint=${fingerprint}`, { headers: { 'x-tenant-id': TENANT_ID } }, ) if (res.ok) { const data = await res.json() if (data.has_consent) { setConsent(data.consent) setShowBanner(false) } } } catch { /* first visit */ } } check() }, [fingerprint]) const saveConsent = useCallback(async (cats: typeof categories) => { setSaving(true) const blocked: string[] = [] if (ewrOnly) { for (const [key, cat] of Object.entries(CATEGORY_VENDORS)) { if (!cats[key as keyof typeof cats]) continue for (const v of cat.vendors) { if (isOutsideEWR(v.country)) blocked.push(v.name) } } } try { const res = await fetch(`${API_BASE}/banner/consent`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-tenant-id': TENANT_ID }, body: JSON.stringify({ site_id: SITE_ID, device_fingerprint: fingerprint, categories: Object.entries(cats).filter(([, v]) => v).map(([k]) => k), vendors: [], consent_string: JSON.stringify({ ewrOnly, blockedVendors: blocked }), user_agent: navigator.userAgent, }), }) const data = await res.json() setApiResult(data) setConsent({ ...data, ewrOnly, blockedVendors: blocked, timestamp: new Date().toISOString() }) setShowBanner(false) } catch (err: any) { setApiResult({ error: err.message }) // Close banner even on error — don't trap the user setShowBanner(false) } setSaving(false) }, [ewrOnly, fingerprint]) const nonEWRCount = countNonEWRVendors() return (
{/* Simulated Website Header */}
MusterShop GmbH
{/* Simulated Website Content */}

Willkommen bei MusterShop

Dies ist eine simulierte Website um den Cookie-Banner zu testen. Die Consent-Daten werden ueber die echte Banner-API gespeichert und erscheinen in Ihrem CMP unter Consent-Records und Consent-Verwaltung.

{['Premium Paket', 'Standard Paket', 'Starter Paket', 'Enterprise'].map(p => (

{p}

Lorem ipsum dolor sit amet

))}
{/* API Debug Panel */}

API Debug

Site ID {SITE_ID}
Fingerprint {fingerprint}
Consent {consent ? 'Gespeichert' : 'Ausstehend'}
{consent && ( <>
Kategorien {consent.categories?.join(', ')}
EWR-Only {consent.ewrOnly ? 'Ja' : 'Nein'}
{consent.blockedVendors?.length > 0 && (
Blockiert:
{consent.blockedVendors.map(v => ( {v} ))}
)} )}
{consent && ( )}
{apiResult && (
POST /banner/consent Response:
{JSON.stringify(apiResult, null, 2)}
)}
Pruefen Sie das Ergebnis in:
{/* Simulated Website Footer */}
MusterShop GmbH — Simulierte Test-Website
Datenschutz Impressum
{/* === REAL COOKIE BANNER === */} {showBanner && ( <>
{/* Header */}

Cookie-Einstellungen

Waehlen Sie, welche Cookie-Kategorien Sie zulassen moechten.

{/* EWR Toggle */}
Nur EU/EWR
{/* Categories */}
{Object.entries(CATEGORY_VENDORS).map(([key, cat]) => { const checked = key === 'necessary' ? true : categories[key as keyof typeof categories] const nonEU = cat.vendors.filter(v => isOutsideEWR(v.country)) const blocked = ewrOnly && checked ? nonEU.length : 0 return (
{cat.label} {blocked > 0 ? `${cat.vendors.length - blocked} aktiv, ${blocked} blockiert` : `${cat.vendors.length} Verarbeiter`}
{cat.description}
) })}
{/* Buttons */}
Datenschutzerklaerung Impressum
)}
) }