'use client' import { useState } from 'react' interface BannerFlag { level: 'ERROR' | 'WARNING' | 'INFO' vendor: string issue: string message: string } interface BannerPreview { config: { categories: { id: string; cookies: { name: string }[] }[] } flags: BannerFlag[] summary: { vendors_total: number vendors_with_no_cookies: number cookies_total: number categories: Record flags_error: number flags_warning: number flags_info: number } } interface DocumentPreview { check_id: string vendor_count: number templates: Record } type Mode = 'banner' | 'documents' export function MigrationPanel({ checkId }: { checkId: string }) { const [open, setOpen] = useState(false) const [mode, setMode] = useState('banner') const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [banner, setBanner] = useState(null) const [docs, setDocs] = useState(null) async function loadPreview(next: Mode) { setMode(next) setOpen(true) setError(null) setLoading(true) try { const path = next === 'banner' ? `/api/sdk/v1/agent/migration/${checkId}/banner-preview` : `/api/sdk/v1/agent/migration/${checkId}/document-preview` const r = await fetch(path) if (!r.ok) throw new Error(`HTTP ${r.status}`) const data = await r.json() if (next === 'banner') setBanner(data) else setDocs(data) } catch (e) { setError(e instanceof Error ? e.message : 'Preview-Ladefehler') } finally { setLoading(false) } } return ( <>
Voll-Audit oeffnen (alle MCs) →
{open && (

{mode === 'banner' ? 'Cookie-Banner Migration' : 'Dokument-Vorbefuellung'}

{loading &&
Lade Preview ...
} {error &&
Fehler: {error}
} {!loading && !error && mode === 'banner' && banner && ( )} {!loading && !error && mode === 'documents' && docs && ( )}
Im Editor oeffnen
)} ) } function BannerPreviewBody({ data }: { data: BannerPreview }) { const { summary, flags, config } = data return (
n > 0).length} />

Kategorien

    {config.categories.map(c => (
  • {c.id}: {c.cookies.length} Cookie(s)
  • ))}
{flags.length > 0 && (

Pruefpunkte

    {flags.map((f, i) => (
  • [{f.level}] {f.vendor}: {f.message}
  • ))}
)}
) } function DocumentPreviewBody({ data }: { data: DocumentPreview }) { return (
{data.vendor_count} Anbieter werden in {Object.keys(data.templates).length} Vorlagen eingespielt.
{Object.entries(data.templates).map(([key, tpl]) => (

{tpl.templateType}

{tpl.suggested_template_search && ( Vorschlag: {tpl.suggested_template_search} )}
            {tpl.initialContent.slice(0, 1200)}{tpl.initialContent.length > 1200 ? '\n…' : ''}
          
))}
) } function Stat({ label, value, tone = 'gray' }: { label: string; value: number; tone?: 'red' | 'amber' | 'gray' }) { const color = tone === 'red' ? 'text-red-700' : tone === 'amber' ? 'text-amber-700' : 'text-gray-800' return (
{value}
{label}
) }