58 lines
2.5 KiB
TypeScript
58 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
import type { PowerBucket } from "@/lib/api";
|
|
|
|
interface Props {
|
|
data: PowerBucket[];
|
|
loading?: boolean;
|
|
}
|
|
|
|
function formatTime(iso: string) {
|
|
return new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
}
|
|
|
|
export function PowerTrendChart({ data, loading }: Props) {
|
|
const chartData = data.map((d) => ({ time: formatTime(d.bucket), power: d.total_kw }));
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader className="pb-2">
|
|
<div className="flex items-center justify-between">
|
|
<CardTitle className="text-sm font-semibold">Total Power (kW)</CardTitle>
|
|
<span className="text-xs text-muted-foreground">Last 60 minutes</span>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{loading ? (
|
|
<Skeleton className="h-64 w-full" />
|
|
) : chartData.length === 0 ? (
|
|
<div className="h-[200px] flex items-center justify-center text-sm text-muted-foreground">
|
|
Waiting for data...
|
|
</div>
|
|
) : (
|
|
<ResponsiveContainer width="100%" height={200}>
|
|
<AreaChart data={chartData} margin={{ top: 4, right: 4, left: -20, bottom: 0 }}>
|
|
<defs>
|
|
<linearGradient id="powerGradient" x1="0" y1="0" x2="0" y2="1">
|
|
<stop offset="5%" stopColor="oklch(0.62 0.17 212)" stopOpacity={0.3} />
|
|
<stop offset="95%" stopColor="oklch(0.62 0.17 212)" stopOpacity={0} />
|
|
</linearGradient>
|
|
</defs>
|
|
<CartesianGrid strokeDasharray="3 3" stroke="oklch(1 0 0 / 8%)" />
|
|
<XAxis dataKey="time" tick={{ fontSize: 10, fill: "oklch(0.65 0.04 257)" }} tickLine={false} axisLine={false} />
|
|
<YAxis tick={{ fontSize: 10, fill: "oklch(0.65 0.04 257)" }} tickLine={false} axisLine={false} />
|
|
<Tooltip
|
|
contentStyle={{ backgroundColor: "oklch(0.16 0.04 265)", border: "1px solid oklch(1 0 0 / 9%)", borderRadius: "6px", fontSize: "12px" }}
|
|
formatter={(value) => [`${value} kW`, "Power"]}
|
|
/>
|
|
<Area type="monotone" dataKey="power" stroke="oklch(0.62 0.17 212)" strokeWidth={2} fill="url(#powerGradient)" dot={false} activeDot={{ r: 4 }} />
|
|
</AreaChart>
|
|
</ResponsiveContainer>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|