'use client' import React, { useState } from 'react' import { ScanResult } from './_components/ScanResult' import { ComplianceCheckTab } from './_components/ComplianceCheckTab' import { BannerCheckTab } from './_components/BannerCheckTab' import { ComplianceFAQ } from './_components/ComplianceFAQ' type AnalysisTab = 'scan' | 'compliance-check' | 'banner-check' const TABS: { id: AnalysisTab; label: string; desc: string }[] = [ { id: 'scan', label: 'Website-Scan', desc: 'Rechtliche Dokumente finden + Dienstleister erkennen' }, { id: 'compliance-check', label: 'Compliance-Check', desc: 'Alle rechtlichen Dokumente zusammen pruefen' }, { id: 'banner-check', label: 'Banner-Check', desc: 'Cookie-Banner auf DSGVO-Konformitaet testen' }, ] export default function AgentPage() { const [url, setUrl] = useState(() => typeof window !== 'undefined' ? localStorage.getItem('agent-scan-url') || '' : '') const [tab, setTab] = useState(() => (typeof window !== 'undefined' ? localStorage.getItem('agent-scan-tab') as AnalysisTab : null) || 'compliance-check') const [scanLoading, setScanLoading] = useState(false) const [scanError, setScanError] = useState(null) const [scanData, setScanData] = useState(() => { if (typeof window === 'undefined') return null try { const s = localStorage.getItem('agent-scan-result'); return s ? JSON.parse(s) : null } catch { return null } }) const [scanProgress, setScanProgress] = useState('') const [activeScanId, setActiveScanId] = useState(() => typeof window !== 'undefined' ? localStorage.getItem('agent-scan-id') || '' : '') const [scanHistory, setScanHistory] = useState<{ url: string; date: string; findings: number; docs: number; resultKey: string }[]>(() => { if (typeof window === 'undefined') return [] try { return JSON.parse(localStorage.getItem('agent-scan-history') || '[]') } catch { return [] } }) React.useEffect(() => { localStorage.setItem('agent-scan-url', url) }, [url]) React.useEffect(() => { localStorage.setItem('agent-scan-tab', tab) }, [tab]) // Resume polling if scan was in progress React.useEffect(() => { if (!activeScanId || scanData?.services) return let cancelled = false setScanLoading(true) setScanProgress('Scan laeuft noch...') const poll = async () => { while (!cancelled) { await new Promise(r => setTimeout(r, 5000)) try { const res = await fetch(`/api/sdk/v1/agent/scan?scan_id=${activeScanId}`) if (!res.ok) continue const data = await res.json() if (data.progress) setScanProgress(data.progress) if (data.status === 'completed' && data.result) { setScanData(data.result); setScanProgress(''); setScanLoading(false) localStorage.setItem('agent-scan-result', JSON.stringify(data.result)) localStorage.removeItem('agent-scan-id'); setActiveScanId('') _addToHistory(data.result); return } if (data.status === 'failed' || data.status === 'not_found') { if (data.status === 'failed') setScanError(data.error || 'Scan fehlgeschlagen') setScanProgress(''); setScanLoading(false) localStorage.removeItem('agent-scan-id'); setActiveScanId(''); return } } catch {} } } poll() return () => { cancelled = true } }, []) // eslint-disable-line react-hooks/exhaustive-deps const _addToHistory = (result: any) => { const resultKey = `scan-result-${Date.now()}` try { localStorage.setItem(resultKey, JSON.stringify(result)) } catch {} const entry = { url: url || result.url || '', date: new Date().toISOString(), findings: result.findings?.length || 0, docs: result.discovered_documents?.length || 0, resultKey } const updated = [entry, ...scanHistory].slice(0, 30) setScanHistory(updated); localStorage.setItem('agent-scan-history', JSON.stringify(updated)) } const handleScan = async (e: React.FormEvent) => { e.preventDefault() if (!url.trim()) return setScanLoading(true); setScanError(null); setScanData(null); setScanProgress('Scan wird gestartet...') try { const startRes = await fetch('/api/sdk/v1/agent/scan', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: url.trim(), mode: 'post_launch' }) }) if (!startRes.ok) throw new Error(`Scan konnte nicht gestartet werden: ${startRes.status}`) const { scan_id } = await startRes.json() if (!scan_id) throw new Error('Keine Scan-ID erhalten') setActiveScanId(scan_id); localStorage.setItem('agent-scan-id', scan_id) let attempts = 0 while (attempts < 120) { await new Promise(r => setTimeout(r, 5000)) const pollRes = await fetch(`/api/sdk/v1/agent/scan?scan_id=${scan_id}`) if (!pollRes.ok) { attempts++; continue } const pollData = await pollRes.json() if (pollData.progress) setScanProgress(pollData.progress) if (pollData.status === 'completed' && pollData.result) { setScanData(pollData.result); setScanProgress('') localStorage.setItem('agent-scan-result', JSON.stringify(pollData.result)) localStorage.removeItem('agent-scan-id'); setActiveScanId(''); _addToHistory(pollData.result); break } if (pollData.status === 'failed') throw new Error(pollData.error || 'Scan fehlgeschlagen') attempts++ } if (attempts >= 120) throw new Error('Scan-Timeout (10 Minuten)') } catch (e) { setScanError(e instanceof Error ? e.message : 'Unbekannter Fehler'); setScanProgress('') } finally { setScanLoading(false) } } const navigateToCheck = (targetTab: AnalysisTab, checkUrl: string) => { const keyMap: Record = { 'doc-check': 'doc-check-prefill-url', 'banner-check': 'banner-check-url', 'impressum-check': 'impressum-check-url' } if (keyMap[targetTab]) localStorage.setItem(keyMap[targetTab], checkUrl) setTab(targetTab) } const discoveredDocs = scanData?.discovered_documents || [] const scannedUrl = scanData?.url || url return (

Compliance Agent

Analysiere Webseiten und Dokumente auf DSGVO-Konformitaet.

{TABS.map(t => ( ))}
{tab === 'scan' && (

Website-Scan (Discovery)

Findet alle rechtlichen Dokumente (DSI, AGB, Impressum, Cookie, Widerruf), erkennt eingesetzte Drittdienste und prueft ob sie in der DSE dokumentiert sind.

setUrl(e.target.value)} placeholder="https://www.example.com/" className="flex-1 px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent text-sm" disabled={scanLoading} required />
{scanProgress &&
{scanProgress}
} {scanError &&
{scanError}
} {scanData && (

Jetzt pruefen

{discoveredDocs.map((doc: any, i: number) => ( ))}
)} {scanData?.services &&
} {scanHistory.length > 0 && (

Letzte Scans

{scanHistory.map((h, i) => ( ))}
)}
)} {tab === 'compliance-check' && } {tab === 'banner-check' && }
) }