b53b36fdc5
- 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>
74 lines
2.7 KiB
TypeScript
74 lines
2.7 KiB
TypeScript
'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>
|
|
)
|
|
}
|