feat(ssr): restore forward/back step slide in the wizard engine

The engine migration replaced the old mm/* modal-stack wizards (which slid
forward/back between steps) with wizard2, but never carried the slide over — step
transitions went flat. Restore the original mechanism in the shared engine so all
wizards (new-invoice, vendor, client, pay, transaction-rule) get it:

- wizard2/step-slide-classes: the group-[.forward]/transition:htmx-* and
  group-[.backward]/* slide variants, applied to the swapped <form>.
- wizard2/transitioner: the #transitioner wrapper whose @htmx:after-request hook
  reads the x-transition-type response header and toggles group/transition +
  forward|backward on itself. All 5 configs' :open-response now use it.
- wizard2/handle-step-submit sets x-transition-type (forward on advance, backward
  on Back, none on a same-step validation re-render) + HX-reswap "outerHTML
  swap:0.16s" so the slide-out plays before the swap. Direction computed from
  step order (transition-type).
- Removed the interim per-card fade-in in favor of this.
- Rebuilt output.css so the 16 fwd + 16 back slide variants are compiled.

REPL-verified: open-wizard emits the transitioner, the form carries the slide
classes, and submit responses carry the transition headers. Live verification
needs a server refresh (the dev server froze its route table at startup).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 21:17:51 -07:00
parent 6c791efb06
commit b44213bffd
8 changed files with 267 additions and 37 deletions

View File

@@ -93,21 +93,28 @@ animate:
- By contrast, `dialog/success-modal-` and the Invoice Pay card (`last-modal-step transition
duration-150`) keep transitions, so the intended pattern still exists to copy from.
**FIX — DONE (subtle fade) & verified:** added the codebase's existing `fade-in transition-opacity
duration-300` to all three wizard step cards (new-invoice basic-details + accounts, vendor
step-card, client step-card). `fade-in` is defined in `resources/input.css`
(`.htmx-added .fade-in { opacity:0 }` → transitions to 1 after htmx settle), so each card fades in
on open *and* on every step swap. Verified live: cards always settle to **opacity 1** (never stuck
invisible) on both open and step navigation — no functional risk.
Notes / intentionally deferred (needs design intent + visual sign-off, so not done autonomously):
- The transaction-edit "reference" card's `last-modal-step` class is **undefined** (a no-op); its
only real transition is `transition duration-150`. So there was no clean reference slide to copy.
- The richer **forward/backward slide** transitions (the old `mm/*` modal-stack system using
`group/transition` + `forward`/`backward` + `htmx-*:translate-x-2/3`) were deliberately deleted in
Phase 11 and purged from the CSS. Re-introducing directional slides is a larger design decision
(which element carries `htmx-swapping`/`htmx-added` — the form vs the card — plus settle timing)
and is left for a human-in-the-loop pass if the subtle fade isn't enough.
**FIX — DONE (forward/back slide restored) in the shared `wizard2` engine.** The user confirmed the
old wizard had a directional **slide forward/back** between steps; the engine migration dropped it.
Restored the original mechanism (read out of the deleted `mm/multi_modal.clj`) in one shared place:
- `wizard2/step-slide-classes` — the `group-[.forward]/transition:htmx-*` + `group-[.backward]/…`
variants, now applied to the swapped wizard `<form>`.
- `wizard2/transitioner` — the `#transitioner` wrapper with the `@htmx:after-request` hook that reads
the `x-transition-type` response header and toggles `group/transition` + `forward|backward` on
itself (so the variants fire on the next swap). All 5 wizard configs' `:open-response` now wrap the
form in `wizard2/transitioner` instead of a plain `#transitioner` div.
- `wizard2/handle-step-submit` now sets `x-transition-type` (forward on advance, backward on Back,
`none` on a same-step validation re-render) + `HX-reswap: outerHTML swap:0.16s` (the swap delay
that lets the slide-out play). Direction is computed from the step order (`transition-type`).
- The earlier per-card `fade-in` (interim) was removed in favor of this.
- CSS rebuilt so the `group-[.forward]/transition:htmx-*` variants (16 fwd + 16 back) are compiled.
- Applies to ALL wizards (new-invoice, vendor, client, pay, transaction-rule) since it lives in the
engine. REPL-verified: `open-wizard` emits the transitioner, the form carries the slide classes,
and submit responses carry `x-transition-type` + the `HX-reswap` swap delay.
- **Live-verify caveat:** the long-lived dev server froze its route table at startup
(`auto-ap.handler/match->handler-lookup` is a `def` that merged the per-ns `key->handler` maps), so
an nREPL reload of leaf namespaces does NOT reach the running router — a server refresh
(`stop jetty → tools.namespace refresh → user/start-http`) or a fresh `lein run` is needed to see
it live. (Documented hazard; see the QA memory.)
## 4. Bug list + fixes (prioritized task list)

View File

@@ -1609,10 +1609,6 @@ input:checked + .toggle-bg {
width: 5em;
}
.w-\[600px\] {
width: 600px;
}
.w-\[700px\] {
width: 700px;
}
@@ -3996,6 +3992,44 @@ input:checked + .toggle-bg {
opacity: 0;
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:translate-x-1\/4.htmx-swapping {
--tw-translate-x: 25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:-translate-x-1\/4.htmx-swapping {
--tw-translate-x: -25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:scale-75.htmx-swapping {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:scale-75.htmx-swapping {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:opacity-0.htmx-swapping {
opacity: 0;
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:opacity-0.htmx-swapping {
opacity: 0;
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-swapping\:ease-in.htmx-swapping {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-swapping\:ease-in.htmx-swapping {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.htmx-swapping .htmx-swapping\:-translate-x-2\/3 {
--tw-translate-x: -66.666667%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -4011,6 +4045,44 @@ input:checked + .toggle-bg {
opacity: 0;
}
.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:translate-x-1\/4 {
--tw-translate-x: 25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:-translate-x-1\/4 {
--tw-translate-x: -25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:scale-75 {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:scale-75 {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:opacity-0 {
opacity: 0;
}
.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:opacity-0 {
opacity: 0;
}
.group\/transition.backward .htmx-swapping .group-\[\.backward\]\/transition\:htmx-swapping\:ease-in {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.group\/transition.forward .htmx-swapping .group-\[\.forward\]\/transition\:htmx-swapping\:ease-in {
transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
}
.htmx-added\:translate-x-2\/3.htmx-added {
--tw-translate-x: 66.666667%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -4026,6 +4098,44 @@ input:checked + .toggle-bg {
opacity: 0;
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:-translate-x-1\/4.htmx-added {
--tw-translate-x: -25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:translate-x-1\/4.htmx-added {
--tw-translate-x: 25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:scale-75.htmx-added {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:scale-75.htmx-added {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:opacity-0.htmx-added {
opacity: 0;
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:opacity-0.htmx-added {
opacity: 0;
}
.group\/transition.backward .group-\[\.backward\]\/transition\:htmx-added\:ease-out.htmx-added {
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.group\/transition.forward .group-\[\.forward\]\/transition\:htmx-added\:ease-out.htmx-added {
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.htmx-added .htmx-added\:translate-x-2\/3 {
--tw-translate-x: 66.666667%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
@@ -4041,6 +4151,44 @@ input:checked + .toggle-bg {
opacity: 0;
}
.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:-translate-x-1\/4 {
--tw-translate-x: -25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:translate-x-1\/4 {
--tw-translate-x: 25%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:scale-75 {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:scale-75 {
--tw-scale-x: .75;
--tw-scale-y: .75;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:opacity-0 {
opacity: 0;
}
.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:opacity-0 {
opacity: 0;
}
.group\/transition.backward .htmx-added .group-\[\.backward\]\/transition\:htmx-added\:ease-out {
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
.group\/transition.forward .htmx-added .group-\[\.forward\]\/transition\:htmx-added\:ease-out {
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
:is(.dark .dark\:border-blue-500) {
--tw-border-opacity: 1;
border-color: rgb(0 156 234 / var(--tw-border-opacity));

View File

@@ -517,7 +517,7 @@
[{:keys [title active all-data nav body]}]
(com/modal-card-advanced
{"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}"
:class " md:w-[820px] md:h-[560px] w-full h-full fade-in transition-opacity duration-300"
:class " md:w-[820px] md:h-[560px] w-full h-full"
:x-data (hx/json {"clientName" (:client/name all-data)})}
(com/modal-header {} [:div.flex [:div.p-2 title]
[:p.ml-2.rounded.bg-gray-50.p-2.dark:bg-gray-600 [:span {:x-text "clientName"}]]])
@@ -1216,7 +1216,7 @@
:form-id "wizard-form"
:submit-route (bidi/path-for ssr-routes/only-routes ::route/save)
:form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"}
:open-response (fn [form] (modal-response [:div#transitioner.flex-1 form]))
:open-response (fn [form] (modal-response (wizard2/transitioner form)))
:init-fn client-init-fn
:steps [{:key :info :decode decode-info :validate (partial validate-with info-schema) :render render-info :next (fn [_] :matches)}
{:key :matches :decode (partial decode-with matches-schema) :validate (partial validate-with matches-schema) :render render-matches :next (fn [_] :contact)}

View File

@@ -827,7 +827,7 @@
;; new/edit routes are just (partial wizard2/open-wizard config) -- no hand-rolled
;; create!/render/wrap/thread boilerplate.
:open-response (fn [form]
(modal-response [:div#transitioner.flex-1 form]))
(modal-response (wizard2/transitioner form)))
:steps [{:key :edit
:decode decode-rule-form
:validate rule-form-errors

View File

@@ -373,7 +373,7 @@
[{:keys [title active all-data nav body]}]
(com/modal-card-advanced
{"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}"
:class " md:w-[760px] md:h-[520px] w-full h-full fade-in transition-opacity duration-300"
:class " md:w-[760px] md:h-[520px] w-full h-full"
:x-data (hx/json {"vendorName" (:vendor/name all-data)
"showPrintAs" (boolean (not-empty (:vendor/print-as all-data)))
"printAs" (:vendor/print-as all-data)})}
@@ -672,7 +672,7 @@
:form-id "wizard-form"
:submit-route (bidi/path-for ssr-routes/only-routes ::route/save)
:form-attrs {:hx-ext "response-targets" :hx-target-400 "#form-errors"}
:open-response (fn [form] (modal-response [:div#transitioner.flex-1 form]))
:open-response (fn [form] (modal-response (wizard2/transitioner form)))
:init-fn vendor-init-fn
:steps [{:key :info :decode (partial decode-with info-schema) :validate (partial validate-with info-schema) :render render-info :next (fn [_] :terms)}
{:key :terms :decode (partial decode-with terms-schema) :validate (partial validate-with terms-schema) :render render-terms :next (fn [_] :account)}

View File

@@ -33,11 +33,15 @@
(:require
[auto-ap.ssr.components :as com]
[auto-ap.ssr.components.wizard-state :as ws]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.utils :refer [html-response]]))
(defn- step-by-key [config k]
(first (filter #(= (:key %) k) (:steps config))))
(defn- step-index [config k]
(.indexOf (mapv :key (:steps config)) k))
(defn- prev-step
"The step key before `k` in the linear step order (or `k` itself if first)."
[config k]
@@ -45,13 +49,68 @@
i (.indexOf keys k)]
(if (pos? i) (nth keys (dec i)) k)))
(defn- transition-type
"forward when advancing to a later step, backward when returning to an earlier one, nil
when staying on the same step (a validation re-render) — used to drive the slide."
[config from-key to-key]
(let [fi (step-index config from-key)
ti (step-index config to-key)]
(cond
(or (neg? fi) (neg? ti) (= fi ti)) nil
(> fi ti) "backward"
:else "forward")))
(def step-slide-classes
"Forward/back slide variants applied to the swapped wizard <form>. The #transitioner
ancestor (see `transitioner`) carries `group/transition` + `forward`|`backward`; during a
step swap the outgoing form gets `htmx-swapping` and the incoming one `htmx-added`, so
these variants animate the card sliding/fading in the matching direction."
(str "group-[.forward]/transition:htmx-swapping:opacity-0 "
"group-[.forward]/transition:htmx-swapping:-translate-x-1/4 "
"group-[.forward]/transition:htmx-swapping:scale-75 "
"group-[.forward]/transition:htmx-swapping:ease-in "
"group-[.forward]/transition:htmx-added:opacity-0 "
"group-[.forward]/transition:htmx-added:scale-75 "
"group-[.forward]/transition:htmx-added:translate-x-1/4 "
"group-[.forward]/transition:htmx-added:ease-out "
"group-[.backward]/transition:htmx-swapping:opacity-0 "
"group-[.backward]/transition:htmx-swapping:translate-x-1/4 "
"group-[.backward]/transition:htmx-swapping:scale-75 "
"group-[.backward]/transition:htmx-swapping:ease-in "
"group-[.backward]/transition:htmx-added:opacity-0 "
"group-[.backward]/transition:htmx-added:scale-75 "
"group-[.backward]/transition:htmx-added:-translate-x-1/4 "
"group-[.backward]/transition:htmx-added:ease-out "
"opacity-100 translate-x-0 scale-100 transition duration-150"))
(defn transitioner
"Wrap the opened wizard form in the #transitioner the slide animation hooks onto. After
each step swap it reads the `x-transition-type` response header and toggles
`group/transition` + `forward`|`backward` on itself, which drives `step-slide-classes` on
the swapped form. Rendered once on open; the form swaps itself inside it, so this node
(and its Alpine state) persists across steps."
[form]
[:div#transitioner.flex-1
{:x-data (hx/json {"transitionType" "none"})
:x-ref "transitioner"
"@htmx:after-request" (str "if (event.detail.xhr.getResponseHeader('x-transition-type') && "
"event.detail.xhr.getResponseHeader('x-transition-type') !== 'none') {"
" $refs.transitioner.classList.remove('forward');"
" $refs.transitioner.classList.remove('backward');"
" $refs.transitioner.classList.add('group/transition');"
" $refs.transitioner.classList.add(event.detail.xhr.getResponseHeader('x-transition-type'));"
"} else { $refs.transitioner.classList.remove('group/transition'); }")}
form])
(defn wizard-form
"Wrap a step body in the wizard <form>: the form posts to the submit route, and only the
wizard-id + current-step ride along (no accumulated data — that lives in the session).
Enter is guarded so it triggers the step's primary nav button (the one marked
`data-primary`) rather than whichever submit button the browser picks first."
`data-primary`) rather than whichever submit button the browser picks first. The form
carries `step-slide-classes` so the whole-form swap animates as a directional slide."
[config wizard-id current-step body]
[:form (merge {:id (:form-id config "wizard-form")
:class step-slide-classes
:hx-post (:submit-route config)
:hx-target "this"
:hx-swap "outerHTML"
@@ -115,6 +174,17 @@
extra)))
(assoc :session session)))
(defn- with-transition
"Attach the slide headers the #transitioner reads: `x-transition-type` (forward/backward)
plus an `HX-reswap` swap delay so the outgoing form's slide-out is visible before the
swap. nil tt -> `none` (a same-step validation re-render does not animate)."
[resp tt]
(if tt
(-> resp
(assoc-in [:headers "x-transition-type"] tt)
(assoc-in [:headers "HX-reswap"] "outerHTML swap:0.16s"))
(assoc-in resp [:headers "x-transition-type"] "none")))
(defn open-wizard
"Create a wizard instance in the session, render its first step, and return a Ring
response with the updated session threaded. `:init-fn` returns {:context ..., :init-data
@@ -158,9 +228,11 @@
(expired-response config request)
(= direction "back")
(render-response config wizard-id
(ws/set-step session wizard-id (prev-step config current-step))
request)
(let [prev (prev-step config current-step)]
(-> (render-response config wizard-id
(ws/set-step session wizard-id prev)
request)
(with-transition (transition-type config current-step prev))))
:else
(let [step (step-by-key config current-step)
@@ -171,13 +243,16 @@
posted ((:decode step) clean)
errors (when-let [v (:validate step)] (v posted request))]
(if (seq errors)
(render-response config wizard-id session request
{:step-errors errors :step-posted posted})
;; same step -> no slide (with-transition nil => "none")
(-> (render-response config wizard-id session request
{:step-errors errors :step-posted posted})
(with-transition nil))
(let [session' (ws/put-step session wizard-id current-step posted)
nxt ((:next step) posted)]
(if (= nxt :done)
(-> ((:done-fn config) (ws/get-all session' wizard-id) request)
(assoc :session (ws/forget session' wizard-id)))
(render-response config wizard-id
(ws/set-step session' wizard-id nxt)
request))))))))
(-> (render-response config wizard-id
(ws/set-step session' wizard-id nxt)
request)
(with-transition (transition-type config current-step nxt))))))))))

View File

@@ -333,7 +333,7 @@
client-val (or (:invoice/client data) client-from-req)]
(com/modal-card-advanced
{"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}"
:class " md:w-[750px] md:h-[600px] w-full h-full fade-in transition-opacity duration-300"
:class " md:w-[750px] md:h-[600px] w-full h-full"
"x-data" ""}
(com/modal-header {} [:div.p-2 (if extant? "Edit invoice" "New invoice")])
(com/modal-body
@@ -526,7 +526,7 @@
total (expense-accounts-total* rows)]
(com/modal-card-advanced
{"@keydown.enter.prevent.stop" "if ($refs.next) {$refs.next.click()}"
:class " md:w-[750px] md:h-[600px] w-full h-full fade-in transition-opacity duration-300"
:class " md:w-[750px] md:h-[600px] w-full h-full"
"x-data" ""}
(com/modal-header {} [:div.p-2 "Invoice accounts "])
(com/modal-body
@@ -778,7 +778,7 @@
:submit-route (bidi/path-for ssr-routes/only-routes ::route/new-invoice-submit)
:form-attrs {:hx-ext "response-targets"
:hx-target-400 "#form-errors"}
:open-response (fn [form] (modal-response [:div#transitioner.flex-1 form]))
:open-response (fn [form] (modal-response (wizard2/transitioner form)))
:init-fn new-init-fn
:steps [{:key :basic-details
:decode decode-basic-details

View File

@@ -1366,7 +1366,7 @@
:submit-route (bidi/path-for ssr-routes/only-routes ::route/pay-submit)
:form-attrs {:hx-ext "response-targets"
:hx-target-400 "#form-errors"}
:open-response (fn [form] (modal-response [:div#transitioner.flex-1 form]))
:open-response (fn [form] (modal-response (wizard2/transitioner form)))
:init-fn pay-init-fn
:steps [{:key :choose-method
:decode decode-choose-method