# Charts & Analytics Guide ## Table of Contents 1. [Overview Architecture](#overview-architecture) 2. [Parallel Routes Pattern](#parallel-routes-pattern) 3. [Chart Components](#chart-components) 4. [Stats Cards](#stats-cards) 5. [Skeleton Loading](#skeleton-loading) 6. [Adding a New Chart Section](#adding-a-new-chart-section) --- ## Overview Architecture The analytics dashboard at `/dashboard/overview` uses **Next.js parallel routes** to load multiple chart sections independently. Each chart slot streams in as its data becomes ready — no waterfall, no blocking. **File structure:** ``` src/app/dashboard/overview/ ├── layout.tsx # Composes all slots into a grid ├── @area_stats/ │ ├── page.tsx # Async server component (fetches data) │ ├── loading.tsx # Skeleton shown while streaming │ └── error.tsx # Error boundary if fetch fails ├── @bar_stats/ │ ├── page.tsx │ ├── loading.tsx │ └── error.tsx ├── @pie_stats/ │ ├── page.tsx │ ├── loading.tsx │ └── error.tsx └── @sales/ ├── page.tsx ├── loading.tsx └── error.tsx src/features/overview/components/ ├── area-graph.tsx # Client chart component ├── area-graph-skeleton.tsx # Matching skeleton ├── bar-graph.tsx ├── bar-graph-skeleton.tsx ├── pie-graph.tsx ├── pie-graph-skeleton.tsx ├── recent-sales.tsx └── recent-sales-skeleton.tsx ``` --- ## Parallel Routes Pattern ### Layout (`layout.tsx`) The layout receives each parallel route as a prop and arranges them in a grid: ```tsx export default function OverviewLayout({ sales, pie_stats, bar_stats, area_stats }: { sales: React.ReactNode; pie_stats: React.ReactNode; bar_stats: React.ReactNode; area_stats: React.ReactNode; }) { return ( {/* Stats cards row */}
Total Revenue
$45,231.89

+20.1% from last month

{/* ...more stat cards */}
{/* Charts grid — each slot loads independently */}
{area_stats}
{sales}
{bar_stats}
{pie_stats}
); } ``` ### Slot Page (`@area_stats/page.tsx`) Each slot is an async server component that fetches data then renders the chart: ```tsx import { delay } from '@/constants/mock-api'; import { AreaGraph } from '@/features/overview/components/area-graph'; export default async function AreaStatsPage() { await delay(2000); // Simulates API fetch return ; } ``` ### Slot Loading (`@area_stats/loading.tsx`) ```tsx import { AreaGraphSkeleton } from '@/features/overview/components/area-graph-skeleton'; export default function Loading() { return ; } ``` ### Slot Error (`@area_stats/error.tsx`) ```tsx 'use client'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Icons } from '@/components/icons'; export default function AreaStatsError({ error }: { error: Error }) { return ( Error Failed to load area stats: {error.message} ); } ``` Each slot can fail independently without affecting others. --- ## Chart Components All chart components are `'use client'` and use **Recharts** wrapped in shadcn's `ChartContainer`. ### Chart Config Every chart defines a config object mapping data keys to labels and theme colors: ```tsx import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; const chartConfig = { desktop: { label: 'Desktop', color: 'var(--chart-1)' }, mobile: { label: 'Mobile', color: 'var(--chart-2)' } } satisfies ChartConfig; ``` Theme colors `--chart-1` through `--chart-5` are defined in each theme's CSS file and automatically adapt to light/dark mode. ### Area Chart Example ```tsx 'use client'; import { Area, AreaChart, CartesianGrid, XAxis } from 'recharts'; import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Icons } from '@/components/icons'; const chartData = [ { month: 'January', desktop: 186, mobile: 80 }, { month: 'February', desktop: 305, mobile: 200 } // ...more months ]; const chartConfig = { desktop: { label: 'Desktop', color: 'var(--chart-1)' }, mobile: { label: 'Mobile', color: 'var(--chart-2)' } } satisfies ChartConfig; export function AreaGraph() { return ( Area Chart - Stacked +12.5% value.slice(0, 3)} /> } /> ); } ``` ### Bar Chart Pattern Same structure, using `BarChart` + `Bar`: ```tsx } /> ``` ### Pie/Donut Chart Pattern ```tsx } /> ``` --- ## Stats Cards Stats cards are simple server-rendered `Card` components at the top of the layout — no parallel routes needed since they render instantly: ```tsx Total Revenue
$45,231.89

+20.1% from last month

``` For dynamic stats that need data fetching, wrap in their own Suspense boundary or parallel route slot. --- ## Skeleton Loading Each chart has a matching skeleton component. Pattern: ```tsx import { Card, CardContent, CardHeader } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; export function AreaGraphSkeleton() { return ( ); } ``` Match the skeleton dimensions to the actual chart for smooth visual transitions. --- ## Adding a New Chart Section To add a new chart (e.g., line chart for user growth): ### 1. Create the chart component `src/features/overview/components/line-graph.tsx`: ```tsx 'use client'; import { Line, LineChart, CartesianGrid, XAxis } from 'recharts'; import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart'; const chartConfig = { users: { label: 'Users', color: 'var(--chart-3)' } } satisfies ChartConfig; const chartData = [ /* monthly user data */ ]; export function LineGraph() { return ( User Growth } /> ); } ``` ### 2. Create matching skeleton `src/features/overview/components/line-graph-skeleton.tsx` ### 3. Create parallel route slot ``` src/app/dashboard/overview/@line_stats/ ├── page.tsx → async, fetches data, returns ├── loading.tsx → returns ├── error.tsx → error alert └── default.tsx → return null (fallback when route doesn't match) ``` `default.tsx` is required for parallel routes — return `null` or a fallback: ```tsx export default function Default() { return null; } ``` ### 4. Add slot to layout Update `src/app/dashboard/overview/layout.tsx`: ```tsx export default function OverviewLayout({ sales, pie_stats, bar_stats, area_stats, line_stats // ← add new slot }: { /* ...types */ }) { return (
{/* existing charts */}
{line_stats}
); } ``` ### Available Recharts Components Common chart types to use with `ChartContainer`: - `AreaChart` + `Area` — filled area charts (stacked or standalone) - `BarChart` + `Bar` — vertical/horizontal bars - `LineChart` + `Line` — line/trend charts - `PieChart` + `Pie` — pie/donut charts - `RadarChart` + `Radar` — radar/spider charts - `RadialBarChart` + `RadialBar` — radial progress bars All support `ChartTooltip`, `ChartLegend`, and theme-aware colors via `var(--chart-N)`.