# Senior Court Monitor (Mobile) — Developer Task Breakdown

> Source-of-truth task list for the Senior Court Monitor slot (dev-mode v1.0, Step 3b). One row per screen + the shared dependencies. Surface = Flutter mobile portrait. Mirrors the anchor (Staff Court Monitor) tasks, `MON-*` → `SCM-*`, **plus the added `SCM-TEAM-STATUS` read-only screen + read-model endpoint**.
> **Team for this slot:** Mobile (Flutter) FE + Backend (shared with TL/SM cascade) + Tester. No web-FE (mobile-primary role).
> **Priority:** P0 (must-ship Phase 1) · P1 (nice-to-have).
> **Dependencies** are topological — build in order. Foundation (Wave 0) precedes everything: schema, auth, runtime RBAC resolver, auto-assign engine, approval cascade, `/me`, photo endpoint, Flutter DS parity, generated Dart models.
> **Reuse note:** screens 1–8 are clones of the anchor's Flutter widgets — wire them to `SCM-*` routes and reuse verbatim. Only `SCM-TEAM-STATUS` is net-new code.

---

## Columns
| Column | Meaning |
|---|---|
| Screen ID | Stable short ID (cross-refs `spec.md`, `api-contract.md`). |
| Screen file | Path under `screens/` (the pixel target). |
| States / sheets | The `states/` + `bottom-sheets/` variants to wire. |
| Dependencies | What must exist first. |
| Mobile-FE tasks | Flutter widget/route/repository work. |
| Backend tasks | Endpoint(s) + logic + migration notes (most are Wave-0 shared). |
| Pri | P0 / P1. |

---

## Auth + bootstrap

### AUTH-LOGIN — Login
| Field | Value |
|---|---|
| Screen file | `screens/01-login.html` |
| States / sheets | `states/locked.html`, `states/error.html` |
| Dependencies | Wave-0 auth + `/me` |
| Mobile-FE tasks | Reuse anchor login widget; call `POST /auth/login`; store tokens (secure storage); on success `GET /me` → route by role (SCM); render locked/error states; navy-on-orange Sign In (52px); Maniax wordmark lockup. |
| Backend tasks | (Wave 0) `POST /auth/login` (bcrypt, JWT access+refresh, rate-limit→423/429); `/auth/refresh`; `/auth/logout`; forgot/reset; `POST /devices/register`. |
| Pri | P0 |

### SCM-DASH — Senior Monitor Home (role-resolved)
| Field | Value |
|---|---|
| Screen file | `screens/02-dashboard.html` |
| States / sheets | `states/loading.html`, `states/empty.html` |
| Dependencies | AUTH-LOGIN; Wave-0 `/me`; auto-assign (roster published) |
| Mobile-FE tasks | Reuse the mobile shell (navy top bar + Game-Zone scope strip + 5-slot bottom nav + FAB) from the Flutter DS; render shift card + KPI tiles + today's checklist list; overdue badge; **add the Team-status entry card** (taps to `SCM-TEAM-STATUS`); nothing-assigned empty state; loading skeleton. |
| Backend tasks | `GET /me/dashboard` (own GZ + own assignments; counts by state; shift; **`teamSummary` block**). |
| Pri | P0 |

## Checklist core (the anchor flow — clone)

### SCM-CHK-TODAY — Today's Checklists
| Field | Value |
|---|---|
| Screen file | `screens/03-today-checklists.html` |
| States / sheets | `states/loading.html`, `states/empty.html`, `states/error.html`, `states/forbidden.html` |
| Dependencies | SCM-DASH; auto-assign engine (Wave 0) |
| Mobile-FE tasks | Reuse anchor list widget: `ChecklistInstance` rows with template name + frequency tag + item-count + `StatusBadge` + "📷 needed" hint; tap → fill (not-started/in-progress) or status (submitted+); loud Sent-back row + Re-fill. |
| Backend tasks | `GET /me/checklists/today` (own assignments, own GZ; stored sub-state per instance). |
| Pri | P0 |

### SCM-CHK-FILL — Fill Checklist (CRITICAL)
| Field | Value |
|---|---|
| Screen file | `screens/04-checklist-fill.html` |
| States / sheets | `bottom-sheets/photo-capture.html`, `bottom-sheets/a-item-note-photo.html`, `states/offline.html` |
| Dependencies | SCM-CHK-TODAY; photo endpoint (Wave 0); instance detail |
| Mobile-FE tasks | Reuse anchor fill widget: sectioned `ChecklistItem` rows with the 44px **G/A segmented toggle** (G green / A red-orange, color+icon+label); **server time + auto-initials display (read-only, §9 #9)**; on **A** open the A-note+photo sheet + flag photo-required; completion-photo `PhotoUpload` tile → photo-capture sheet; multipart upload; save responses (`PATCH …/responses`, `If-Match`) as draft; **offline: hold draft in memory + retry**; FAB = camera. |
| Backend tasks | `GET /checklist-instances/:id` (filler+GZ scoped, version/ETag); `PATCH …/responses` (upsert responses, **set server `recordedAt` + auto initials**, set `fillerId`, bump version, 409 on stale, audit); `POST /uploads/photos` (multipart → **local disk**, `sharp` thumb, `Photo` row); `DELETE /uploads/photos/:id`. |
| Pri | P0 |

### SCM-CHK-SUBMIT — Submit Checklist
| Field | Value |
|---|---|
| Screen file | `screens/05-checklist-submit.html` |
| States / sheets | `bottom-sheets/confirm-submit.html`, `states/offline.html`, `states/error.html` |
| Dependencies | SCM-CHK-FILL; cascade engine (Wave 0) |
| Mobile-FE tasks | Reuse anchor submit widget: review summary (G/A counts, completion + A-item thumbnails); enforce the photo/answer **gate client-side** with inline danger messages; confirm-submit sheet; `POST …/submit`; handle 422 (highlight missing); on success route to status. |
| Backend tasks | `POST /checklist-instances/:id/submit` — **re-check gate (422 if untouched item / no completion photo / missing A-photo)**; state→`SUBMITTED`; create TL/SM/OH `ApprovalStep`s; **notify TL (FCM + in-app)**; audit. (Shared handler with anchor.) |
| Pri | P0 |

### SCM-CHK-STATUS — My Checklist Status
| Field | Value |
|---|---|
| Screen file | `screens/06-my-status.html` |
| States / sheets | `states/empty.html`, sent-back banner (inline) |
| Dependencies | SCM-CHK-SUBMIT; cascade (Wave 0); send-back from TL/SM/OH packs |
| Mobile-FE tasks | Reuse anchor status widget: `ApprovalTimeline` vertical stepper (Filled→TL→SM→OH) with actor/role/timestamp + `StatusBadge`; show **real sub-state** (never Pending); **Sent-back red banner + reason + Re-fill** → reopen fill; `/me/submissions` list. |
| Backend tasks | `GET /me/submissions`; `GET /checklist-instances/:id/timeline` (steps + sentBackReason); `renderStatusForViewer()` (shared, Wave 0). |
| Pri | P0 |

## Supporting screens

### SCM-ROSTER-OWN — My Roster (read-only)
| Field | Value |
|---|---|
| Screen file | `screens/08-my-roster.html` |
| States / sheets | `states/empty.html`, day/week toggle |
| Dependencies | Wave-0 roster |
| Mobile-FE tasks | Reuse anchor roster widget: day/week toggle; own `RosterEntry` rows (ride + shift, template-colored blocks); leave overlay; **no create/edit affordance**. |
| Backend tasks | `GET /me/roster?date=` / `?weekOf=` (own entries only; roster-create denied to SCM by resolver). |
| Pri | P0 |

### SH-PROFILE — Profile / More
| Field | Value |
|---|---|
| Screen file | `screens/07-profile.html` |
| States / sheets | — |
| Dependencies | Wave-0 `/me` |
| Mobile-FE tasks | Reuse anchor profile widget: profile (name, role, Game Zone, reports-to, certified rides); **add a "Team / Zone status" menu row → `SCM-TEAM-STATUS`**; Alerts entry; logout (confirm → clear tokens → login). |
| Backend tasks | `GET /me/profile`; `POST /auth/logout`; `GET /me/notifications` + read. |
| Pri | P0 |

## ADDED — read-only oversight

### SCM-TEAM-STATUS — Team / Zone status (read-only) — NET-NEW
| Field | Value |
|---|---|
| Screen file | `screens/09-team-status.html` |
| States / sheets | `states/loading.html`, `states/empty.html` (no team activity / all-clear), read-only detail (reuses fill/status read widgets) |
| Dependencies | SCM-DASH; cascade + `renderStatusForViewer()` (Wave 0); the `checklist.view` (own_team) permission seed |
| Mobile-FE tasks | Net-new screen: per-monitor list (avatar + name + ride/shift + completion summary + their instances each with `StatusBadge`); filter chips All / Overdue / Sent back; tap → **read-only** instance detail (reuse the fill/status *read* widgets — photos lightbox + `ApprovalTimeline`) with **NO approve / send-back / edit buttons**; empty + all-clear positive states. **Guard: render no write affordance even if a permission is mis-seeded.** |
| Backend tasks | `GET /me/team/checklists/today` (Staff Court Monitors in SCM's GZ + same team; counts + instances; status via shared resolver, SCM viewer → never "Pending"); reuse read-only `GET /checklist-instances/:id` + `/timeline` for team instances; **seed `RolePermission`: SCM gets `checklist.view` scope `own_team`, `checklist.approve` = denied**; resolver returns 403 on any SCM write to a team instance. |
| Pri | P0 (the role's added value; P1-droppable if client declines senior oversight — see handoff blocking Qs) |

---

## Build order (topological)
1. **(Wave 0)** auth, `/me`, RBAC resolver (+ SCM `checklist.view` own_team seed), schema, auto-assign, cascade, photo endpoint, Flutter DS, Dart models.
2. `AUTH-LOGIN` → `SCM-DASH` (shell + role-resolve + Team-status card).
3. `SCM-CHK-TODAY` → `SCM-CHK-FILL` → `SCM-CHK-SUBMIT` (the anchor flow — clone; depends on photo endpoint + cascade).
4. `SCM-CHK-STATUS` (depends on submit + cascade + the TL send-back touchpoint).
5. `SCM-ROSTER-OWN`, `SH-PROFILE` (independent; can run in parallel).
6. `SCM-TEAM-STATUS` (net-new; depends on the team read-model endpoint + read-only detail reuse).

> The SCM demo gate: **Karan logs in → opens Trampoline Daily → ticks G/A (server time + auto initials) with a completion photo + an A-item photo → submit blocked then passes → submitted → TL notified → status timeline shows awaiting-TL → (TL sends back) red banner + Re-fill** AND **opens Team / Zone status → sees the zone monitors' submissions with statuses + photos + timeline and has NO way to approve/edit anything.** When that closes end-to-end against real APIs, the slot is DONE.
