Syasya fce26a2bc4
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m56s
amend api endpoints
2025-08-26 15:10:14 +08:00

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;