import { useEffect, useState } from "react"; import { LineChart, Line, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, BarChart, Bar, CartesianGrid, } from "recharts"; import { fetchDashboard, DashboardData } from "../api"; export default function Dashboard() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetchDashboard() .then(setData) .catch((e) => setError(e.message)) .finally(() => setLoading(false)); }, []); if (loading) return (
); if (error) return (
Error loading dashboard: {error}
); if (!data) return null; // Prepare capacity fade chart data (first 6 batteries) const fadeEntries = Object.entries(data.capacity_fade).slice(0, 6); const maxLen = Math.max(...fadeEntries.map(([, v]) => v.length)); const fadeData = Array.from({ length: maxLen }, (_, i) => { const row: Record = { cycle: i + 1 }; fadeEntries.forEach(([bid, caps]) => { if (i < caps.length) row[bid] = +(caps[i] / 2 * 100).toFixed(1); }); return row; }); // Model metrics const metricsList = Object.entries(data.model_metrics) .map(([name, m]) => ({ name, r2: m.R2 ?? m.r2 ?? 0, mae: m.MAE ?? m.mae ?? 0 })) .sort((a, b) => b.r2 - a.r2) .slice(0, 10); const COLORS = ["#22c55e", "#3b82f6", "#f59e0b", "#ef4444", "#8b5cf6", "#06b6d4"]; return (
{/* Stats Cards */}
{/* Battery Grid */}

Battery Fleet Overview

{data.batteries.map((b) => (
{b.battery_id}
{b.soh_pct}%
{b.degradation_state}
))}
{/* Capacity Fade Chart */}

SOH Capacity Fade

{fadeEntries.map(([bid], i) => ( ))}
{/* Model Comparison */}

Model R² Comparison

); } function StatCard({ label, value }: { label: string; value: string | number }) { return (
{label}
{value}
); }