busi488energy/src/app/_sections/stress-gauges.tsx
2026-02-11 21:35:03 -05:00

101 lines
3.1 KiB
TypeScript

import { GridStressGauge } from '@/components/dashboard/grid-stress-gauge.js';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card.js';
import { Radio } from 'lucide-react';
import { fetchRegionDemandSummary } from '@/actions/demand.js';
import { deserialize } from '@/lib/superjson.js';
interface RegionStatus {
regionCode: string;
regionName: string;
latestDemandMw: number;
peakDemandMw: number;
}
export async function StressGauges() {
const demandResult = await fetchRegionDemandSummary();
const demandRows = demandResult.ok
? deserialize<
Array<{
avg_demand: number | null;
peak_demand: number | null;
region_code: string;
region_name: string;
day: Date;
}>
>(demandResult.data)
: [];
// For each region: use the most recent day's avg_demand as "current",
// and the 7-day peak_demand as the ceiling.
const regionMap = new Map<string, RegionStatus>();
for (const row of demandRows) {
const existing = regionMap.get(row.region_code);
const demand = row.avg_demand ?? 0;
const peak = row.peak_demand ?? 0;
if (!existing) {
regionMap.set(row.region_code, {
regionCode: row.region_code,
regionName: row.region_name,
latestDemandMw: demand,
peakDemandMw: peak,
});
} else {
// The query is ordered by day ASC, so later rows overwrite latestDemand
existing.latestDemandMw = demand;
if (peak > existing.peakDemandMw) existing.peakDemandMw = peak;
}
}
const regions = [...regionMap.values()]
.filter(r => r.peakDemandMw > 0)
.sort((a, b) => b.latestDemandMw - a.latestDemandMw);
if (regions.length === 0) return null;
// Split into two columns for wider screens
const midpoint = Math.ceil(regions.length / 2);
const leftColumn = regions.slice(0, midpoint);
const rightColumn = regions.slice(midpoint);
return (
<Card>
<CardHeader className="pb-3">
<CardTitle className="flex items-center gap-2">
<Radio className="h-5 w-5 text-chart-4" />
Region Grid Status
</CardTitle>
<p className="text-xs text-muted-foreground">Current demand vs. 7-day peak by region</p>
</CardHeader>
<CardContent>
<div className="grid gap-x-8 gap-y-2.5 md:grid-cols-2">
<div className="flex flex-col gap-2.5">
{leftColumn.map(r => (
<GridStressGauge
key={r.regionCode}
regionCode={r.regionCode}
regionName={r.regionName}
demandMw={r.latestDemandMw}
peakDemandMw={r.peakDemandMw}
/>
))}
</div>
<div className="flex flex-col gap-2.5">
{rightColumn.map(r => (
<GridStressGauge
key={r.regionCode}
regionCode={r.regionCode}
regionName={r.regionName}
demandMw={r.latestDemandMw}
peakDemandMw={r.peakDemandMw}
/>
))}
</div>
</div>
</CardContent>
</Card>
);
}