[C04] Reassignment Dialog

Summary

Cross-cutting, reusable dialog used wherever an event participant holds a race number and the operator needs to swap it. First caller: E02 Event Participants. Future callers: E07 Pre-assignment.

The dialog provides the operator’s explicit signal for what should happen to the old number X. Without it, X can sit in ISSUED indefinitely after a physical replacement — ghost inventory.

Actor & Context

Actor: event organiser, tenant admin, or stock operator. Frequency: ad-hoc; surfaces whenever a number swap is needed (damaged at sign-in, lost in transit, operator override). Precondition: an EP exists with an assigned number; user has permission to reassign. Entry point: Reassign number action on E02 row; Assign inline action on E01 finalisation readiness panel; future per-EP screens.

Main Flow

  1. Dialog opens with EP context (event, name, current number).

  2. New-number picker — pre-populated from the WS1b last-used pick list for person_id (same subtype first; pool fall-through).

  3. Swap-reason picker (required): Damaged, Lost, Other + optional free-text note.

  4. Temporary checkboxTemporary — do not cascade to future events (default unchecked).

  5. Cascade preview — "This change will also detach N future EP(s)."

  6. Submit:

    1. DamagedPOST /api/event-participants/{id}/reassign-number then chain POST /api/race-numbers/flag-unfit for old X.

    2. Lost → reassignment then chain POST /api/race-numbers/mark-lost for old X.

    3. Other → reassignment only.

  7. Success banner reports cascade summary: originating EP swapped, N future EPs detached, temporary y/n.

Alternative Flows

  • AF-1: Reassignment succeeds, chained X-side action fails — surface error; admin told X needs manual attention. Primary swap not rolled back.

  • AF-2: Cascade preview shows zero future EPs — proceed without warning.

  • AF-3: Permission denied — dialog closes with a clear error.

Acceptance Criteria

  • Dialog renders per Claude Design pass.

  • Component is reusable (no E02-specific imports).

  • All three swap-reason chains behave per Session 9 of the journal.

  • Cascade summary surfaced after submit.

  • Failure-handling path tested.

API Surface

Call Purpose

GET /api/persons/{personId}/number-pickList

Last-used pick list for the new-number picker (WS1b).

POST /api/event-participants/{id}/reassign-number

Primary reassignment with swapReason parameter (US #505).

POST /api/race-numbers/flag-unfit

Chained for Damaged.

POST /api/race-numbers/mark-lost

Chained for Lost.

Out of Scope

  • Bulk reassignment across many EPs — single-EP only for v1.

  • Auto-disposal chain from Damaged — admin runs dispose as a separate step.

  • SMS notification when X is flagged — separate Feature.

Design Anchors

Notes

Reuses backend behaviour from US #505 (shipped). UI candidate for @ems/shared-ui migration once a second consumer surfaces.

Active design iteration in progress. See admin-portal Screen Design Prompt Iteration for WIP prompts and open design questions. Next session: read that journal entry + this .adoc, then derive the v3 prompt from THIS .adoc after design discussion.