'use client' import React, { useState } from 'react' import { ScanResult } from './_components/ScanResult' <<<<<<< HEAD import { DocCheckTab } from './_components/DocCheckTab' import { BannerCheckTab } from './_components/BannerCheckTab' import { ImpressumCheckTab } from './_components/ImpressumCheckTab' import { ComplianceFAQ } from './_components/ComplianceFAQ' type AnalysisTab = 'scan' | 'doc-check' | 'banner-check' | 'impressum-check' const TABS: { id: AnalysisTab; label: string; desc: string }[] = [ { id: 'scan', label: 'Website-Scan', desc: 'Rechtliche Dokumente finden + Dienstleister erkennen' }, { id: 'doc-check', label: 'Dokumenten-Pruefung', desc: 'DSI, AGB, Cookie-Richtlinie inhaltlich pruefen' }, { id: 'banner-check', label: 'Banner-Check', desc: 'Cookie-Banner auf DSGVO-Konformitaet testen' }, { id: 'impressum-check', label: 'Impressum-Check', desc: 'Impressum auf §5 TMG Pflichtangaben pruefen' }, ] 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) || 'scan') 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 [] } }) ======= 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() >>>>>>> feat/zeroclaw-compliance-agent 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() <<<<<<< HEAD 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('') ======= 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') >>>>>>> feat/zeroclaw-compliance-agent } 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

<<<<<<< HEAD

Analysiere Webseiten und Dokumente auf DSGVO-Konformitaet.

{/* Tab Selection */}
{TABS.map(t => ( ))}
{/* Website-Scan Tab */} {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}
)} {/* Quick Action Buttons — navigate to specialized tabs */} {scanData && (

Jetzt pruefen

{discoveredDocs.map((doc: any, i: number) => ( ))}
)} {/* Full Scan Result */} {scanData?.services && (
)} {/* Scan History */} {scanHistory.length > 0 && (

Letzte Scans

{scanHistory.map((h, i) => ( ))}
=======

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' ? (