# QA — Dashboard overview analytics UI

Manual + automated checklist for `wave1/dashboard-overview-analytics-ui`.
Walk top-to-bottom before promoting to staging.

## Build / static checks

- [ ] `pnpm --filter @navi/api-client typecheck` passes.
- [ ] `pnpm --filter @navi/api-client lint` passes.
- [ ] `pnpm --filter @navi/dashboard typecheck` passes.
- [ ] `pnpm --filter @navi/dashboard lint` passes.
- [ ] No new TypeScript `any` introduced (use the typed DTOs from `@navi/types`).
- [ ] No imports from `apps/api/*` in `apps/dashboard/*` or `packages/api-client/*`.
- [ ] `recharts` is the only new runtime dependency.

## Routes / navigation

- [ ] `/overview` renders for authenticated users with analytics permissions.
- [ ] Filter bar updates `searchParams` and re-renders the page without a hard reload.
- [ ] All "View all …" links resolve to existing routes (`/bookings`, `/provider-health`).

## Permission matrix

| Actor                     | KPI grid | Revenue | Bookings | Customer behavior | Provider readiness | Provider health table |
| ------------------------- | -------- | ------- | -------- | ----------------- | ------------------ | --------------------- |
| Anonymous                 | redirect to login | redirect | redirect | redirect | redirect | redirect |
| Tourist (`REGISTERED`)    | forbidden | forbidden | forbidden | forbidden | forbidden | forbidden |
| Partner (`PARTNER_OWNER`) | forbidden | forbidden | forbidden | forbidden | forbidden | forbidden |
| Support (`SUPPORT_AGENT` with `provider_integration.health.read`) | forbidden | forbidden | forbidden | forbidden | **visible** | **visible** |
| Admin (`admin.report.read`) | visible | visible | visible | visible | visible | visible |
| Super Admin (`*`)         | visible | visible | visible | visible | visible | visible |

For each row, confirm that:
- "Forbidden" panels render `AnalyticsForbiddenState`, not blank space.
- API responses with 401/403 do not throw uncaught errors.

## Data states per panel

For each of the six panels (KPI grid, Risk, Revenue, Bookings, Provider readiness, Provider health, Customer behavior), confirm:
- [ ] Loading: server fetch inflight → no flash of empty layout. (Skeleton not strictly needed for server-rendered fetches, but charts must render placeholders with no console errors.)
- [ ] Empty: zero data → human-readable empty state, not a broken chart axis.
- [ ] Error: API 5xx → `AnalyticsErrorState` with the error message.
- [ ] Forbidden: API 403 → `AnalyticsForbiddenState`.
- [ ] Success: real data renders correctly and matches the API DTO.

## Filter behavior

- [ ] `from`/`to` date pickers default to a trailing 30-day window.
- [ ] Selecting a `from` after `to` causes the API to return 400 → `AnalyticsErrorState` is shown (not a crash).
- [ ] Selecting a >92-day window causes the API to return 400 → error banner shown.
- [ ] Provider environment filter only affects the provider panels.
- [ ] Category filter is rendered disabled with the "Coming soon" label.
- [ ] Booking status filter is rendered disabled with the "Coming soon" label.

## Accessibility

- [ ] Every chart has a tooltip, axis labels, and legible contrast (>= 4.5:1).
- [ ] Filter inputs have associated `<label>` elements.
- [ ] Status badges use both color + text ("DOWN", "DEGRADED" etc.).
- [ ] No reliance on hover-only affordances.

## RTL / i18n

- [ ] Layout does not break with `dir="rtl"` set on `<html>`.
- [ ] Numeric / currency formatting uses `formatMoney` / `formatNumber` so
      the UAE locale and currency render consistently.

## No fake data

- [ ] Search the diff for placeholder strings ("Lorem", "TODO", "fake", "demo only").
- [ ] Confirm no inline values shadow the DTO (every visible number traces back
      to a field in the response).

## Visual smoke (browser)

Run the dashboard locally:

```
pnpm --filter @navi/api dev          # API on :4000
pnpm --filter @navi/api prisma:seed  # Optional: realistic seed
pnpm --filter @navi/dashboard dev    # Dashboard on :3001
```

Then sign in as each actor profile and load `http://localhost:3001/overview`.
Capture a screenshot for the design review record.

## Rollback

- Revert the merge of `wave1/dashboard-overview-analytics-ui`. The previous
  placeholder overview page is preserved in git history. No DB migrations.
  The analytics API endpoints (from `wave1/dashboard-analytics-api`) keep
  working; only the dashboard surface reverts.
