import React, { useEffect, useMemo, useState } from 'react'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Legend, } from 'recharts'; import { format } from 'date-fns'; import { fetchMonthlyKpi, type MonthlyKPI } from '@/app/utils/api'; interface MonthlyBarChartProps { siteId: string; } const getLastNMonthKeys = (n: number): string[] => { const out: string[] = []; const now = new Date(); // include current month, go back n-1 months for (let i = 0; i < n; i++) { const d = new Date(now.getFullYear(), now.getMonth() - (n - 1 - i), 1); const key = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`; // YYYY-MM out.push(key); } return out; }; function useIsDarkMode() { const [isDark, setIsDark] = useState(() => typeof document !== 'undefined' ? document.body.classList.contains('dark') : false ); useEffect(() => { const check = () => setIsDark(document.body.classList.contains('dark')); check(); const observer = new MutationObserver(check); observer.observe(document.body, { attributes: true, attributeFilter: ['class'] }); return () => observer.disconnect(); }, []); return isDark; } const MonthlyBarChart: React.FC = ({ siteId }) => { const [chartData, setChartData] = useState< { month: string; consumption: number; generation: number }[] >([]); const [loading, setLoading] = useState(true); const isDark = useIsDarkMode(); const consumptionColor = isDark ? '#ba8e23' : '#003049'; const generationColor = isDark ? '#fcd913' : '#669bbc'; const monthKeys = useMemo(() => getLastNMonthKeys(6), []); useEffect(() => { if (!siteId) return; const load = async () => { setLoading(true); try { // Fetch all 6 months in parallel const results: MonthlyKPI[] = await Promise.all( monthKeys.map((month) => fetchMonthlyKpi({ site: siteId, month, // consumption_topic: '...', // optional if your API needs it // generation_topic: '...', // optional if your API needs it }).catch((e) => { // normalize failures to an error-shaped record so the chart can still render other months return { site: siteId, month, yield_kwh: null, consumption_kwh: null, grid_draw_kwh: null, efficiency: null, peak_demand_kw: null, avg_power_factor: null, load_factor: null, error: String(e), } as MonthlyKPI; }) ) ); // Map to chart rows; default nulls to 0 for stacking/tooltip friendliness const rows = results.map((kpi) => { const monthLabel = format(new Date(`${kpi.month}-01`), 'MMM'); return { month: monthLabel, consumption: kpi.consumption_kwh ?? 0, generation: kpi.yield_kwh ?? 0, }; }); setChartData(rows); } finally { setLoading(false); } }; load(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [siteId]); // monthKeys are stable via useMemo if (loading || !siteId || chartData.length === 0) { return (

{loading ? 'Loading data...' : 'No data available for chart.'}

); } return (
[`${value.toFixed(2)} kWh`]} labelFormatter={(label) => `${label}`} contentStyle={{ background: isDark ? '#232b3e' : '#fff', color: isDark ? '#fff' : '#222', border: isDark ? '1px solid #444' : '1px solid #ccc', }} labelStyle={{ color: isDark ? '#fff' : '#222', }} cursor={{ fill: isDark ? '#808080' : '#e0e7ef', fillOpacity: isDark ? 0.6 : 0.3, }} />
); }; export default MonthlyBarChart;