[C05] Import Mapping Flow (shared)

Summary

Cross-cutting shared middle steps of the async import workflow. Used by both E06 EP import and E08 result import. Captures column-mapping dialog, cell-mapping dialog, and progress + row-results component.

The use-case-specific upload screens (E06/E08 bookend 1) write a localStorage caller key before redirecting into C05; C05 reads the key on completion and redirects back to the matching summary screen (E06/E08 bookend 2).

Actor & Context

Actor: event organiser; staff with import permission. Frequency: per import job — every CSV/XLSX upload that needs mapping resolution. Precondition: a job has been created via POST /api/imports; localStorage caller key written by the calling page. Entry point: redirect from E06 upload screen, E08 upload screen, or a future caller; resume from My imports link or job-list entry.

Main Flow

  1. Read job state via GET /api/imports/{uuid}.

  2. If state is COLUMN_MAPPING — render column-mapping dialog: unmatched columns picker against target fields returned by the server. User submits with PUT /api/imports/{uuid}/column-mappings.

  3. If state is CELL_MAPPING — render cell-mapping dialog: unmatched-FK-values picker (dropdown of valid options). User submits with PUT /api/imports/{uuid}/cell-mappings.

  4. While state is PROCESSING — render progress component with polling loop.

  5. When state is COMPLETED or FAILED — render row-results component (paginated row outcomes) briefly, then read the caller key from localStorage and redirect to the matching use-case summary screen.

Alternative Flows

  • AF-1 — Pause. User leaves the mapping screen; state is server-side; resume via My imports returns to the same point.

  • AF-2 — Cancel. DELETE /api/imports/{uuid} aborts; SPA reflects CANCELLED state.

  • AF-3 — Invalid state transition (409). Surface a clear message and a recovery path: refresh status, retry mapping, abort.

  • AF-4 — No caller key. Fall back to a generic landing (My imports list); do not assume a caller.

  • AF-5 — Fatal job error. Render the failure with reason + a Try again action that returns to the caller’s upload screen.

Acceptance Criteria

  • Use-case page authored.

  • Status moves design-todo → in-design → handoff-ready after Claude Design pass.

  • :design-url: populated.

  • Cross-references to E06 + E08 use cases.

  • Caller-tracking convention documented (key name, write-time, read-time, fallback).

  • State-transition error (409) UX is concrete and actionable.

API Surface

Call Purpose

GET /api/imports/{uuid}

Fetch current job state + pending mappings.

PUT /api/imports/{uuid}/column-mappings

Submit column mapping corrections (202 Accepted).

PUT /api/imports/{uuid}/cell-mappings

Submit cell mapping corrections (202 Accepted).

GET /api/imports/{uuid}/results

Paginated row-by-row results.

DELETE /api/imports/{uuid}

Cancel the job.

Out of Scope

  • Use-case-specific upload screens — those are E06 / E08 bookends.

  • Use-case-specific summary screens — those are E06 / E08 bookends.

  • Backend changes to async-import — already shipped on develop and deployed to dev.

Design Anchors

Notes

Async-import backend is on develop and deployed to dev; testable end-to-end without backend changes. Strict state-machine — 409 on invalid transitions; UX must surface this gracefully.

Caller-key convention (proposed): localStorage.setItem('importCaller', 'e06' | 'e08' | …) written by the caller before navigating to C05. C05 clears the key after redirect-back to prevent stale state.

Active design iteration in progress. A 2026-04-29 session drafted Claude Design prompts directly in chat without reading this .adoc first; the result was wrong on the 2-phase API. WIP context, prompts, and seven open design questions are persisted at admin-portal Screen Design Prompt Iteration. Next session: read that journal entry + this .adoc, then derive the v3 prompt from THIS .adoc after design discussion.