# Implementation Plan: Reporting and Analytics Dashboards UI **Branch**: `002-reporting-dashboards-ui` | **Date**: 2026-09-09 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `specs/002-reporting-dashboards-ui/spec.md` ## Summary Presents `supporthub-api`'s already-complete 015-reporting-dashboards contract (four `GET /admin/reports/*` endpoints) as a tabbed admin surface, replacing nothing existing — `admin/reports/page.tsx` already hosts the SLA Monitor and Escalation Matrix (012-admin-list- views work); this feature adds Management/Product/Support/AI as four more tabs on that same page. New reusable dashboard primitives (stat tile, ranked bar list, status distribution bar, meter) are built once in `components/ui` and reused across all four dashboards, following the `dataviz` skill's methodology: pick the form before color, status colors (already defined in this project's own design tokens) for status-flavored splits, a single sequential hue for magnitude rankings, validated in both light and dark mode. ## Technical Context **Language/Version**: TypeScript, Next.js 14 App Router (unchanged). **Primary Dependencies**: None new — TanStack Query (already the standard), the existing `components/ui` kit, this project's own Tailwind design tokens. No charting library added (spec.md Assumptions) — every visual is plain HTML/CSS per the `dataviz` skill's Tier 0/1 component guidance (a proportional div-based bar needs no SVG/canvas dependency). **Storage**: N/A — no client-side persistence; date-range selection is component state (spec.md Assumptions). **Testing**: Vitest for the new pure helpers (duration/rate formatting, the "no data" guard); component tests for each dashboard's loading/empty/error/ready rendering (mocked query client, matching 001-agent-admin-ui's own established testing pattern); Playwright E2E against the real running `supporthub-api` + `supporthub-web` pair for the full tab-switching, date-range, and product-selection flow — this session's standing rule of never claiming a frontend scenario done without exercising it against real, live infrastructure. **Target Platform**: Web, `(admin)` portal only (Constitution Principle III). **Project Type**: Frontend — single Next.js app, no new module boundary crossed. **Performance Goals**: Each dashboard fetches independently (its own `useQuery`) so switching tabs doesn't block on data the current tab doesn't need; date-range changes debounce-free (a single explicit "Apply" action, not a fetch per keystroke) to avoid hammering the backend while typing a date. **Constraints**: FR-008 — no new/changed backend endpoint; this is presentation-only. FR-004 — every `null` rate/average renders as an explicit "No data" treatment, computed once in the mapping layer (`lib/api/reports.ts`) so every consuming component gets an already-safe shape, never a raw `null` a component might accidentally interpolate into text. **Scale/Scope**: One new `lib/api/reports.ts` (+types), four new `features/reports/*-dashboard.tsx` components, four new `components/ui` primitives (stat tile, ranked bar list, status distribution bar, meter), one modified `admin/reports/page.tsx` (adds tabs), one shared date-range control. ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | Principle / Section | Check | Result | |---|---|---| | I. Each Identity Has Exactly One Authority, and the Frontend Is Never It | Not applicable — no identity/access surface touched. | PASS — N/A | | II. The Backend Is the Sole Source of Business Logic | Every figure (rates, distributions, rankings) is rendered exactly as the backend computed it — this feature does no business-rule computation, only display formatting (e.g. seconds -> "2h 15m"). | PASS | | III. Strict Portal Boundaries | All new code lives under `(admin)`/`features/reports` — no customer- or support-portal import, no shared primitive leaks admin-only data (the new `components/ui` primitives are generic value/label/color renderers, not admin-shaped). | PASS | | IV. Typed API Boundary, No Ad Hoc Fetching | All four dashboards fetched through new `lib/api/reports.ts` functions wrapped in TanStack Query hooks — no direct `fetch`/`axios` in any component. | PASS | | V. Configuration Over Hardcoding | Not applicable — no admin-configurable enum rendered by this feature (the confidence bands/status labels are fixed, backend-defined vocabulary, not business policy). | PASS — N/A | | VI. Accessible, Responsive, Enterprise-Grade UI | New primitives keep density over decoration per this principle's own wording — status colors always paired with a text label (never color-alone, satisfying both this principle's WCAG requirement and the `dataviz` skill's own non-negotiable), keyboard-reachable tab/date controls, responsive down to a single column. | PASS | | VII. Testing Gates | Typecheck/lint clean; new Vitest coverage for the mapping/formatting helpers and each dashboard's query-state rendering; Playwright coverage added for the reports tab-switching flow (not one of the constitution's two named cross-cutting journeys, but this project's own established practice of E2E-verifying every admin feature against a real backend, per 001's own precedent). | PASS | No violations requiring Complexity Tracking justification. ## Project Structure ### Documentation (this feature) ```text specs/002-reporting-dashboards-ui/ ├── plan.md ├── data-model.md ├── quickstart.md └── tasks.md ``` ### Source Code (repository root) ```text supporthub-web/ ├── src/ │ ├── components/ui/ │ │ ├── stat-tile.tsx # NEW │ │ ├── ranked-bar-list.tsx # NEW │ │ ├── status-distribution.tsx # NEW │ │ ├── meter.tsx # NEW │ │ └── index.ts # MODIFIED — export the four above │ ├── lib/ │ │ ├── api/ │ │ │ ├── reports.ts # NEW — 4 fetch functions │ │ │ └── types/ │ │ │ └── reports.ts # NEW — response + view-model types │ │ └── format/ │ │ └── duration.ts # NEW — seconds -> "2h 15m" / "No data" │ ├── features/reports/ │ │ ├── management-dashboard.tsx # NEW │ │ ├── product-dashboard.tsx # NEW │ │ ├── support-dashboard.tsx # NEW │ │ ├── ai-dashboard.tsx # NEW │ │ ├── date-range-control.tsx # NEW — shared by Management/Product/AI │ │ ├── sla-monitor.tsx # UNCHANGED (012's own) │ │ └── escalation-matrix.tsx # UNCHANGED (012's own) │ └── app/(admin)/admin/reports/ │ └── page.tsx # MODIFIED — adds 4 tabs alongside the 2 existing sections └── tests/ ├── unit/lib/format/ # duration formatting, no-data guard ├── unit/features/reports/ # per-dashboard query-state rendering └── e2e/ # reports tab-switching + date-range Playwright spec ``` **Structure Decision**: No new route, no new portal — extends the existing `(admin)/admin/reports` page and `features/reports` module already established by 012-admin-list-views' SLA Monitor/ Escalation Matrix work. ## Complexity Tracking *No constitution violations — table intentionally omitted.*