File size: 3,504 Bytes
b87cbc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import {
  AreaChart,
  Area,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
} from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "@labas/ui/components/card";

interface TrendPoint {
  date: string;
  attempts: number;
  avgScorePct: number;
}

interface ScoreTrendChartProps {
  data: TrendPoint[] | undefined;
}

function formatDateLabel(dateStr: string) {
  const d = new Date(dateStr);
  return `${d.getDate()}/${d.getMonth() + 1}`;
}

export function ScoreTrendChart({ data }: ScoreTrendChartProps) {
  if (!data || data.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)]">
            Tren Skor
          </CardTitle>
        </CardHeader>
        <CardContent className="h-64 flex items-center justify-center text-[var(--warm-charcoal)]">
          Belum ada data tren.
        </CardContent>
      </Card>
    );
  }

  const chartData = data.map((d) => ({
    ...d,
    label: formatDateLabel(d.date),
  }));

  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)]">
          Tren Skor (30 Hari)
        </CardTitle>
      </CardHeader>
      <CardContent>
        <ResponsiveContainer width="100%" height={256}>
          <AreaChart data={chartData} margin={{ top: 5, right: 10, left: -10, bottom: 0 }}>
            <defs>
              <linearGradient id="scoreGradient" x1="0" y1="0" x2="0" y2="1">
                <stop offset="5%" stopColor="var(--matcha-600)" stopOpacity={0.2} />
                <stop offset="95%" stopColor="var(--matcha-600)" stopOpacity={0} />
              </linearGradient>
            </defs>
            <CartesianGrid strokeDasharray="3 3" stroke="var(--oat-border)" />
            <XAxis
              dataKey="label"
              tick={{ fontSize: 12, fill: "var(--warm-charcoal)" }}
              axisLine={{ stroke: "var(--oat-border)" }}
              tickLine={false}
            />
            <YAxis
              tick={{ fontSize: 12, fill: "var(--warm-charcoal)" }}
              axisLine={false}
              tickLine={false}
              domain={[0, 100]}
              unit="%"
            />
            <Tooltip
              contentStyle={{
                backgroundColor: "var(--pure-white)",
                border: "2px solid var(--oat-border)",
                borderRadius: "var(--radius-lg)",
                fontSize: 13,
              }}
              formatter={(value: unknown, name: unknown, _item: unknown, _index: unknown, _payload: unknown) => {
                const num = typeof value === "number" ? value : 0;
                const n = typeof name === "string" ? name : "";
                if (n === "avgScorePct") return [`${num}%`, "Rata-rata Skor"];
                if (n === "attempts") return [num, "Latihan"];
                return [num, n];
              }}
            />
            <Area
              type="monotone"
              dataKey="avgScorePct"
              stroke="var(--matcha-600)"
              strokeWidth={2}
              fill="url(#scoreGradient)"
            />
          </AreaChart>
        </ResponsiveContainer>
      </CardContent>
    </Card>
  );
}