# Technician (Mobile) — Developer Task Breakdown

> Source-of-truth task list for the Technician slot (dev-mode v1.0, CL-2). One row per screen + the shared dependencies. Surface = Flutter mobile portrait.
> **Team for this slot:** Mobile (Flutter) FE + Backend (shared with the Maintenance TL pack + WorkOrder foundation) + 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 (incl. `WorkOrder` / `WorkOrderEvent` / `WorkOrderPhoto`), auth, runtime RBAC resolver, WO state machine, parent `HELD` release logic, `/me`, photo endpoint, Flutter DS parity, generated Dart models.

---

## 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 with `maintenance-tl-web`). |
| Pri | P0 / P1. |

---

## Auth + bootstrap

### AUTH-LOGIN — Login
| Field | Value |
|---|---|
| Screen file | `screens/01-login.html` |
| States / sheets | `states/locked.html`, `states/error.html`, `states/session-expired.html` |
| Dependencies | Wave-0 auth + `/me` |
| Mobile-FE tasks | Login form (email/phone + password, reveal toggle); call `POST /auth/login`; store tokens (secure storage); on success `GET /me` → route by role; render locked/error/session-expired 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); `POST /auth/refresh` (rotate+reuse-detect); `POST /auth/logout`; forgot/reset; `POST /devices/register`. |
| Pri | P0 |

### TECH-DASH — Technician 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`; WorkOrder foundation (assign happened) |
| Mobile-FE tasks | Build the mobile shell (navy top bar + Game-Zone scope strip + 5-slot bottom nav + camera FAB on Done) from the Flutter DS; render maintenance card + 4 KPI tiles (assigned/in-prog/returned/done) + due-soon/overdue badges + WO list preview via `useDashboard`/`WorkOrderRepository`; overdue badge; nothing-assigned empty state; loading skeleton. |
| Backend tasks | `GET /me/dashboard` (own GZ + WOs assigned to me; counts by state; SLA buckets). |
| Pri | P0 |

## Work-order core (the maintenance flow)

### TECH-WO-TODAY — My Work-Orders
| Field | Value |
|---|---|
| Screen file | `screens/03-work-orders.html` |
| States / sheets | `states/loading.html`, `states/empty.html`, `states/error.html`, `states/forbidden.html` |
| Dependencies | TECH-DASH; WorkOrder foundation; assign touchpoint (`maintenance-tl-web`) |
| Mobile-FE tasks | `WorkOrderCard` list (§6.22): A-item + WO code + source checklist + ride + issue-photo count + `StatusBadge wo=…` + SLA/age chip + assigner; filter chips (Open/Assigned/In-progress/Overdue); tap → detail; muted-warning Returned row; mock repo then Dio. |
| Backend tasks | `GET /me/work-orders?state=` (own assignments, own GZ; stored WO state per row; SLA computed). |
| Pri | P0 |

### TECH-WO-DETAIL — Work-Order Detail
| Field | Value |
|---|---|
| Screen file | `screens/04-wo-detail.html` |
| States / sheets | `states/forbidden.html`; photo viewer (inline) |
| Dependencies | TECH-WO-TODAY; WO detail endpoint; timeline (§6.14 WO variant) |
| Mobile-FE tasks | Render source A-item + issue-photo gallery (full-screen viewer) + source checklist/ride/found-by/routed-by/assigned-by + instructions + WO timeline (Routed→Assigned→your-turn); action bar **Start work** (primary) + **Return** (secondary); on Start `PATCH …/start` (If-Match); **no approve/outsource affordance**. |
| Backend tasks | `GET /work-orders/:id` (assignee+GZ scoped, version/ETag); `PATCH …/start` (`ASSIGNED→IN_PROGRESS`, `WorkOrderEvent`, 409 on stale). |
| Pri | P0 |

### TECH-WO-DONE — Mark Done (fixed) (CRITICAL)
| Field | Value |
|---|---|
| Screen file | `screens/05-wo-done.html` |
| States / sheets | `bottom-sheets/photo-capture.html`, `bottom-sheets/confirm-done.html`, `states/offline.html` |
| Dependencies | TECH-WO-DETAIL; photo endpoint (Wave 0); parent `HELD` release logic |
| Mobile-FE tasks | Fix-note textarea; **mandatory fix-photo** `PhotoUpload` tile → photo-capture sheet; camera FAB; multipart upload via `PhotoRepository` (`kind=COMPLETION`, `workOrderId`); **gate Mark Done client-side** until ≥1 photo; confirm-done sheet (states "closes at maintenance"); `PATCH …/done` (If-Match); handle 422 (no photo); **online-only: hold draft in memory + retry**; on success route to status / list. |
| Backend tasks | `POST /uploads/photos` (multipart → **local disk**, `sharp` thumb, `WorkOrderPhoto` row); `DELETE /uploads/photos/:id`; `PATCH …/done` — **re-check photo gate (422 if no `WorkOrderPhoto`)**; `IN_PROGRESS→DONE`; `closedAt`; `WorkOrderEvent`; compute parent `HELD` release on last open WO (no SM notify); audit. |
| Pri | P0 |

### TECH-WO-RETURN — Return with Reason
| Field | Value |
|---|---|
| Screen file | `screens/06-wo-return.html` |
| States / sheets | `bottom-sheets/return-reason.html`, `states/offline.html`, `states/error.html` |
| Dependencies | TECH-WO-DETAIL; Maintenance TL notify touchpoint |
| Mobile-FE tasks | Explainer ("back to Maintenance TL"); quick-reason chips; **required reason** textarea (gate client-side); optional photo tile; return-reason sheet; `PATCH …/return { reason }` (If-Match); handle 422 (empty reason); on success route to list (Returned). |
| Backend tasks | `PATCH …/return` — **reason-required (422 if empty)**; `IN_PROGRESS→RETURNED`; store `returnReason` + `WorkOrderEvent`; **notify the Maintenance TL (FCM + in-app)**; audit. |
| Pri | P0 |

## Supporting screens

### SH-PROFILE — Profile / More
| Field | Value |
|---|---|
| Screen file | `screens/07-profile.html` |
| States / sheets | — |
| Dependencies | Wave-0 `/me` |
| Mobile-FE tasks | Profile (name, role, Game Zone, team, reports-to, skills); Alerts entry; logout (confirm → clear tokens → login). |
| Backend tasks | `GET /me/profile`; `POST /auth/logout`; `GET /me/notifications` + read. |
| Pri | P0 |

---

## Build order (topological)
1. **(Wave 0 / Foundation)** auth, `/me`, RBAC resolver, schema (incl. `WorkOrder`/`WorkOrderEvent`/`WorkOrderPhoto`), WO state machine, parent `HELD` release logic, photo endpoint, Flutter DS, Dart models.
2. `AUTH-LOGIN` → `TECH-DASH` (shell + role-resolve).
3. `TECH-WO-TODAY` → `TECH-WO-DETAIL` → `TECH-WO-DONE` / `TECH-WO-RETURN` (the maintenance flow — depends on the WO endpoints + photo endpoint; pairs with `maintenance-tl-web` assign/review).
4. `SH-PROFILE` (independent; can run in parallel).

> The slot demo gate: **Suresh logs in → opens an assigned WO → Starts → tries Done blocked (no photo) → shoots a fix photo → Done passes → action closes at maintenance + parent checklist releases from Held; and on a different WO → Return blocked (no reason) → enters reason → Return passes → Maintenance TL notified.** When that closes end-to-end against real APIs (paired with `maintenance-tl-web`), the Technician slot is DONE.
