feat: 5-tab agent UI — PDF export, compare, auth test, all proxies
- 5 tabs: Schnellanalyse, Website-Scan, Cookie-Test, Vergleich, Login-Test - PDF download button in ScanResult - CompareResult: side-by-side compliance comparison table - AuthTestResult: 5 post-login checks with legal refs - API proxies: /scans/pdf, /compare, /authenticated-scan - Compare: textarea for 2-5 URLs, parallel scanning Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
|
||||
interface AuthCheck {
|
||||
found: boolean
|
||||
text: string
|
||||
legal_ref: string
|
||||
}
|
||||
|
||||
interface AuthData {
|
||||
url: string
|
||||
authenticated: boolean
|
||||
login_error: string
|
||||
checks: Record<string, AuthCheck>
|
||||
findings_count: number
|
||||
}
|
||||
|
||||
const CHECK_LABELS: Record<string, { label: string; icon: string }> = {
|
||||
cancel_subscription: { label: 'Kuendigungsbutton (2 Klicks)', icon: '🚫' },
|
||||
delete_account: { label: 'Konto loeschen', icon: '🗑️' },
|
||||
export_data: { label: 'Daten exportieren', icon: '📥' },
|
||||
consent_settings: { label: 'Einwilligungen widerrufen', icon: '⚙️' },
|
||||
profile_visible: { label: 'Profildaten einsehen', icon: '👤' },
|
||||
}
|
||||
|
||||
export function AuthTestResult({ data }: { data: AuthData }) {
|
||||
if (!data.authenticated) {
|
||||
return (
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<p className="text-sm font-medium text-red-800">Login fehlgeschlagen</p>
|
||||
<p className="text-xs text-red-600 mt-1">{data.login_error || 'Credentials oder Formular nicht erkannt'}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-3 h-3 rounded-full bg-green-500" />
|
||||
<span className="text-sm font-medium text-gray-900">Erfolgreich eingeloggt</span>
|
||||
<span className={`ml-auto text-xs px-2 py-1 rounded font-medium ${data.findings_count > 0 ? 'bg-red-100 text-red-700' : 'bg-green-100 text-green-700'}`}>
|
||||
{data.findings_count} fehlende Funktionen
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{Object.entries(data.checks).map(([key, check]) => {
|
||||
const info = CHECK_LABELS[key] || { label: key, icon: '❓' }
|
||||
return (
|
||||
<div key={key} className={`flex items-center gap-3 p-3 rounded-lg border ${check.found ? 'bg-green-50 border-green-200' : 'bg-red-50 border-red-200'}`}>
|
||||
<span className="text-lg">{info.icon}</span>
|
||||
<div className="flex-1">
|
||||
<p className={`text-sm font-medium ${check.found ? 'text-green-800' : 'text-red-800'}`}>
|
||||
{check.found ? '✓' : '✗'} {info.label}
|
||||
</p>
|
||||
{check.text && <p className="text-xs text-gray-500 mt-0.5">{check.text}</p>}
|
||||
</div>
|
||||
<span className="text-[10px] text-gray-400">{check.legal_ref}</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{data.findings_count > 0 && (
|
||||
<div className="bg-red-50 border-l-4 border-red-500 p-3 text-xs text-red-700">
|
||||
<strong>{data.findings_count} Pflichtfunktion(en) fehlen.</strong> Der Nutzer kann seine Rechte
|
||||
nach DSGVO nicht vollstaendig ausueben.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user