# Maintenance Team Leader (Web) — Developer Handoff

> Handoff pack for **dev-mode v1.0 — Maintenance Team Leader (web)**, Change List v1.1 **CL-2**. Built 2026-06-19, mirroring the Operation Head web pack (`operation-head-web/`) file-for-file. Source of truth: `docs/design/SCREEN_LIST.md` MTL block (7 screens), `docs/design/DESIGN_SYSTEM.md` (§2.4 `wo-*` + `st-held`, §6.14 ApprovalTimeline workorder variant, §6.22 WorkOrderCard, §6.24 HeldBanner, §7 MTL sidebar, §8.1 web shell), `docs/dev-mode-v1.0/FOUNDATION_SPEC.md` (§4 / §4a / §5 + WorkOrder models), `docs/CHANGE_LIST_v1.1.md` (CL-2).
> Persona: **Vikram Rana** · Maintenance Team Leader · own Game Zone (Ahmedabad-1) · reports to the Store Manager · maintenance branch of the cascade.
> Surface: **Web (Next.js), desktop 1440×900.** A mobile companion (on-floor queue + review) is a P2 secondary surface, not built here.

---

## Who consumes which file

| Role | Primary file | Why |
|---|---|---|
| **Web Frontend (Next.js) Developer** | `tasks.md` Web-FE column → filter `Priority=P0`, sort by Dependencies. Pixel target = `screens/*.html` at 1440px. | Builds the navy 240px sidebar + topbar branch badge shell, the WO queue DataTable, the WO detail + WorkOrder-variant ApprovalTimeline, the assign picker, the review decision bar, and the outsource compose screen. |
| **Backend Developer** | `tasks.md` Backend column + `api-contract.md` + `FOUNDATION_SPEC §4/§4a/§5`. | The WO assign / close / outsource transitions, the HELD-release computation, the dashboard aggregate, the technicians list, the photo viewer. |
| **Tester** | `spec.md` acceptance summary + the two `flows/`. | Web e2e: route-in → assign → tech-done → close (un-HOLD); return → review → outsource (reaches SM); only-outsource-reaches-SM; HELD release on last WO; own-GZ scope. |
| **Mobile (Flutter) Developer** | **Coordinate, don't build here.** The Technician (`technician-mobile`) pack is the downstream that does start/done(+photo)/return; the MTL assigns to it. | — |

---

## Definition of Done for the Maintenance Team Leader (web) slot

The slot ships when all P0 behaviours in `spec.md` pass in a UAT build, evidenced by:

1. **Login → role-resolve:** login routes to the MTL Dashboard via `GET /me`; the **240px navy sidebar** (5 items, 2 groups) + permissions come from the server — **no hardcoded role logic**; active item = 3px orange left bar; topbar **branch badge is read-only** (own scope, no selector).
2. **Dashboard WO health:** `MTL-DASH` shows the WO state-machine KPIs (New/Routed, Assigned, In-progress, Held-source, Returned, Closed today, Overdue) using the locked `wo-*` colors + a queue preview; KPI/preview clicks drill into the queue/detail.
3. **WO queue:** `MTL-WO-QUEUE` lists every routed A-item WO for own GZ (WO# · source · A-item · `wo-*` StatusBadge · technician · age/SLA · action); filter chips by state + Overdue; Routed → Assign, Returned → Review.
4. **WO detail + timeline:** `MTL-WO-DETAIL` shows the source A-item + issue photos (lightbox) + the **HELD banner** + the **WorkOrder-variant ApprovalTimeline** (Routed → Maintenance TL → Technician → Closed/Outsourced); action bar is state- and role-gated.
5. **Assign:** `MTL-WO-ASSIGN` lists only own-team technicians in own GZ with open-WO load badges; assign → `ASSIGNED`; reassign a returned WO → `ASSIGNED`; `If-Match` → 409 on stale.
6. **Review + decision:** `MTL-WO-REVIEW` shows the technician's return reason + photo; **Close internally** → `DONE` (SM **not** notified); **Reassign** → `ASSIGNED`; **Escalate** → `MTL-WO-ESCALATE`.
7. **Outsource = only SM channel:** `MTL-WO-ESCALATE` requires a note (422 if blank) → `OUTSOURCED` → surfaces on `SM-WO-OUTSOURCE`; `DONE` never reaches the SM (CL-2 locked).
8. **Photo viewer (read-only, §4a):** issue + fix + return photos open in the lightbox (local-disk URLs); the MTL never uploads. Technician **Done is photo-gated** (≥1 `WorkOrderPhoto`) — enforced on the Technician side.
9. **Single-track hold:** the source checklist stays HELD while any WO is open; closing the **last** WO (`DONE`/`OUTSOURCED`) auto-releases it (`HELD → TL_APPROVED`) and resumes the TL→SM→OH cascade.
10. **Own-GZ scope + dynamic RBAC:** every WO read/write is server-forced to `me.gameZoneId`; out-of-GZ → 403; assign/close/outsource render from the resolved `RolePermission`, never a hardcoded `role === 'MTL'`.
11. **States + chrome:** loading (skeleton), empty, no-results, error+retry, 401 (session-expired → login), 403 (out-of-GZ / denied) all render; navy 240px sidebar + 64px topbar + branch badge match `DESIGN_SYSTEM §8.1`; CI type-drift gate green.

P1 items are nice-to-have for the slot; out-of-slot items (routing, the physical fix, SM outsourcing decisions, fill/approval) are explicitly not here.

---

## Slot scope at a glance

- **9 screen mockups** (login, dashboard, WO queue, WO detail, WO assign, WO review, WO escalate, team, profile) · **6 state variants** · **4 modals** = **19 HTML artifacts** (PNG render is a later step).
- Endpoints consumed: auth, `/me`, MTL dashboard aggregate, WO list/detail/timeline/photos, technicians list (+load), WO **assign / close / outsource**. WO **create** is the operations TL's; WO **start / done / return** are the Technician's (consumed indirectly).
- **The MTL is the maintenance branch:** it never fills/approves inspection checklists, never does the physical fix, and only escalates outsource cases to the SM. Internal fixes close at the maintenance level; the last close un-HOLDs the source checklist.

## Blocking questions / decisions before fan-out / build

- [ ] **`GET /mtl/dashboard` aggregate shape:** confirm the WO state-machine KPI roll-up + held-source-checklist count + queue preview. Pure aggregation, no new fields, but the shape must be locked. (api-contract gap #1.)
- [ ] **MTL internal `close` endpoint:** is `RETURNED → DONE` (MTL closes internally) a distinct `PATCH …/close` route or the same `done` handler with an MTL actor? `§4a` only names the Technician `done`. (gap #2.)
- [ ] **WO SLA / overdue source:** what defines a WO's SLA (per-priority duration? per-ride?) for the age/over-SLA flag? There is no SLA master in the schema. Confirm at the demo whether SLA is a config or we show age only. (gap #4 — a genuine design question, not assumed.)
- [ ] **Photo grouping (issue / fix / return):** confirm the `GET /work-orders/:id/photos` grouping derives cleanly from `WorkOrderPhoto.kind` + the source A-item's NEGATIVE photo. (gap #3.)
- [ ] **HELD-release notification:** when the last WO closes and the checklist un-HOLDs, who is notified — the operations TL, the SM, or both? (P1; `HANDOFFS.md`.)
- [ ] **Reassign across the team:** can the MTL reassign to *any* own-team technician, or only ones under SLA capacity? Confirm the eligibility rule for the picker.

---

## File references
- Pack root: `docs/design/dev-mode-v1.0/maintenance-tl-web/`
- Screens: `screens/*.html` · States: `states/*.html` · Modals: `modals/*.html`
- Spec: `spec.md` · API: `api-contract.md` · Handoffs: `HANDOFFS.md` · Flows: `flows/*.md`
- Mirrored reference: `docs/design/dev-mode-v1.0/operation-head-web/`
- Foundation: `docs/dev-mode-v1.0/FOUNDATION_SPEC.md` (§4 / §4a / §5, WorkOrder models) · Change list: `docs/CHANGE_LIST_v1.1.md` (CL-2)
- Screen list: `docs/design/SCREEN_LIST.md` (MTL block) · Design system: `docs/design/DESIGN_SYSTEM.md` (§2.4, §6.14, §6.22, §6.24, §7)
- Downstream: `technician-mobile` (assign-out) · SM `SM-WO-OUTSOURCE` (outsource-out) · Upstream: operations-TL `TL-CHK-VERIFY` (route-in)
