cpns / apps /web /src /components /analytics /ScoreTrendChart.tsx
pramudya-yb
Rename project from Labas to Pram
2b62b0c
Raw
History Blame Contribute Delete
3.5 kB
import {
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from "recharts";
import { Card, CardContent, CardHeader, CardTitle } from "@pram/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>
);
}