import { useCallback, useEffect, useState } from 'react' import { CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from 'recharts' import { getJson } from '../api/postgrest' import { instantPragueDay, pragueCalendarDay } from '../lib/pragueDate' import type { SiteEffectivePriceRow } from '../types/ems' function parseNum(v: string | number | null | undefined): number | null { if (v == null) return null if (typeof v === 'number' && !Number.isNaN(v)) return v const n = Number(v) return Number.isFinite(n) ? n : null } export type PricePoint = { label: string buy: number | null sell: number | null } type Props = { siteId: number | null pollMs?: number } /** Efektivní nákup / prodej (Kč/kWh) pro dnešní den v Europe/Prague. */ export function PriceChart({ siteId, pollMs = 120_000 }: Props) { const [points, setPoints] = useState([]) const [ready, setReady] = useState(false) const load = useCallback(async () => { if (siteId == null) { setPoints([]) setReady(true) return } try { const rows = await getJson('/vw_site_effective_price', { site_id: `eq.${siteId}`, order: 'interval_start.desc', limit: '200', }) const today = pragueCalendarDay() const todayRows = Array.isArray(rows) ? rows.filter((r) => instantPragueDay(r.interval_start) === today) : [] todayRows.sort((a, b) => new Date(a.interval_start).getTime() - new Date(b.interval_start).getTime()) const mapped: PricePoint[] = todayRows.map((r) => { const t = new Date(r.interval_start) return { label: t.toLocaleTimeString('cs-CZ', { hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Prague', }), buy: parseNum(r.effective_buy_price_czk_kwh), sell: parseNum(r.effective_sell_price_czk_kwh), } }) setPoints(mapped) } catch { setPoints([]) } finally { setReady(true) } }, [siteId]) useEffect(() => { void load() const id = window.setInterval(() => void load(), pollMs) return () => window.clearInterval(id) }, [load, pollMs]) if (!ready || points.length === 0) { return (
) } return (
) }