'use client'; /** * Dev-only chart gallery. * * Every primitive is exercised here against the REAL route handlers, not * inline arrays — so this page simultaneously proves the charts render, the * data layer round-trips, and the loading/empty/error skins are correct. * Use the state buttons to force each branch. */ import {useState} from 'react'; import {VStack, HStack} from '@astryxdesign/core/Layout'; import {Grid} from '@astryxdesign/core/Grid'; import {Card} from '@astryxdesign/core/Card'; import {Heading, Text} from '@astryxdesign/core/Text'; import {Button} from '@astryxdesign/core/Button'; import {Badge} from '@astryxdesign/core/Badge'; import {useResource} from '@/shared/hooks/useResource'; import {dashboardRepository} from '@/features/dashboard/repositories/dashboardRepository'; import {ChartCard} from '@/shared/components/charts/ChartCard'; import {LineChartView} from '@/shared/components/charts/LineChartView'; import {AreaChartView} from '@/shared/components/charts/AreaChartView'; import {BarChartView} from '@/shared/components/charts/BarChartView'; import {Sparkline} from '@/shared/components/charts/Sparkline'; import {HeatmapGrid} from '@/shared/components/charts/HeatmapGrid'; import type {HourCell, Kpi, TimePoint} from '@/features/dashboard/types/dashboard'; import { formatCompact, formatDayLabel, formatDelta, formatInrCompact, formatPct, } from '@/shared/utils/format'; type Forced = '' | 'empty' | 'error' | 'delay'; export default function ChartsGallery() { const [forced, setForced] = useState(''); // The forced state is folded into the endpoint params, so it becomes part of // the request identity and useResource refetches when it changes. const extra = forced === 'delay' ? {_delay: '4000'} : forced ? {_state: forced} : {}; const scope = {range: '30d' as const, storeId: 'all'}; const withExtra = (e: {path: string; params: Record}) => ({...e, params: {...e.params, ...extra}}) as never as T; const series = useResource( withExtra(dashboardRepository.timeseries(scope)), ); const kpis = useResource(withExtra(dashboardRepository.kpis(scope))); const peak = useResource( withExtra(dashboardRepository.peakHours(scope)), ); return ( Chart primitives Monochrome by construction. Series beyond the second are separated by dash pattern and hatch fill, never hue — semantic colour is reserved for thresholds and deltas. {( [ ['', 'Live data'], ['delay', 'Loading (4s)'], ['empty', 'Empty'], ['error', 'Error'], ] as [Forced, string][] ).map(([v, label]) => (