refactor(ssr): full Selmer migration of Transaction Edit; remove the wizard

Migrate every part of the Transaction Edit modal's HTML to Selmer templates
(zero Hiccup in the render path) and delete the mm multi-modal "wizard"
abstraction entirely -- there was only ever one step.

- New auto-ap.ssr.components.selmer (sc) + ~22 shared component partials under
  resources/templates/components/ (typeahead, button-group, radio-card,
  data-grid, validated-field, modal, buttons, inputs, SVGs). Each wrapper renders
  its own partial; dynamic HTMX/Alpine attrs bridge via attrs->str -> {{attrs|safe}}.
- 15 modal templates under resources/templates/transaction-edit/.
- Delete EditWizard/LinksStep records + all mm/* usage. Plain handlers: flat
  wrap-decode-edit (fields renamed off step-params[...], stray keys stripped),
  flat wrap-derive-state, *errors*-based field errors, generic wrap-form-4xx-2.
- Drop the edit-wizard-navigate route (routes ~12 -> 5).
- Fix: stray `method` (tab button-group hidden) leaked into the upsert -> 500;
  strip decoded map to schema keys.
- e2e selectors updated (#wizard-form->#edit-form, #wizardmodal->#editmodal,
  step-params[...] field names). Parity: swap 6/6, edit 8/8, suite 38/1
  (1 pre-existing unrelated nav test).
- ssr-form-migration skill updated with the learnings (composition mechanics,
  sc/* library, drop-the-wizard recipe, scorecard row, 3 new gotchas).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 07:47:47 -07:00
parent c892719bd1
commit a01dfc197e
47 changed files with 1161 additions and 659 deletions

View File

@@ -0,0 +1,4 @@
{# Modal card chrome (header / optional side panel / body / footer). Single-step, so
no timeline, no back/next nav -- just the Done button in the footer. Enter triggers
the save button via $refs.next. #}
<div class="modal-card bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content flex flex-col max-h-screen max-w-screen md:w-[950px] md:h-[650px] w-full h-full last-modal-step transition duration-150" @keydown.enter.prevent.stop="if ($refs.next) {$refs.next.click()}" x-data=""><div class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0">{{ head|safe }}</div><div class="flex shrink overflow-auto grow">{% if side_panel %}<div class="grow-0 w-64 bg-gray-50 border-r hidden md:block overflow-y-auto max-h-full">{{ side_panel|safe }}</div>{% endif %}<div class="px-6 py-2 space-y-6 overflow-y-scroll w-full shrink grow">{{ body|safe }}</div></div><div class="p-4 border-t">{{ footer|safe }}</div></div>