Spaces:
Sleeping
Sleeping
| import { AlertTriangle, CheckCircle, XCircle, AlertCircle, Sparkles } from 'lucide-react'; | |
| import { AnalysisData } from '../types/analysis'; | |
| import { Progress } from './ui/progress'; | |
| import { Badge } from './ui/badge'; | |
| import { StatisticsBar } from './StatisticsBar'; | |
| interface OverviewPanelProps { | |
| data: AnalysisData; | |
| } | |
| export function OverviewPanel({ data }: OverviewPanelProps) { | |
| const getSeverityBadgeClass = (severity: string) => { | |
| switch (severity) { | |
| case 'critical': | |
| return 'bg-red-500/10 text-red-400 border border-red-500/20'; | |
| case 'high': | |
| return 'bg-orange-500/10 text-orange-400 border border-orange-500/20'; | |
| case 'medium': | |
| return 'bg-amber-500/10 text-amber-400 border border-amber-500/20'; | |
| case 'low': | |
| return 'bg-indigo-500/10 text-indigo-400 border border-indigo-500/20'; | |
| default: | |
| return 'bg-slate-500/10 text-slate-400 border border-slate-500/20'; | |
| } | |
| }; | |
| const getRiskIcon = () => { | |
| switch (data.riskLevel) { | |
| case 'critical': | |
| return <XCircle className="w-10 h-10 text-rose-500" />; | |
| case 'high': | |
| return <AlertTriangle className="w-10 h-10 text-orange-500 animate-bounce" />; | |
| case 'medium': | |
| return <AlertCircle className="w-10 h-10 text-amber-500" />; | |
| default: | |
| return <CheckCircle className="w-10 h-10 text-emerald-500" />; | |
| } | |
| }; | |
| const getRiskColor = () => { | |
| switch (data.riskLevel) { | |
| case 'critical': | |
| return 'from-rose-500/10 via-rose-500/5 to-transparent border-rose-500/30'; | |
| case 'high': | |
| return 'from-orange-500/10 via-orange-500/5 to-transparent border-orange-500/30'; | |
| case 'medium': | |
| return 'from-amber-500/10 via-amber-500/5 to-transparent border-amber-500/30'; | |
| default: | |
| return 'from-emerald-500/10 via-emerald-500/5 to-transparent border-emerald-500/30'; | |
| } | |
| }; | |
| const severityCounts = data.darkPatterns.reduce((acc, pattern) => { | |
| acc[pattern.severity] = (acc[pattern.severity] || 0) + 1; | |
| return acc; | |
| }, {} as Record<string, number>); | |
| const avgConfidence = data.darkPatterns.length > 0 | |
| ? Math.round(data.darkPatterns.reduce((sum, p) => sum + p.confidence, 0) / data.darkPatterns.length) | |
| : 0; | |
| return ( | |
| <div className="space-y-6"> | |
| {/* Statistics Bar */} | |
| <StatisticsBar | |
| totalPatterns={data.darkPatterns.length} | |
| criticalCount={severityCounts['critical'] || 0} | |
| complianceScore={data.complianceReport.cfpbAlignment} | |
| avgConfidence={avgConfidence} | |
| /> | |
| {/* Overall Risk Score */} | |
| <div className={`p-6 rounded-2xl border bg-gradient-to-br ${getRiskColor()} relative overflow-hidden`}> | |
| <div className="absolute top-0 right-0 w-48 h-48 bg-indigo-500/5 rounded-full blur-3xl pointer-events-none" /> | |
| <div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-4"> | |
| <div className="flex items-center gap-4"> | |
| <div className="p-1 bg-slate-950/20 rounded-xl border border-white/5"> | |
| {getRiskIcon()} | |
| </div> | |
| <div> | |
| <h3 className="text-xl font-extrabold text-slate-100 flex items-center gap-2"> | |
| Platform Trust Score: {data.overallScore}/100 | |
| </h3> | |
| <p className="text-xs text-slate-400 mt-0.5"> | |
| Calculated Risk Rating:{' '} | |
| <span className="font-extrabold uppercase text-indigo-400"> | |
| {data.riskLevel} | |
| </span> | |
| </p> | |
| </div> | |
| </div> | |
| <div className="text-left sm:text-right bg-slate-950/20 px-4 py-2.5 rounded-xl border border-white/5"> | |
| <div className="text-2xl font-extrabold text-white leading-none"> | |
| {data.darkPatterns.length} | |
| </div> | |
| <div className="text-[10px] uppercase font-bold text-slate-400 tracking-wider mt-1"> | |
| Violations Found | |
| </div> | |
| </div> | |
| </div> | |
| <Progress value={data.overallScore} className="h-2.5 bg-slate-900 border border-white/5" /> | |
| </div> | |
| <div className="grid md:grid-cols-2 gap-6"> | |
| {/* Pattern Types Detected */} | |
| <div className="bg-slate-900/30 rounded-2xl p-6 border border-border"> | |
| <h4 className="font-bold text-sm text-slate-200 mb-4 flex items-center gap-2"> | |
| <Sparkles className="w-4 h-4 text-indigo-400" /> | |
| Detected Deceptive Categories | |
| </h4> | |
| {data.darkPatterns.length > 0 ? ( | |
| <div className="flex flex-wrap gap-2"> | |
| {Array.from(new Set(data.darkPatterns.map((p) => p.type))).map((type) => { | |
| const pattern = data.darkPatterns.find((p) => p.type === type); | |
| return ( | |
| <Badge | |
| key={type} | |
| variant="outline" | |
| className={`${getSeverityBadgeClass(pattern?.severity || 'low')} text-[10px] font-bold px-3 py-1 rounded-md`} | |
| > | |
| {type} | |
| </Badge> | |
| ); | |
| })} | |
| </div> | |
| ) : ( | |
| <p className="text-xs text-slate-500">No deceptive categories detected. Fully compliant!</p> | |
| )} | |
| </div> | |
| {/* Quick Summary */} | |
| <div className="bg-slate-900/30 rounded-2xl p-6 border border-border"> | |
| <h4 className="font-bold text-sm text-slate-200 mb-3">🤖 Explainable AI (XAI) Summary</h4> | |
| <p className="text-xs text-slate-400 leading-relaxed"> | |
| {data.darkPatterns.length > 0 ? ( | |
| <> | |
| This interface contains <strong>{data.darkPatterns.length} dark patterns</strong> flagged by the NLP vector classifiers. | |
| Common patterns include <strong>{Array.from(new Set(data.darkPatterns.map(p => p.type))).slice(0, 3).join(', ')}</strong>. | |
| The platform trust rating of <strong>{data.overallScore}/100</strong> indicates a{' '} | |
| <span className="text-indigo-400 font-semibold">{data.riskLevel} risk</span> of regulatory non-compliance with the Consumer Financial Protection Bureau (CFPB) guidelines. | |
| </> | |
| ) : ( | |
| <> | |
| This interface is clean! The NLP model scanned all textual and layout layers and did not detect any | |
| cognitive friction, forced continuity, hidden costs, or urgency tactics. The trust score of{' '} | |
| <strong>{data.overallScore}/100</strong> indicates alignment with CFPB consumer protection policies. | |
| </> | |
| )} | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| } |