first commit

This commit is contained in:
mega 2026-03-19 11:32:17 +00:00
commit 4b98219bf7
144 changed files with 31561 additions and 0 deletions

View file

@ -0,0 +1,58 @@
"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>
);
}