2025-08-07 16:46:11 +08:00

109 lines
3.6 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; // ✅ new
avg_power_factor: number | null; // ✅ new
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);
useEffect(() => {
const fetchKPI = async () => {
setLoading(true);
try {
const res = await fetch(`http://localhost:8000/kpi/monthly?site=${siteId}&month=${month}`);
const data = await res.json();
setKpiData(data);
} catch (err) {
console.error('Failed to fetch KPI:', err);
setKpiData(null); // fallback
} finally {
setLoading(false);
}
};
if (siteId && month) fetchKPI();
}, [siteId, month]);
if (!siteId) {
return (
<div>
<h2 className="text-lg font-bold mb-2">Monthly KPI</h2>
<div className="min-h-[275px] w-full flex items-center justify-center border">
<p>No site selected</p>
</div>
</div>
);
}
if (loading) {
return (
<div>
<h2 className="text-lg font-bold mb-2">Monthly KPI</h2>
<div className="min-h-[275px] w-full flex items-center justify-center border">
<p>Loading...</p>
</div>
</div>
);
}
// Use optional chaining and nullish coalescing to safely default values to 0
const yield_kwh = kpiData?.yield_kwh ?? 0;
const consumption_kwh = kpiData?.consumption_kwh ?? 0;
const grid_draw_kwh = kpiData?.grid_draw_kwh ?? 0;
const efficiency = kpiData?.efficiency ?? 0;
const peak_demand_kw = kpiData?.peak_demand_kw ?? 0;
const power_factor = kpiData?.avg_power_factor ?? 0;
const load_factor = kpiData?.load_factor ?? 0;
const data = [
{ kpi: 'Monthly Yield', value: `${yield_kwh.toFixed(0)} kWh` },
{ kpi: 'Monthly Consumption', value: `${consumption_kwh.toFixed(0)} kWh` },
{ kpi: 'Monthly Grid Draw', value: `${grid_draw_kwh.toFixed(0)} kWh` },
{ kpi: 'Efficiency', value: `${efficiency.toFixed(1)}%` },
{ kpi: 'Peak Demand', value: `${peak_demand_kw.toFixed(2)} kW` }, // ✅ added
{ kpi: 'Power Factor', value: `${power_factor.toFixed(2)} kW` }, // ✅ added
{ kpi: 'Load Factor', value: `${load_factor.toFixed(2)} kW` }, // ✅ added
];
return (
<div>
<h2 className="text-lg font-bold mb-2 dark:text-white">Monthly KPI</h2>
<table className="min-h-[275px] w-full border-collapse border border-gray-300 dark:border-rtgray-700 text-black dark:text-white bg-white dark:bg-rtgray-700">
<thead>
<tr className="bg-rtgray-100 dark:bg-rtgray-800 text-black dark:text-white">
<th className="border border-rtgray-300 dark:border-rtgray-700 p-3 text-left dark:bg-rtgray-900">KPI</th>
<th className="border border-rtgray-300 dark:border-rtgray-700 p-3 text-left dark:bg-rtgray-900">Value</th>
</tr>
</thead>
<tbody>
{data.map((row) => (
<tr key={row.kpi} className="even:bg-rtgray-50 dark:even:bg-rtgray-800">
<td className="border border-rtgray-300 dark:border-rtgray-700 p-2.5">{row.kpi}</td>
<td className="border border-rtgray-300 dark:border-rtgray-700 p-2.5">{row.value}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default KPI_Table;