Chart Config Sync — Single Source of Truth
Date: 2026-02-13 Goal: Ensure export pages automatically support any chart added to the main data pages.
Problem
Chart definitions are duplicated:
- Dust Ranger:
CHART_CONFIGSinDustRangerChartDashboard.tsx(10 charts) vschartOptionsinexport.tsx(10 charts) — currently in sync but can drift - Dust Levels: Charts hardcoded inline in
index.tsxvschartOptionsinexport.tsx— already out of sync (export missing Road Corrugation charts)
When a developer adds a new chart to the main page, they must remember to also add it to the export page.
Solution
Create a shared chart config per feature that both the main page and export page consume.
Dust Ranger: src/features/dust-ranger/config/chartConfig.ts
export interface DustRangerChartConfig {
key: string;
label: string;
icon: string;
defaultSelected: boolean; // for export page
/** Dynamic label parts that depend on dataType */
labelFn?: (dataType: DataType) => string;
}
export const DUST_RANGER_CHART_CONFIGS: DustRangerChartConfig[] = [
{ key: "timeSeries", label: "Time Series", icon: "solar:chart-2-linear", defaultSelected: true, labelFn: (dt) => `${dt === "mc" ? "Mass" : "Number"} Concentration Over Time ${dt === "mc" ? "(MC)" : "(NC)"}` },
{ key: "hourlyAverage", label: "Hourly Average", icon: "solar:clock-circle-linear", defaultSelected: true, labelFn: (dt) => `Hourly Average Patterns ${dt === "mc" ? "(MC)" : "(NC)"}` },
// ... all 10 charts
];Main page (DustRangerChartDashboard.tsx): imports DUST_RANGER_CHART_CONFIGS, uses key/label/icon for toggle buttons.
Export page (dust-ranger-data/export.tsx): imports DUST_RANGER_CHART_CONFIGS, maps to ChartOption[] using key/labelFn/defaultSelected.
Dust Levels: src/features/dust-levels/config/chartConfig.ts
export interface DustLevelChartConfig {
key: string;
label: string;
icon: string;
defaultSelected: boolean;
/** Whether this chart is per-geofence (duplicated when "All" selected) */
perGeofence: boolean;
}
export const DUST_LEVEL_CHART_CONFIGS: DustLevelChartConfig[] = [
{ key: "dustLevelTemp", label: "Dust Levels", icon: "solar:chart-2-linear", defaultSelected: true, perGeofence: true },
{ key: "weeklyAverage", label: "Weekly Average", icon: "solar:calendar-linear", defaultSelected: true, perGeofence: true },
{ key: "monthlyAverage", label: "Monthly Average", icon: "solar:calendar-linear", defaultSelected: true, perGeofence: true },
{ key: "weeklyRoadBumps", label: "Weekly Road Corrugation Count", icon: "solar:road-linear", defaultSelected: false, perGeofence: true },
{ key: "monthlyRoadBumps", label: "Monthly Road Corrugation Count", icon: "solar:road-linear", defaultSelected: false, perGeofence: true },
{ key: "dustDistribution", label: "Data Distribution & Threshold Selection", icon: "solar:pie-chart-linear", defaultSelected: false, perGeofence: false },
{ key: "dustlocUsage", label: "Dustloc Usage", icon: "solar:graph-linear", defaultSelected: true, perGeofence: false },
];Tasks
Task 1: Create Dust Ranger chart config
New file: src/features/dust-ranger/config/chartConfig.ts
- Extract chart definitions from
DustRangerChartDashboard.tsx - Add
defaultSelectedandlabelFnfields
Task 2: Update DustRangerChartDashboard to use shared config
Modify: src/features/dust-ranger/components/DustRangerChartDashboard.tsx
- Import
DUST_RANGER_CHART_CONFIGS - Remove local
CHART_CONFIGS
Task 3: Update Dust Ranger export page to use shared config
Modify: src/app/(admin)/(pages)/dust-ranger-data/export.tsx
- Import
DUST_RANGER_CHART_CONFIGS - Derive
chartOptionsfrom shared config usinglabelFn(dataType)
Task 4: Create Dust Levels chart config
New file: src/features/dust-levels/config/chartConfig.ts
- Define all charts including Road Corrugation charts
Task 5: Update Dust Levels export page to use shared config + add missing charts
Modify: src/app/(admin)/(pages)/dust-levels/export.tsx
- Import
DUST_LEVEL_CHART_CONFIGS - Derive
chartOptionsfrom shared config - Add Road Corrugation chart rendering (Weekly + Monthly, per-geofence aware)
Task 6: Update Dust Levels main page to use shared config (optional)
Modify: src/app/(admin)/(pages)/dust-levels/index.tsx
- Use config for
data-export-keyattributes (lighter touch — main page has complex inline rendering)
Task 7: Verify and lint
npx tsc --noEmitpnpm lint