Download apps/web/src/components/analytics/WeaknessPanel.tsx from Atmint/cpns: direct link, hf CLI and curl.
- Browser
- Download file 4.28 kB
-
https://huggingface.co/spaces/Atmint/cpns/resolve/main/apps/web/src/components/analytics/WeaknessPanel.tsx
- Command line
-
hf download hf://spaces/Atmint/cpns/apps/web/src/components/analytics/WeaknessPanel.tsx
-
curl -L -o WeaknessPanel.tsx https://huggingface.co/spaces/Atmint/cpns/resolve/main/apps/web/src/components/analytics/WeaknessPanel.tsx
4.28 kB
| import { Card, CardContent, CardHeader, CardTitle } from "@pram/ui/components/card"; | |
| import { MaterialIcon } from "@/components/ui/MaterialIcon"; | |
| import { formatLabel } from "@/lib/format"; | |
| interface Weakness { | |
| type: "format" | "section" | "skill"; | |
| name: string; | |
| totalQuestions: number; | |
| accuracyPct: number; | |
| } | |
| interface WeaknessPanelProps { | |
| weaknesses: Weakness[] | undefined; | |
| recommendations: string[] | undefined; | |
| } | |
| function getTypeIcon(type: Weakness["type"]) { | |
| switch (type) { | |
| case "format": | |
| return "quiz"; | |
| case "section": | |
| return "folder"; | |
| case "skill": | |
| return "psychology"; | |
| } | |
| } | |
| function getTypeLabel(type: Weakness["type"]) { | |
| switch (type) { | |
| case "format": | |
| return "Format"; | |
| case "section": | |
| return "Section"; | |
| case "skill": | |
| return "Skill"; | |
| } | |
| } | |
| function getSeverityColor(pct: number) { | |
| if (pct < 40) return "text-[var(--pomegranate-600)]"; | |
| if (pct < 60) return "text-[var(--lemon-700)]"; | |
| return "text-[var(--matcha-600)]"; | |
| } | |
| export function WeaknessPanel({ weaknesses, recommendations }: WeaknessPanelProps) { | |
| const hasData = weaknesses && weaknesses.length > 0; | |
| return ( | |
| <Card className="clay-shadow bg-[var(--pure-white)] border-2 border-[var(--oat-border)] rounded-[var(--radius-xl)]"> | |
| <CardHeader> | |
| <CardTitle className="text-lg font-headline font-bold text-[var(--clay-black)] flex items-center gap-2"> | |
| <MaterialIcon name="analytics" className="text-[var(--pomegranate-600)]" /> | |
| Area untuk Ditingkatkan | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| {hasData ? ( | |
| <> | |
| <div className="space-y-3"> | |
| {weaknesses.map((w, _i) => ( | |
| <div | |
| key={`${w.type}-${w.name}`} | |
| className="flex items-center gap-4 p-3 rounded-[var(--radius-md)] bg-[var(--warm-cream)] border-2 border-[var(--oat-border)]" | |
| > | |
| <div className="flex items-center justify-center w-10 h-10 rounded-[var(--radius-lg)] bg-[var(--oat-light)] shrink-0"> | |
| <MaterialIcon name={getTypeIcon(w.type)} className="text-[var(--warm-charcoal)]" /> | |
| </div> | |
| <div className="flex-1 min-w-0"> | |
| <div className="flex items-center gap-2"> | |
| <span className="text-xs font-medium text-[var(--warm-silver)] uppercase tracking-wide"> | |
| {getTypeLabel(w.type)} | |
| </span> | |
| </div> | |
| <div className="text-sm font-semibold text-[var(--clay-black)] truncate"> | |
| {formatLabel(w.name)} | |
| </div> | |
| </div> | |
| <div className="text-right shrink-0"> | |
| <div className={`text-xl font-headline font-extrabold ${getSeverityColor(w.accuracyPct)}`}> | |
| {w.accuracyPct}% | |
| </div> | |
| <div className="text-xs text-[var(--warm-silver)]">{w.totalQuestions} soal</div> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| {recommendations && recommendations.length > 0 && ( | |
| <div className="space-y-2"> | |
| <h4 className="text-sm font-semibold text-[var(--clay-black)]">Rekomendasi</h4> | |
| <ul className="space-y-2"> | |
| {recommendations.map((rec, i) => ( | |
| <li key={i} className="flex items-start gap-2 text-sm text-[var(--warm-charcoal)]"> | |
| <MaterialIcon name="lightbulb" className="text-[var(--lemon-700)] shrink-0 mt-0.5" /> | |
| <span>{rec}</span> | |
| </li> | |
| ))} | |
| </ul> | |
| </div> | |
| )} | |
| </> | |
| ) : ( | |
| <div className="text-center py-8 text-[var(--warm-charcoal)]"> | |
| <MaterialIcon name="insights" className="text-5xl text-[var(--warm-silver)] mx-auto mb-3" /> | |
| <p className="font-semibold">Belum cukup data</p> | |
| <p className="text-sm mt-1">Selesaikan lebih banyak latihan untuk melihat analisis kelemahan.</p> | |
| </div> | |
| )} | |
| </CardContent> | |
| </Card> | |
| ); | |
| } | |