All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m56s
95 lines
3.0 KiB
TypeScript
95 lines
3.0 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
|
|
interface KPI_TableProps {
|
|
siteId: string;
|
|
month: string; // format: "YYYY-MM"
|
|
}
|
|
|
|
interface MonthlyKPI {
|
|
site: string;
|
|
month: string;
|
|
yield_kwh: number | null;
|
|
consumption_kwh: number | null;
|
|
grid_draw_kwh: number | null;
|
|
efficiency: number | null;
|
|
peak_demand_kw: number | null;
|
|
avg_power_factor: number | null;
|
|
load_factor: number | null;
|
|
}
|
|
|
|
const KPI_Table: React.FC<KPI_TableProps> = ({ siteId, month }) => {
|
|
const [kpiData, setKpiData] = useState<MonthlyKPI | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const API_URL = process.env.NEXT_PUBLIC_FASTAPI_URL;
|
|
|
|
useEffect(() => {
|
|
if (!siteId || !month) return;
|
|
|
|
const fetchKPI = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await fetch(
|
|
`${API_URL}/kpi/monthly?site=${siteId}&month=${month}`
|
|
);
|
|
setKpiData(await res.json());
|
|
} catch (err) {
|
|
console.error("Failed to fetch KPI:", err);
|
|
setKpiData(null);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchKPI();
|
|
}, [siteId, month]);
|
|
|
|
const formatValue = (value: number | null, unit = "", decimals = 2) =>
|
|
value != null ? `${value.toFixed(decimals)}${unit}` : "—";
|
|
|
|
const rows = [
|
|
{ label: "Monthly Yield", value: formatValue(kpiData?.yield_kwh ?? null, " kWh", 0) },
|
|
{ label: "Monthly Consumption", value: formatValue(kpiData?.consumption_kwh ?? null, " kWh", 0) },
|
|
{ label: "Monthly Grid Draw", value: formatValue(kpiData?.grid_draw_kwh ?? null, " kWh", 0) },
|
|
{ label: "Efficiency", value: formatValue(kpiData?.efficiency ?? null, "%", 1) },
|
|
{ label: "Peak Demand", value: formatValue(kpiData?.peak_demand_kw ?? null, " kW") },
|
|
{ label: "Power Factor", value: formatValue(kpiData?.avg_power_factor ?? null) },
|
|
{ label: "Load Factor", value: formatValue(kpiData?.load_factor ?? null) },
|
|
];
|
|
|
|
return (
|
|
<div>
|
|
<h2 className="text-lg font-bold mb-2 dark:text-white">Monthly KPI</h2>
|
|
<div className="min-h-[275px] border rounded">
|
|
{!siteId ? (
|
|
<p className="text-center py-10">No site selected</p>
|
|
) : loading ? (
|
|
<p className="text-center py-10">Loading...</p>
|
|
) : (
|
|
<table className="w-full border-collapse">
|
|
<thead>
|
|
<tr className="bg-gray-100 dark:bg-rtgray-800">
|
|
<th className="border p-3 text-left dark:text-white">KPI</th>
|
|
<th className="border p-3 text-left dark:text-white">Value</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{rows.map((row) => (
|
|
<tr key={row.label} className="even:bg-gray-50 dark:even:bg-rtgray-800">
|
|
<td className="border p-2.5 dark:text-white">{row.label}</td>
|
|
<td className="border p-2.5 dark:text-white">{row.value}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default KPI_Table;
|
|
|
|
|
|
|