From 464c02a7f4b885a178adcd3041eb1380ce6f9ad6 Mon Sep 17 00:00:00 2001 From: lorentz Date: Sun, 3 May 2026 16:51:30 -0400 Subject: [PATCH] docs(03-01): complete dashboard API + components plan summary --- .../03-dashboard-restyle/03-01-SUMMARY.md | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 .planning/phases/03-dashboard-restyle/03-01-SUMMARY.md diff --git a/.planning/phases/03-dashboard-restyle/03-01-SUMMARY.md b/.planning/phases/03-dashboard-restyle/03-01-SUMMARY.md new file mode 100644 index 0000000..11661d9 --- /dev/null +++ b/.planning/phases/03-dashboard-restyle/03-01-SUMMARY.md @@ -0,0 +1,140 @@ +--- +phase: 03-dashboard-restyle +plan: 01 +subsystem: api, ui +tags: [mobile, dashboard, nextjs, postgres, tailwind, shadcn, lucide] + +# Dependency graph +requires: + - phase: 02-mobile-shell-more-drawer + provides: mobile layout shell (HeaderBar, BottomNav, MoreDrawer) that wraps all /mobile/* pages +provides: + - GET /api/mobile/dashboard returning MobileDashboardResponse (kpis, needsAttention, workers) + - KpiCardMobile component (phone-sized KPI card, tone-aware destructive border) + - NeedsAttentionStrip component (horizontal-scroll strip of compact attention cards) + - WorkerStatusRow component (3-cell worker/backup status row with status dot indicators) +affects: + - 03-02 (plan 02 wires these components into app/mobile/dashboard/page.tsx) + +# Tech tracking +tech-stack: + added: [] + patterns: + - "Mobile API endpoint: single Promise.all with 6 parameterless queries, company_scope exclusion filter, manual snake→camel transform" + - "Mobile component comment block: /* ComponentName — phase 03 (DASH-XX). */ header with purpose description" + - "Tone-aware KPI card: TONE_BORDER record maps tone to Tailwind border class" + - "Worker status derivation: down if fail_1h>0 and in_flight=0, warn if fail_1h>0, ok otherwise" + +key-files: + created: + - components/mobile/KpiCardMobile.tsx + - components/mobile/NeedsAttentionStrip.tsx + - components/mobile/WorkerStatusRow.tsx + modified: + - app/api/mobile/dashboard/route.ts + +key-decisions: + - "Reused sla_breaches integer from KPI query for overdue_tickets count in needsAttention — avoids a 7th query" + - "Default export import (not named) for postgresClient matches app/api/dashboard/overview/route.ts reference route pattern" + - "captions left undefined for now — plan 02 can add vs-yesterday deltas without an API change" + +patterns-established: + - "Mobile endpoint pattern: requireAuth at top, single Promise.all, typed query generics, manual int parse with ?? '0' fallback" + - "Mobile component pattern: 'use client'; /* Name — phase NN (REQ-NN). */ block, pure presentational, no fetch" + +requirements-completed: [DASH-01, DASH-02, DASH-03] + +# Metrics +duration: 18min +completed: 2026-05-03 +--- + +# Phase 3 Plan 1: Dashboard API + Presentational Components Summary + +**Mobile dashboard API reshaped to return kpis/needsAttention/workers in a single round-trip, plus three presentational components (KpiCardMobile, NeedsAttentionStrip, WorkerStatusRow) ready for plan 02 to wire into the page.** + +## Performance + +- **Duration:** ~18 min +- **Started:** 2026-05-03T00:00:00Z +- **Completed:** 2026-05-03T00:18:00Z +- **Tasks:** 2 +- **Files modified:** 4 (1 rewritten, 3 created) + +## Accomplishments + +- Rewrote `app/api/mobile/dashboard/route.ts` to return `MobileDashboardResponse` (4 KPIs, 3 Needs Attention items, 3 worker entries) in a single Promise.all of 6 parameterless queries +- Exported 4 TypeScript interfaces (`KpiResponse`, `AttentionResponse`, `WorkerResponse`, `MobileDashboardResponse`) so plan 02 can `import type` them without re-exploring the codebase +- Created `KpiCardMobile` — phone-sized KPI card with optional destructive left border for `tone='attention'` (SLA breaches) +- Created `NeedsAttentionStrip` — horizontal-scroll snap strip of compact attention cards, renders null when empty +- Created `WorkerStatusRow` — 3-cell status row with emerald/amber/destructive status dots, each a next/link to the corresponding admin page + +## Response Shape + +```typescript +export interface MobileDashboardResponse { + kpis: KpiResponse[]; // 4 entries: open_total, opened_today, resolved_today, sla_breaches + needsAttention: AttentionResponse[]; // 3 entries: overdue_tickets, failed_backups, stalled_workflows + workers: WorkerResponse[]; // 3 entries: analyzer, rmm, backup_success_rate +} +``` + +## Component Export Signatures + +```typescript +// KpiCardMobile.tsx +export type KpiTone = 'default' | 'attention'; +export function KpiCardMobile({ label, value, caption, tone }: KpiCardMobileProps): JSX.Element + +// NeedsAttentionStrip.tsx +export interface NeedsAttentionItem { id, label, count, href } +export function NeedsAttentionStrip({ items }: NeedsAttentionStripProps): JSX.Element | null + +// WorkerStatusRow.tsx +export type WorkerStatus = 'ok' | 'warn' | 'down'; +export interface WorkerStatusEntry { id, label, value, status, href } +export function WorkerStatusRow({ entries }: WorkerStatusRowProps): JSX.Element +``` + +## Task Commits + +1. **Task 1: Rewrite /api/mobile/dashboard to return kpis/needsAttention/workers shape** - `24e20c7` (feat) +2. **Task 2: Add KpiCardMobile, NeedsAttentionStrip, WorkerStatusRow components** - `bfe9549` (feat) + +## Files Created/Modified + +- `app/api/mobile/dashboard/route.ts` — Completely rewritten; exports 4 interfaces + GET handler returning MobileDashboardResponse +- `components/mobile/KpiCardMobile.tsx` — New; phone-sized KPI card with tone-aware destructive left border +- `components/mobile/NeedsAttentionStrip.tsx` — New; horizontal-scroll attention strip with snap-x +- `components/mobile/WorkerStatusRow.tsx` — New; 3-cell worker/backup status row with color-coded dots + +## Decisions Made + +- **Reuse sla_breaches for overdue_tickets:** The overdue_tickets count in `needsAttention` is the same value as `sla_breaches` in `kpis` — computed from the same KPI query row, avoiding a 7th query. +- **Default postgresClient import:** Used `import postgresClient from '@/lib/services/postgres-client'` (default export) to match `app/api/dashboard/overview/route.ts` reference route, not the named export used in the old mobile route. +- **Captions deferred:** `caption` fields on KpiResponse are left `undefined` for now; plan 02 can add vs-yesterday deltas without an API shape change. + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None. + +## Known Stubs + +None — all data flows are wired to live DB queries. + +## Threat Flags + +No new security surface introduced. The `/api/mobile/dashboard` endpoint was already an existing route; it now enforces `requireAuth()` (T-03-01) and applies the `company_scope` exclusion on all ticket queries (T-03-02), both as specified in the plan's threat model. + +## Next Phase Readiness + +- Plan 02 (`03-02`) can immediately import `MobileDashboardResponse`, `KpiCardMobile`, `NeedsAttentionStrip`, and `WorkerStatusRow` — no codebase exploration needed +- No blockers. `app/mobile/dashboard/page.tsx` untouched as required (reserved for plan 02) + +--- +*Phase: 03-dashboard-restyle* +*Completed: 2026-05-03*