'use client' /** * Snapshot-Detail — öffnet einen gespeicherten Check aus der Historie und * zeigt die Ergebnis-Views aus den Rohdaten (kein Re-Crawl), als Modul-Tabs: * Cookies & Tracking + Impressum + Datenschutzerklärung (AGB folgen). * Doc-Agenten (Impressum/DSE) laufen beim Öffnen des Tabs auf dem gespeicherten * Text — generisch via AgentModuleTab. */ import React, { use as useUnwrap, useEffect, useMemo, useState } from 'react' import Link from 'next/link' import { CookieLibraryPanel } from '../../_components/CookieLibraryPanel' import { CookieDeclarationDiff } from '../../_components/CookieDeclarationDiff' import { CookieResultView } from '../../_components/CookieResultView' import { AgentModuleTab } from '../../_components/AgentModuleTab' import { BrowserBehaviorView } from '../../_components/BrowserBehaviorView' import { AuditReportTab } from '../../_components/AuditReportTab' export default function SnapshotDetail( { params }: { params: Promise<{ snapshotId: string }> }, ) { const { snapshotId } = useUnwrap(params) const [snap, setSnap] = useState(null) const [check, setCheck] = useState(null) // cookie-check const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [tab, setTab] = useState('') useEffect(() => { let cancelled = false fetch(`/api/sdk/v1/agent/snapshots/${snapshotId}`) .then(r => r.json()) .then(d => { if (cancelled) return if (d?.error) setError(d.error); else setSnap(d) }) .catch(e => { if (!cancelled) setError(String(e)) }) .finally(() => { if (!cancelled) setLoading(false) }) return () => { cancelled = true } }, [snapshotId]) // Cookie-Abgleich einmal laden (Findings + cookie_categories für beide Views). useEffect(() => { let cancelled = false fetch(`/api/sdk/v1/agent/snapshots/${snapshotId}/cookie-check`) .then(r => r.json()) .then(d => { if (!cancelled) setCheck(d) }) .catch(() => { if (!cancelled) setCheck(null) }) return () => { cancelled = true } }, [snapshotId]) const docs = snap?.doc_entries || [] const hasCookies = (snap?.cmp_vendors?.length ?? 0) > 0 // Browser-Verhalten braucht nur eine scanbare URL (on-demand-Live-Lauf). const hasSite = docs.some((e: any) => (e.url || '').trim()) || (!!snap?.site_domain && snap.site_domain !== 'unknown') const modules = useMemo(() => [ ...(hasCookies ? [{ key: 'cookie', label: 'Cookies & Tracking' }] : []), // Doc-Tabs IMMER zeigen; ohne erfassten Text gibt der Tab einen Hinweis // ("kein …-Text erfasst") statt zu verschwinden. { key: 'impressum', label: 'Impressum' }, { key: 'dse', label: 'Datenschutzerklärung' }, { key: 'agb', label: 'AGB' }, ...(hasSite ? [{ key: 'browser', label: 'Browser-Verhalten' }] : []), { key: 'bericht', label: 'Bericht' }, // eslint-disable-next-line react-hooks/exhaustive-deps ], [snap]) useEffect(() => { if (!tab && modules.length) setTab(modules[0].key) }, [modules, tab]) const tabBtn = (key: string, label: string) => ( ) return (
‹ Zurück zur Historie {loading ? (
Lade Snapshot…
) : error || !snap ? (
Snapshot nicht gefunden.
) : modules.length === 0 ? (
Dieser Snapshot enthält keine auswertbaren Daten.
) : ( <>

{snap.site_label || snap.site_domain || 'Snapshot'}

{snap.site_domain} {snap.created_at ? ` · ${String(snap.created_at).slice(0, 16).replace('T', ' ')}` : ''}

{snap.check_id && ( Voll-Audit öffnen (alle MCs) → )}
{modules.map(m => tabBtn(m.key, m.label))}
{tab === 'cookie' && hasCookies && (
)} {tab === 'impressum' && ( )} {tab === 'dse' && ( )} {tab === 'agb' && ( )} {tab === 'browser' && ( )} {tab === 'bericht' && ( )} )}
) }