'use client'
import React from 'react'
interface Violation {
service: string
severity: string
text: string
legal_ref: string
}
interface PhaseData {
scripts: string[]
cookies: string[]
tracking_services?: string[]
new_tracking?: string[]
violations?: Violation[]
undocumented?: string[]
}
interface ConsentData {
banner_detected: boolean
banner_provider: string
phases: {
before_consent: PhaseData
after_reject: PhaseData
after_accept: PhaseData
}
summary: {
critical: number
high: number
undocumented: number
total_violations: number
category_violations?: number
categories_tested?: number
}
banner_checks?: {
has_impressum_link: boolean
has_dse_link: boolean
violations: { service: string; severity: string; text: string; legal_ref: string }[]
}
category_tests?: {
category: string
category_label: string
tracking_services: string[]
violations: { service: string; severity: string; text: string }[]
}[]
}
const SEV = {
CRITICAL: { bg: 'bg-red-100 border-red-300', text: 'text-red-800', badge: 'bg-red-600' },
HIGH: { bg: 'bg-orange-100 border-orange-300', text: 'text-orange-800', badge: 'bg-orange-500' },
}
function PhaseCard({ title, icon, data, type }: {
title: string; icon: string; data: PhaseData; type: 'before' | 'reject' | 'accept'
}) {
const violations = data.violations || []
const tracking = data.tracking_services || data.new_tracking || []
const undocumented = data.undocumented || []
const hasProblem = violations.length > 0 || undocumented.length > 0
return (
{icon} {title}
{/* Violations */}
{violations.map((v, i) => (
{v.severity}
{v.service}
{v.text}
{v.legal_ref}
))}
{/* Undocumented (Phase C only) */}
{undocumented.map((s, i) => (
✗ {s} — nicht in Cookie-Policy dokumentiert
))}
{/* Tracking services (no violations) */}
{violations.length === 0 && undocumented.length === 0 && tracking.length > 0 && (
{tracking.map((t, i) =>
✓ {t} — {type === 'accept' ? 'mit Consent OK' : 'erkannt'}
)}
)}
{violations.length === 0 && undocumented.length === 0 && tracking.length === 0 && (
✓ Keine Tracking-Dienste erkannt
)}
{/* Cookie/Script count */}
{data.scripts?.length || 0} Scripts
{data.cookies?.length || 0} Cookies
)
}
export function ConsentTestResult({ data }: { data: ConsentData }) {
const s = data.summary
return (
{/* Header */}
Cookie-Banner: {data.banner_detected ? data.banner_provider : 'Nicht erkannt'}
{s.critical > 0 && (
{s.critical} Kritisch
)}
{s.high > 0 && (
{s.high} Hoch
)}
{s.total_violations === 0 && (
Keine Verstoesse
)}
{/* Three Phases */}
{data.banner_detected && (
<>
>
)}
{/* Banner Text Checks */}
{data.banner_checks && (data.banner_checks.violations?.length > 0 || data.banner_checks.has_impressum_link !== undefined) && (
📝 Banner-Text Pruefung
{data.banner_checks.has_impressum_link ? '✓' : '✗'} Impressum-Link
{data.banner_checks.has_dse_link ? '✓' : '✗'} DSE-Link
{data.banner_checks.violations?.map((v: any, i: number) => {
const isHigh = v.severity === 'HIGH' || v.severity === 'CRITICAL'
return (
)
})}
{(!data.banner_checks.violations || data.banner_checks.violations.length === 0) && (
✓ Keine Banner-Text-Verstoesse erkannt
)}
)}
{/* Category Tests (Phase D-F) */}
{data.category_tests && data.category_tests.length > 0 && (
Kategorie-Tests ({data.category_tests.length})
{data.category_tests.map((ct, i) => {
const hasViolations = ct.violations.length > 0
return (
🔀 Nur "{ct.category_label}"
{ct.violations.length > 0 ? (
ct.violations.map((v, vi) => (
FALSCH
{v.text}
))
) : (
{ct.tracking_services.length > 0 ? (
ct.tracking_services.map((s, si) =>
✓ {s} — korrekte Kategorie
)
) : (
✓ Keine Tracking-Dienste geladen — korrekt
)}
)}
)
})}
)}
{/* No banner warning */}
{!data.banner_detected && (
Kein Cookie-Banner erkannt. Alle erkannten Tracking-Dienste laden ohne
Einwilligung — dies ist ein Verstoss gegen §25 TDDDG.
)}
)
}