"use client"; import { useEffect, useState, useCallback } from "react"; import { Sheet, SheetContent, SheetHeader, SheetTitle, } from "@/components/ui/sheet"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip as RechartTooltip, ResponsiveContainer, ReferenceLine, } from "recharts"; import { Battery, Zap, Activity, AlertTriangle, CheckCircle2, TrendingDown } from "lucide-react"; import { cn } from "@/lib/utils"; import { fetchUpsHistory, type UpsAsset, type UpsHistoryPoint } from "@/lib/api"; const SITE_ID = "sg-01"; function fmt(iso: string) { return new Date(iso).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); } function StatRow({ label, value, color }: { label: string; value: string; color?: string }) { return (
{label} {value}
); } function GaugeBar({ label, value, max, unit, warnAt, critAt, reverse = false, }: { label: string; value: number | null; max: number; unit: string; warnAt?: number; critAt?: number; reverse?: boolean; }) { const v = value ?? 0; const pct = Math.min(100, (v / max) * 100); const isWarn = warnAt !== undefined && (reverse ? v < warnAt : v >= warnAt); const isCrit = critAt !== undefined && (reverse ? v < critAt : v >= critAt); const barColor = isCrit ? "bg-destructive" : isWarn ? "bg-amber-500" : "bg-green-500"; const textColor = isCrit ? "text-destructive" : isWarn ? "text-amber-400" : ""; return (
{label} {value !== null ? `${value}${unit}` : "—"}
); } function MiniChart({ data, dataKey, color, refLines = [], unit, domain, }: { data: UpsHistoryPoint[]; dataKey: keyof UpsHistoryPoint; color: string; refLines?: { y: number; color: string; label: string }[]; unit?: string; domain?: [number, number]; }) { if (data.length === 0) { return (
Waiting for data...
); } return ( [`${v}${unit ?? ""}`, String(dataKey)]} labelFormatter={(l) => fmt(String(l))} /> {refLines.map((r) => ( ))} ); } // ── Overview Tab ────────────────────────────────────────────────────────────── function OverviewTab({ ups }: { ups: UpsAsset }) { const onBattery = ups.state === "battery"; const overload = ups.state === "overload"; const charge = ups.charge_pct ?? 0; const runtime = ups.runtime_min ?? null; const load = ups.load_pct ?? null; return (
{/* State hero */}

{overload ? "Overloaded" : onBattery ? "On Battery" : "Mains Power"}

{overload ? "Critical — load exceeds safe capacity" : onBattery ? "Mains power lost — running on battery" : "Grid power normal — charging battery"}

{/* Gauges */}
{/* Runtime + voltage row */}

Est. Runtime

{runtime !== null ? `${Math.round(runtime)}` : "—"}

minutes

Input Voltage

250) ? "text-amber-400" : "", )}> {ups.voltage_v !== null ? `${ups.voltage_v}` : "—"}

V AC

{/* Quick stats */}
= 95 ? "text-destructive" : load !== null && load >= 85 ? "text-amber-400" : ""} /> 250) ? "text-amber-400" : ""} />
); } // ── Battery Tab ─────────────────────────────────────────────────────────────── function BatteryTab({ history }: { history: UpsHistoryPoint[] }) { const charge = history.map((d) => ({ ...d, bucket: d.bucket })); const runtime = history.map((d) => ({ ...d, bucket: d.bucket })); return (

Battery Charge (%)

Estimated Runtime (min)

); } // ── Load Tab ────────────────────────────────────────────────────────────────── function LoadTab({ history }: { history: UpsHistoryPoint[] }) { return (

Load (%)

Input Voltage (V)

); } // ── Sheet ───────────────────────────────────────────────────────────────────── interface Props { ups: UpsAsset | null; onClose: () => void; } export function UpsDetailSheet({ ups, onClose }: Props) { const [history, setHistory] = useState([]); const [hours, setHours] = useState(6); const loadHistory = useCallback(async () => { if (!ups) return; try { const h = await fetchUpsHistory(SITE_ID, ups.ups_id, hours); setHistory(h); } catch { /* keep stale */ } }, [ups, hours]); useEffect(() => { if (ups) loadHistory(); }, [ups, loadHistory]); if (!ups) return null; const overload = ups.state === "overload"; const onBattery = ups.state === "battery"; return ( { if (!open) onClose(); }}>
{ups.ups_id.toUpperCase()} {overload || onBattery ? : } {overload ? "Overloaded" : onBattery ? "On Battery" : "Mains"}
Overview Battery Load & Voltage
); }