File size: 6,735 Bytes
743409d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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>
  );
}