# Pattern: Analytics

## Intent

A data-dense page focused on comparative, time-series analysis. Unlike the Dashboard pattern, Analytics pages prioritize filtering scope (time periods) and allow users to switch between multiple analytical views via Tabs. Every chart on the page responds to the same period filter.

---

## When to Use

- Adoption metrics, engagement trends, funnel analysis
- Performance monitoring over configurable time ranges
- Any page where users compare data across multiple time periods or segments

---

## Key Difference from Dashboard

| Dashboard             | Analytics                    |
| --------------------- | ---------------------------- |
| At-a-glance overview  | Deep comparative analysis    |
| Fixed, static metrics | Time-period-filtered metrics |
| One primary view      | Multiple tab-based views     |
| Fast to read          | Requires user interaction    |

---

## Anatomy

```
┌─────────────────────────────────────────────────────────────────┐
│  Page Header: Title         [Period Select ▾] [Export Button]   │
│                              ← period filter applies globally → │
├─────────────────────────────────────────────────────────────────┤
│  Tabs: [General] [Funnel] [Performance] [Custom...]             │
├─────────────────────────────────────────────────────────────────┤
│  Tab Content:                                                    │
│  ┌──────────┬──────────┬──────────┐                            │
│  │ StatCard │ StatCard │ StatCard │  ← 3-col stats grid        │
│  └──────────┴──────────┴──────────┘                            │
│  ┌─────────────────────────────────┐                            │
│  │ Chart Panel (full width)        │                            │
│  └─────────────────────────────────┘                            │
└─────────────────────────────────────────────────────────────────┘
```

---

## Full Pattern Code

```tsx
import {
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
  Card,
  CardHeader,
  CardTitle,
  CardContent,
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
  Button,
} from 'xertica-ui/ui';
import { CalendarIcon, Download } from 'lucide-react';
import { useState } from 'react';

export function AnalyticsDashboard() {
  const [period, setPeriod] = useState('30');

  return (
    <div className="p-6 w-full max-w-7xl mx-auto space-y-6">
      {/* 1. Page Header with Period Filter */}
      <div className="flex flex-col gap-4 md:flex-row md:items-center justify-between">
        <div>
          <h1 className="text-3xl font-bold tracking-tight">Analytics</h1>
          <p className="text-muted-foreground">Adoption and engagement metrics</p>
        </div>
        <div className="flex items-center gap-2">
          <Select value={period} onValueChange={setPeriod}>
            <SelectTrigger className="w-[180px]">
              <CalendarIcon className="mr-2 size-4 text-muted-foreground" />
              <SelectValue placeholder="Period" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="7">Last 7 days</SelectItem>
              <SelectItem value="30">Last 30 days</SelectItem>
              <SelectItem value="90">Last 3 months</SelectItem>
              <SelectItem value="365">Last year</SelectItem>
            </SelectContent>
          </Select>
          <Button variant="outline" className="gap-2">
            <Download className="size-4" />
            Export CSV
          </Button>
        </div>
      </div>

      {/* 2. Tabs */}
      <Tabs defaultValue="general">
        <TabsList>
          <TabsTrigger value="general">General</TabsTrigger>
          <TabsTrigger value="funnel">Adoption Funnel</TabsTrigger>
          <TabsTrigger value="performance">Performance</TabsTrigger>
        </TabsList>

        {/* Tab: General */}
        <TabsContent value="general" className="mt-6 space-y-6">
          {/* Stats Row */}
          <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
            <StatCard title="Total Sessions" value="12,430" trend="+8.2%" />
            <StatCard title="Unique Users" value="3,204" trend="+14.1%" />
            <StatCard title="Avg. Session Duration" value="4m 32s" trend="-0.5%" />
          </div>

          {/* Chart */}
          <Card>
            <CardHeader>
              <CardTitle>Daily Engagement (MAU)</CardTitle>
            </CardHeader>
            <CardContent className="h-[400px]">
              {/* Mount Recharts LineChart here, filtered by `period` state */}
              <div className="flex h-full w-full items-center justify-center rounded-md border border-dashed bg-muted/20 text-muted-foreground">
                Line Chart Area — filtered by last {period} days
              </div>
            </CardContent>
          </Card>
        </TabsContent>

        {/* Tab: Funnel */}
        <TabsContent value="funnel" className="mt-6">
          <Card>
            <CardHeader>
              <CardTitle>Adoption Funnel</CardTitle>
            </CardHeader>
            <CardContent className="h-[400px] flex items-center justify-center">
              <p className="text-muted-foreground">Funnel chart placeholder</p>
            </CardContent>
          </Card>
        </TabsContent>

        {/* Tab: Performance */}
        <TabsContent value="performance" className="mt-6">
          <p className="text-muted-foreground">Performance metrics go here.</p>
        </TabsContent>
      </Tabs>
    </div>
  );
}

function StatCard({ title, value, trend }: { title: string; value: string; trend: string }) {
  return (
    <Card>
      <CardHeader className="pb-2">
        <CardTitle className="text-sm font-medium text-muted-foreground">{title}</CardTitle>
      </CardHeader>
      <CardContent>
        <div className="text-2xl font-bold">{value}</div>
        <p className="mt-1 text-xs text-muted-foreground">
          <span className="text-primary font-medium">{trend}</span> vs previous period
        </p>
      </CardContent>
    </Card>
  );
}
```

---

## Composition Rules

1. **Period filter is global** — it must sit in the page header and drive all charts within all tabs.
2. **Period filter uses `<Select>`** — not a date picker by default. Add `<Calendar>` only when exact date range selection is required.
3. **`max-w-7xl mx-auto`** — always constrain analytics pages to prevent charts from stretching too wide on ultra-wide monitors.
4. **Use `Tabs` for view switching** — never create separate pages for each analytics view.
5. **Chart placeholder areas** use `h-[400px]` and `border-dashed bg-muted/20`.
6. **Stats in analytics use a 3-column grid** — unlike Dashboard which uses 4. Analytics metrics tend to be wider with more context.

---

## Related Patterns

- [Dashboard Pattern](./dashboard.md) — For simpler overview pages without deep filtering
- [CRUD Pattern](./crud.md) — For entity management triggered from analytics

## Related Components

- [`Tabs`](../components/tabs.md)
- [`Select`](../components/select.md)
- [`Card`](../components/card.md)
- [`Chart`](../components/chart.md)
