From 916337b5036475ece00d99a55361df649f9afe36 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Mon, 11 May 2026 15:04:29 +0200 Subject: [PATCH] fix: Restore new page.tsx with 4 tabs (was overwritten by merge) Merge took the old page.tsx from main which still had useAgentAnalysis. Restored: Website-Scan, Dokumenten-Pruefung, Banner-Check, Impressum-Check. Removed: Schnellanalyse, Consent-Test, Compare, Auth-Test tabs. Co-Authored-By: Claude Opus 4.6 (1M context) --- admin-compliance/app/sdk/agent/page.tsx | 315 +++++++++--------------- 1 file changed, 118 insertions(+), 197 deletions(-) diff --git a/admin-compliance/app/sdk/agent/page.tsx b/admin-compliance/app/sdk/agent/page.tsx index 71463cc..78ef42b 100644 --- a/admin-compliance/app/sdk/agent/page.tsx +++ b/admin-compliance/app/sdk/agent/page.tsx @@ -2,41 +2,35 @@ 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' +import { DocCheckTab } from './_components/DocCheckTab' +import { BannerCheckTab } from './_components/BannerCheckTab' +import { ImpressumCheckTab } from './_components/ImpressumCheckTab' +import { ComplianceFAQ } from './_components/ComplianceFAQ' -type Mode = 'pre_launch' | 'post_launch' -type Tab = 'quick' | 'scan' | 'consent' | 'compare' | 'auth' +type AnalysisTab = 'scan' | 'doc-check' | 'banner-check' | 'impressum-check' -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.' }, +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('') - const [urls, setUrls] = useState('') - const [mode, setMode] = useState('post_launch') - const [tab, setTab] = useState('quick') + 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(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() + 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]) @@ -56,24 +50,17 @@ export default function AgentPage() { const data = await res.json() if (data.progress) setScanProgress(data.progress) if (data.status === 'completed' && data.result) { - setScanData(data.result) - setScanProgress('') - setScanLoading(false) + 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 + 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 + setScanProgress(''); setScanLoading(false) + localStorage.removeItem('agent-scan-id'); setActiveScanId(''); return } - } catch { /* retry */ } + } catch {} } } poll() @@ -83,83 +70,47 @@ export default function AgentPage() { 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 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)) + setScanHistory(updated); localStorage.setItem('agent-scan-history', JSON.stringify(updated)) } const handleScan = async (e: React.FormEvent) => { e.preventDefault() - setScanLoading(true) - setScanError(null) - + if (!url.trim()) return + setScanLoading(true); setScanError(null); setScanData(null); setScanProgress('Scan wird gestartet...') try { - if (tab === 'quick') { - setScanLoading(false) - analyze(url.trim(), mode) - return + 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++ } - - 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) - } + if (attempts >= 120) throw new Error('Scan-Timeout (10 Minuten)') + } catch (e) { setScanError(e instanceof Error ? e.message : 'Unbekannter Fehler'); setScanProgress('') } + 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) - } + 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 @@ -167,109 +118,79 @@ export default function AgentPage() {

Compliance Agent

-

Analysiere Dokumente und Webseiten auf DSGVO-Konformitaet.

+

Analysiere Webseiten und Dokumente auf DSGVO-Konformitaet.

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

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

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