100 lines
2.8 KiB
TypeScript
100 lines
2.8 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;
|
|
}
|
|
|
|
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 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)}%` },
|
|
];
|
|
|
|
return (
|
|
<div>
|
|
<h2 className="text-lg font-bold mb-2">Monthly KPI</h2>
|
|
<table className="min-h-[275px] w-full border-collapse border border-gray-700 text-black bg-white">
|
|
<thead>
|
|
<tr className="bg-gray-800 text-black">
|
|
<th className="border border-gray-700 p-3 text-left">KPI</th>
|
|
<th className="border border-gray-700 p-3 text-left">Value</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{data.map((row) => (
|
|
<tr key={row.kpi}>
|
|
<td className="border border-gray-700 p-3">{row.kpi}</td>
|
|
<td className="border border-gray-700 p-3">{row.value}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default KPI_Table;
|
|
|
|
|