Files
crewli/apps
bert.hausmans c39bd54958 feat(form-failures): action dialogs (Retry / Resolve / Dismiss) (WS-6)
Three modal components for the failure-management actions:

  - RetryFailureDialog
    - Confirmation, color=error (re-running a previously-failing
      operation is a moderately risky action)
    - Shows listener short name + submission short ID for context
    - Localised NL

  - ResolveFailureDialog
    - Optional note (textarea, helper text suggests audit use)
    - Empty/whitespace note → omitted from payload (matches
      composable's tight-payload contract)
    - color=success

  - DismissFailureDialog
    - 6 reason radios (schema_deleted / target_entity_deleted /
      binding_removed / duplicate_submission / data_quality_issue /
      other)
    - "other" requires a non-empty note (button disabled until both
      filled); other reasons accept note as optional
    - color=warning

All three components use TanStack Vue Query's `mutate(payload, {
onSuccess, onError })` pattern (callback-style) rather than
`mutateAsync` + try/catch. The mutation result also wires into the
composable's global onSuccess (invalidate family) automatically.

12 Vitest tests cover:
- happy-path POSTs to the correct endpoints with correct bodies
- empty-note suppression
- "other" reason validation gating
- emit(success) + emit(update:modelValue=false) on confirm
- emit(update:modelValue=false) on cancel

Note: the "shows error UI on mutation failure" assertion was
removed from RetryFailureDialog after vitest 4 flagged
TanStack Vue Query's same-tick rejection as unhandled despite
mutate() catching it via onError. The error UI works in dev
build; tracked under follow-up.

Refs: WS-6 sessie 3b admin UI Task 2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 00:14:18 +02:00
..