From a01dfc197e443d43bb7c77d69bbda41ea8c386d3 Mon Sep 17 00:00:00 2001 From: Bryce Date: Thu, 4 Jun 2026 07:47:47 -0700 Subject: [PATCH] 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 --- .../reference/component-cookbook.md | 31 + .../reference/form-vs-wizard.md | 33 +- .../ssr-form-migration/reference/gotchas.md | 48 +- .../ssr-form-migration/reference/scorecard.md | 23 + .../reference/selmer-conventions.md | 57 +- e2e/transaction-edit-swap.spec.ts | 12 +- e2e/transaction-edit.spec.ts | 16 +- resources/templates/components/a-button.html | 1 + .../templates/components/a-icon-button.html | 1 + resources/templates/components/badge.html | 1 + .../components/button-group-button.html | 1 + .../templates/components/button-group.html | 1 + resources/templates/components/button.html | 1 + .../templates/components/data-grid-cell.html | 1 + .../components/data-grid-header.html | 1 + .../templates/components/data-grid-row.html | 1 + resources/templates/components/data-grid.html | 1 + resources/templates/components/hidden.html | 3 + resources/templates/components/link.html | 1 + resources/templates/components/modal.html | 1 + .../templates/components/money-input.html | 2 + .../templates/components/radio-card.html | 1 + resources/templates/components/spinner.html | 1 + .../templates/components/svg-drop-down.html | 1 + .../components/svg-external-link.html | 1 + resources/templates/components/svg-x.html | 1 + .../templates/components/text-input.html | 3 + resources/templates/components/typeahead.html | 4 + .../templates/components/validated-field.html | 6 + .../transaction-edit/account-totals.html | 3 + .../transaction-edit/approval-status.html | 1 + .../transaction-edit/details-panel.html | 2 + .../templates/transaction-edit/edit-form.html | 4 + .../transaction-edit/edit-modal.html | 4 + .../transaction-edit/invoice-option.html | 1 + .../transaction-edit/linked-payment.html | 1 + .../transaction-edit/links-body.html | 3 + .../transaction-edit/manual-coding.html | 3 + .../transaction-edit/panel-empty.html | 1 + .../transaction-edit/panel-list.html | 3 + .../transaction-edit/payment-matches.html | 2 + .../transaction-edit/rule-option.html | 1 + .../transaction-edit/simple-mode.html | 4 + .../transaction-edit/transitioner.html | 3 + src/clj/auto_ap/ssr/components/selmer.clj | 292 ++++ src/clj/auto_ap/ssr/transaction/edit.clj | 1236 ++++++++--------- src/cljc/auto_ap/routes/transactions.cljc | 1 - 47 files changed, 1161 insertions(+), 659 deletions(-) create mode 100644 resources/templates/components/a-button.html create mode 100644 resources/templates/components/a-icon-button.html create mode 100644 resources/templates/components/badge.html create mode 100644 resources/templates/components/button-group-button.html create mode 100644 resources/templates/components/button-group.html create mode 100644 resources/templates/components/button.html create mode 100644 resources/templates/components/data-grid-cell.html create mode 100644 resources/templates/components/data-grid-header.html create mode 100644 resources/templates/components/data-grid-row.html create mode 100644 resources/templates/components/data-grid.html create mode 100644 resources/templates/components/hidden.html create mode 100644 resources/templates/components/link.html create mode 100644 resources/templates/components/modal.html create mode 100644 resources/templates/components/money-input.html create mode 100644 resources/templates/components/radio-card.html create mode 100644 resources/templates/components/spinner.html create mode 100644 resources/templates/components/svg-drop-down.html create mode 100644 resources/templates/components/svg-external-link.html create mode 100644 resources/templates/components/svg-x.html create mode 100644 resources/templates/components/text-input.html create mode 100644 resources/templates/components/typeahead.html create mode 100644 resources/templates/components/validated-field.html create mode 100644 resources/templates/transaction-edit/account-totals.html create mode 100644 resources/templates/transaction-edit/approval-status.html create mode 100644 resources/templates/transaction-edit/details-panel.html create mode 100644 resources/templates/transaction-edit/edit-form.html create mode 100644 resources/templates/transaction-edit/edit-modal.html create mode 100644 resources/templates/transaction-edit/invoice-option.html create mode 100644 resources/templates/transaction-edit/linked-payment.html create mode 100644 resources/templates/transaction-edit/links-body.html create mode 100644 resources/templates/transaction-edit/manual-coding.html create mode 100644 resources/templates/transaction-edit/panel-empty.html create mode 100644 resources/templates/transaction-edit/panel-list.html create mode 100644 resources/templates/transaction-edit/payment-matches.html create mode 100644 resources/templates/transaction-edit/rule-option.html create mode 100644 resources/templates/transaction-edit/simple-mode.html create mode 100644 resources/templates/transaction-edit/transitioner.html create mode 100644 src/clj/auto_ap/ssr/components/selmer.clj diff --git a/.claude/skills/ssr-form-migration/reference/component-cookbook.md b/.claude/skills/ssr-form-migration/reference/component-cookbook.md index dcfcddb1..af778820 100644 --- a/.claude/skills/ssr-form-migration/reference/component-cookbook.md +++ b/.claude/skills/ssr-form-migration/reference/component-cookbook.md @@ -149,3 +149,34 @@ divergence). Scorecard heuristic 1: faked roots → 0. ``` TODO Phase 2: the simple/advanced toggle becomes a `?mode=` re-render (plain form), not a dedicated route. + +--- + +## The Selmer component library (`auto-ap.ssr.components.selmer` / `sc`) — Phase 2-final + +Every shared component the modal renders through is now a thin Clojure wrapper over a +partial under `resources/templates/components/`. **Reuse these before reaching for the +Hiccup `com/*` versions in a migrated modal.** Each wrapper builds a context (reusing the +real class helpers so output matches modulo Tailwind order) and renders its own partial via +the interop bridge; dynamic HTMX/Alpine attrs go through `sc/attrs->str` → +`{{ attrs|safe }}`. See `selmer-conventions.md` for the mechanics. + +| Wrapper | Partial | Notes | +|---------|---------|-------| +| `sc/hidden` / `sc/text-input` / `sc/money-input` | `hidden`/`text-input`/`money-input`.html | leaf inputs; class via `inputs/default-input-classes` + `use-size` | +| `sc/validated-field` | `validated-field.html` | label + body + always-present error `

`; pass-through attrs land on the wrapping div (the per-row location cell hangs its swap wiring here) | +| `sc/button` / `sc/a-button` / `sc/a-icon-button` | `button`/`a-button`/`a-icon-button`.html | spinner via `{% include "spinner.html" %}`; class via `btn/bg-colors` | +| `sc/badge` / `sc/link` | `badge`/`link`.html | | +| `sc/button-group` / `sc/button-group-button` | `button-group(+button).html` | the group does **not** mutate children's classes (the Hiccup `group-` added rounded-l/r) — add rounding in the caller/template (tabs do) | +| `sc/radio-card` | `radio-card.html` | reproduces the `select-keys [:hx-post :hx-target :hx-swap :hx-include :hx-trigger]` filter (drops `:hx-vals`/`:hx-select`) **and** the dangling-`[:h3]` quirk: only the `