busi488energy/src/app/_sections/prices-by-region.tsx
Joey Eamigh 79850a61be
cleanup
2026-02-11 22:03:19 -05:00

66 lines
2.3 KiB
TypeScript

import { Sparkline } from '@/components/charts/sparkline.js';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card.js';
import { BarChart3 } from 'lucide-react';
import { fetchLatestPrices, fetchPriceSparklines } from '@/actions/prices.js';
import { deserialize } from '@/lib/superjson.js';
export async function PricesByRegion() {
const [pricesResult, sparklinesResult] = await Promise.all([fetchLatestPrices(), fetchPriceSparklines()]);
const prices = pricesResult.ok
? deserialize<
Array<{
price_mwh: number;
region_code: string;
region_name: string;
}>
>(pricesResult.data)
: [];
const sparklines = sparklinesResult.ok
? deserialize<Array<{ region_code: string; points: { value: number }[] }>>(sparklinesResult.data)
: [];
const sparklineMap: Record<string, { value: number }[]> = {};
for (const s of sparklines) {
sparklineMap[s.region_code] = s.points;
}
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BarChart3 className="h-5 w-5 text-chart-2" />
Recent Prices by Region
</CardTitle>
</CardHeader>
<CardContent>
{prices.length > 0 ? (
<div className="max-h-100 space-y-3 overflow-y-auto pr-1">
{prices.map(p => {
const regionSparkline = sparklineMap[p.region_code];
return (
<div key={p.region_code} className="flex items-center gap-3 text-sm">
<span className="w-16 shrink-0 font-medium">{p.region_code}</span>
<div className="min-w-0 flex-1">
{regionSparkline && regionSparkline.length >= 2 && (
<Sparkline data={regionSparkline} color="hsl(210, 90%, 55%)" height={24} />
)}
</div>
<div className="flex shrink-0 items-baseline gap-1.5">
<span className="font-mono font-semibold">${p.price_mwh.toFixed(2)}</span>
<span className="text-xs text-muted-foreground">/MWh</span>
</div>
</div>
);
})}
</div>
) : (
<p className="text-sm text-muted-foreground">No price data available yet.</p>
)}
</CardContent>
</Card>
);
}