SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
2 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%

Web: no function props from server pages into client charts (prerender fix)

Simon-Pierre Boucher committed 21 days ago (Sep 11, 2026) parent 9a137b9

3 changed files +6 −5

modified apps/web/src/app/(site)/(home)/page.tsx +2 −3
@@ -95,8 +95,8 @@ export default async function HomePage() {
95 95 href: r.href || routes.market(r.slug),
96 96 coverage: r.coverage,
97 97 secondary: r.coverage !== undefined && r.coverage !== null ? `${fmtPct(r.coverage)} MW coverage` : undefined,
98 + display: fmtMw(r.value),
98 99 }))}
99 − format={(v) => fmtMw(v)}
100 100 />
101 101 ) : (
102 102 <EmptyState compact title="Rankings not computed yet" />
@@ -106,8 +106,7 @@ export default async function HomePage() {
106 106 <Section title="Largest operators" description="By facility count and known MW." aside={<MoreLink href={routes.rankings("operators")} />}>
107 107 {d?.topOperators?.length ? (
108 108 <BarList
109 − items={d.topOperators.slice(0, 10).map((r) => ({ rank: r.rank, label: r.name, value: r.value, href: r.href || routes.operator(r.slug), secondary: r.secondary !== undefined && r.secondary !== null ? fmtMw(r.secondary) : undefined }))}
110 − format={(v) => fmtInt(v)}
109 + items={d.topOperators.slice(0, 10).map((r) => ({ rank: r.rank, label: r.name, value: r.value, href: r.href || routes.operator(r.slug), secondary: r.secondary !== undefined && r.secondary !== null ? fmtMw(r.secondary) : undefined, display: fmtInt(r.value) }))}
111 110 />
112 111 ) : (
113 112 <EmptyState compact title="Rankings not computed yet" />
modified apps/web/src/app/(site)/rankings/(index)/page.tsx +1 −1
@@ -60,7 +60,7 @@ function RankingCard({ r }: { r: Ranking }) {
60 60 </div>
61 61 {top.length > 0 && (
62 62 <div className="min-w-0">
63 − <BarList items={top.map((row) => ({ label: row.name, value: row.value, href: rowHref(row, r.scope), rank: row.rank, coverage: row.coverage }))} format={(v) => fmtRankValue(v, r.unit)} showRank />
63 + <BarList items={top.map((row) => ({ label: row.name, value: row.value, href: rowHref(row, r.scope), rank: row.rank, coverage: row.coverage, display: fmtRankValue(row.value, r.unit) }))} showRank />
64 64 </div>
65 65 )}
66 66 </div>
modified apps/web/src/components/ui/charts.tsx +3 −1
@@ -69,6 +69,8 @@ export interface BarListItem {
69 69 /** 0..1 coverage → hatch hint when low */
70 70 coverage?: number | null;
71 71 rank?: number;
72 + /** preformatted value (lets server components avoid passing formatter functions) */
73 + display?: string;
72 74 }
73 75
74 76 /** Horizontal ranked bars (rankings module). Value formatted by `format`. */
@@ -90,7 +92,7 @@ export function BarList({ items, format = fmtCompact, max, className, showRank =
90 92 <div className="h-full" style={{ width: `${pct}%`, background: barColor, opacity: it.coverage !== undefined && it.coverage !== null && it.coverage < 0.5 ? 0.55 : 1 }} />
91 93 </div>
92 94 </div>
93 − <span className="figure w-[64px] text-right text-[12.5px] text-ink-2">{format(it.value)}</span>
95 + <span className="figure w-[64px] text-right text-[12.5px] text-ink-2">{it.display ?? format(it.value)}</span>
94 96 </div>
95 97 );
96 98 return (
97 99