Commit Graph

3 Commits

Author SHA1 Message Date
482b4802ff Make swaps precise: drop no-op requests, swap only the affected field
Refine per-trigger granularity now that the swap target is explicit:

- Memo issues no request at all -- it affects nothing else, so its value just
  rides along in the form and is merged into the snapshot on save. (Changing the
  Location *value* likewise issues no request -- it never did; that cell's request
  is the account->location dependency.)
- Account select swaps only that row's Location cell (#account-location-<index> /
  #simple-account-location) instead of the whole form. Selecting an account only
  affects the valid Location options (computed from the posted account-id), so a
  precise cell swap is safe -- no snapshot dependency.

Account-structural changes (vendor, add/remove row, mode toggle, $/% radio) keep
swapping the whole form: their accounts+amount-mode state is interdependent and
round-trips through the single form-level snapshot hidden field, so a whole-form
swap is what keeps it consistent with zero OOB.

Update the memo test to assert it fires no request and keeps its value/caret.
Full e2e suite: 27 passed / 2 failed (same pre-existing, unrelated failures).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 20:12:22 -07:00
5f1bb6db82 Whole-form hx-select swaps with zero out-of-band swaps
Replace the section-swap + OOB approach with uniform whole-form swaps,
eliminating both out-of-band swaps:

- Discrete edits (vendor, account, location, mode, add/remove row) now swap all
  of #wizard-form via hx-select. The active action/tab already round-trips
  (:action is in edit-form-schema and the tab x-data inits from it), so a
  whole-form swap re-creates the tab state from the server value and the active
  tab is preserved -- no #wizard-snapshot OOB needed, since the snapshot hidden
  field rides along inside the form.
- Move the totals into their own <tbody id="account-totals"> (new optional
  :footer-tbody param on data-grid-) so the amount field updates them with a
  plain targeted swap instead of an OOB swap of #total,#balance. The totals tbody
  is a sibling of the input rows, so the amount input is never replaced.
- Memo unchanged (hx-swap=none).

Net: 0 hx-select-oob, 0 morph. The focus invariant is unchanged -- the typed
field is never inside a region it swaps. Tab clicks stay Alpine (instant); only
the action value round-trips. Revert the now-unneeded #wizard-snapshot id.

Full e2e suite: 27 passed / 2 failed (same pre-existing, unrelated failures).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 11:01:37 -07:00
a2684bf5c1 Replace alpine-morph with targeted hx-select / OOB swaps
Drop the whole-form alpine-morph swap in favour of posting the whole form
but swapping back only what changed, never the input the user is editing --
so focus and caret survive a plain swap with no morph extension.

- Discrete changes (vendor, account, location, mode, add/remove row) swap the
  #manual-coding-section fragment via hx-select, plus an OOB refresh of the
  #wizard-snapshot hidden field so the round-tripped wizard state stays in sync
  (the snapshot lives at #wizard-form level, outside the swapped fragment, and
  the new/remove-account handlers read it).
- The amount field OOB-swaps only #total/#balance (hx-swap=none); memo posts
  with hx-swap=none. Neither input is ever replaced.
- Give the BALANCE cell a unique id (#balance) so the OOB selector is unambiguous.
- Remove the alpine-morph ext + @alpinejs/morph plugin and all the key/x-data
  re-init tricks they required. Rebuilding the fragment fresh makes vendor->account
  population and repeat vendor changes work without any keying.
- Rename e2e/transaction-edit-morph.spec.ts -> -swap.spec.ts; assertions unchanged
  (focus/caret preservation, vendor->account, repeat vendor changes all hold).

Full e2e suite: 27 passed / 2 failed (both pre-existing and unrelated -- the
legacy save-flow test and the date-range filter test).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 08:10:05 -07:00