fix(reports): chart series all rendered one colour (RSC boundary bug)
The comparison charts (and detail-page breakdown swatches) rendered every
series in recharts' default colour instead of the per-item palette.
Root cause: `SERIES_COLORS` was defined in `components/reports/charts.tsx`,
which is a "use client" module. The report **pages are server components** and
imported the palette from it. A plain value imported from a client module into
a server component is a client-reference proxy, not the real array — so
`SERIES_COLORS[i % SERIES_COLORS.length]` was `SERIES_COLORS[NaN]` → undefined,
every line got `stroke={undefined}`, and recharts fell back to #3182bd. (The
literal `strokeWidth={2}` still applied, which is why only the colour was wrong.
It passed jsdom tests because those import the array directly, not across the
RSC boundary.)
Fix: move the palette to a dependency-free shared module `lib/report-colors.ts`
(no "use client", no server-only imports) that resolves to the real array in
both server and client graphs. `charts.tsx` and all four report pages import it
from there. It can't live in `lib/reports.ts` (that imports Prisma `db`, which
must not enter the client bundle).
Verified in a real browser: line strokes now cycle the 10-colour palette
(#2563eb, #16a34a, …) instead of a uniform #3182bd.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cf69292be3
commit
34143b5e75
6 changed files with 33 additions and 5 deletions
|
|
@ -19,7 +19,8 @@ import {
|
|||
WEEK_LABELS,
|
||||
} from "@/lib/reports";
|
||||
import { ReportsToolbar } from "@/components/reports/reports-toolbar";
|
||||
import { TrendChart, BreakdownChart, SERIES_COLORS } from "@/components/reports/charts";
|
||||
import { TrendChart, BreakdownChart } from "@/components/reports/charts";
|
||||
import { SERIES_COLORS } from "@/lib/report-colors";
|
||||
import { Kpi, KpiStrip } from "@/components/reports/kpi";
|
||||
import { ReportBreadcrumb, ReportTitle, SegLink } from "@/components/reports/report-header";
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ import {
|
|||
type NodeSpend,
|
||||
} from "@/lib/reports";
|
||||
import { ReportsToolbar } from "@/components/reports/reports-toolbar";
|
||||
import { ComparisonChart, Sparkline, SERIES_COLORS, type Series } from "@/components/reports/charts";
|
||||
import { ComparisonChart, Sparkline, type Series } from "@/components/reports/charts";
|
||||
import { SERIES_COLORS } from "@/lib/report-colors";
|
||||
import { Kpi, KpiStrip } from "@/components/reports/kpi";
|
||||
import { ReportBreadcrumb, ReportTitle, SelectCheckbox, CompareBar } from "@/components/reports/report-header";
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ import {
|
|||
type Tier,
|
||||
} from "@/lib/reports";
|
||||
import { ReportsToolbar } from "@/components/reports/reports-toolbar";
|
||||
import { TrendChart, BreakdownChart, SERIES_COLORS } from "@/components/reports/charts";
|
||||
import { TrendChart, BreakdownChart } from "@/components/reports/charts";
|
||||
import { SERIES_COLORS } from "@/lib/report-colors";
|
||||
import { Kpi, KpiStrip } from "@/components/reports/kpi";
|
||||
import { ReportBreadcrumb, ReportTitle, SegLink } from "@/components/reports/report-header";
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import {
|
|||
type CostCentreSpend,
|
||||
} from "@/lib/reports";
|
||||
import { ReportsToolbar } from "@/components/reports/reports-toolbar";
|
||||
import { ComparisonChart, Sparkline, SERIES_COLORS, type Series } from "@/components/reports/charts";
|
||||
import { ComparisonChart, Sparkline, type Series } from "@/components/reports/charts";
|
||||
import { SERIES_COLORS } from "@/lib/report-colors";
|
||||
import { Kpi, KpiStrip } from "@/components/reports/kpi";
|
||||
import { ReportBreadcrumb, ReportTitle, SelectCheckbox, CompareBar } from "@/components/reports/report-header";
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,11 @@ import {
|
|||
CartesianGrid,
|
||||
Cell,
|
||||
} from "recharts";
|
||||
import { SERIES_COLORS } from "@/lib/report-colors";
|
||||
|
||||
export const SERIES_COLORS = ["#2563eb", "#16a34a", "#9333ea", "#ea580c", "#0891b2", "#dc2626", "#ca8a04", "#4f46e5", "#0d9488", "#db2777"];
|
||||
// Re-exported for back-compat; new server-component code should import the
|
||||
// palette from "@/lib/report-colors" directly (see that file for why).
|
||||
export { SERIES_COLORS };
|
||||
|
||||
/** Compact Indian-currency formatter for axis ticks / tooltips (₹..K / ₹..L / ₹..Cr). */
|
||||
export function formatINRShort(n: number): string {
|
||||
|
|
|
|||
21
App/lib/report-colors.ts
Normal file
21
App/lib/report-colors.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Shared categorical palette for the Reports charts + table swatches.
|
||||
//
|
||||
// This is a plain, dependency-free module (NO "use client", no server-only
|
||||
// imports) so it can be imported by BOTH the server-component report pages and
|
||||
// the client chart components and resolve to the real array in each. It must NOT
|
||||
// live in a "use client" module: a plain value imported from a client module
|
||||
// into a server component becomes a client-reference proxy (not the array), so
|
||||
// `SERIES_COLORS[i]` would silently be `undefined` and every series would fall
|
||||
// back to recharts' default colour.
|
||||
export const SERIES_COLORS = [
|
||||
"#2563eb",
|
||||
"#16a34a",
|
||||
"#9333ea",
|
||||
"#ea580c",
|
||||
"#0891b2",
|
||||
"#dc2626",
|
||||
"#ca8a04",
|
||||
"#4f46e5",
|
||||
"#0d9488",
|
||||
"#db2777",
|
||||
];
|
||||
Loading…
Add table
Reference in a new issue