'use client' import React, { useState } from 'react' import { ScanResult } from './_components/ScanResult' import { ConsentTestResult } from './_components/ConsentTestResult' import { CompareResult } from './_components/CompareResult' import { AuthTestResult } from './_components/AuthTestResult' type Mode = 'pre_launch' | 'post_launch' type Tab = 'quick' | 'scan' | 'consent' | 'compare' | 'auth' const MODES = [ { id: 'pre_launch' as Mode, label: 'Internes Dokument', desc: 'Vor Veroeffentlichung', icon: '📋' }, { id: 'post_launch' as Mode, label: 'Live-Website', desc: 'Bereits online', icon: '🌐' }, ] const TABS = [ { id: 'quick' as Tab, label: 'Schnellanalyse', info: 'Einzelne URL klassifizieren und bewerten.' }, { id: 'scan' as Tab, label: 'Website-Scan', info: '5-10 Seiten scannen, Dienstleister abgleichen, Pflichtinhalte pruefen.' }, { id: 'consent' as Tab, label: 'Cookie-Test', info: 'Testet mit Browser was VOR und NACH Cookie-Einwilligung geladen wird.' }, { id: 'compare' as Tab, label: 'Vergleich', info: '2-5 Websites parallel scannen und Compliance vergleichen.' }, { id: 'auth' as Tab, label: 'Login-Test', info: 'Nach Login pruefen: Kuendigung, Daten loeschen, Export, Einwilligungen.' }, ] export default function AgentPage() { const [url, setUrl] = useState('') const [urls, setUrls] = useState('') const [mode, setMode] = useState('post_launch') const [tab, setTab] = useState('quick') const [scanLoading, setScanLoading] = useState(false) const [scanError, setScanError] = useState(null) const [scanData, setScanData] = useState(null) const [scanHistory, setScanHistory] = useState([]) const [consentData, setConsentData] = useState(null) const [compareData, setCompareData] = useState(null) const [authData, setAuthData] = useState(null) const [authUser, setAuthUser] = useState('') const [authPass, setAuthPass] = useState('') const { analyze, answerFollowUp, loading, error, result, history } = useAgentAnalysis() 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 { /* retry */ } } } 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() setScanLoading(true) setScanError(null) try { if (tab === 'quick') { setScanLoading(false) analyze(url.trim(), mode) return } let endpoint = '' let body: any = {} if (tab === 'scan') { endpoint = '/api/sdk/v1/agent/scan' body = { url: url.trim(), mode } } else if (tab === 'consent') { endpoint = '/api/sdk/v1/agent/consent-test' body = { url: url.trim() } } else if (tab === 'compare') { endpoint = '/api/sdk/v1/agent/compare' body = { urls: urls.split('\n').map(u => u.trim()).filter(Boolean), mode } } else if (tab === 'auth') { endpoint = '/api/sdk/v1/agent/authenticated-scan' body = { url: url.trim(), username: authUser, password: authPass } } const res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }) if (!res.ok) throw new Error(`Fehlgeschlagen: ${res.status}`) const data = await res.json() if (tab === 'scan') { setScanData(data) setScanHistory(prev => [{ url: url.trim(), ...data, scanned_at: new Date().toISOString() }, ...prev].slice(0, 20)) } else if (tab === 'consent') setConsentData(data) else if (tab === 'compare') setCompareData(data) else if (tab === 'auth') setAuthData(data) } catch (e) { setScanError(e instanceof Error ? e.message : 'Fehler') } finally { setScanLoading(false) } } // Navigate to a specialized tab with a pre-filled URL const navigateToCheck = (targetTab: AnalysisTab, checkUrl: string) => { // Store the URL in the target tab's localStorage key 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) } // Extract discovered documents for quick-action buttons const discoveredDocs = scanData?.discovered_documents || [] const scannedUrl = scanData?.url || url return (

Compliance Agent

Analysiere Dokumente und Webseiten auf DSGVO-Konformitaet.

{/* Mode */}
{MODES.map(m => ( ))}
{/* Tabs */}
{TABS.map(t => ( ))}

{TABS.find(t => t.id === tab)?.info}

{/* Input */}
{tab === 'compare' ? (