Files
integreat/src/clj/auto_ap/ssr/components/dialog.clj
Bryce fc8ce2633e fix(ssr): bulk-edit empty-selection 500 + modal-footer EDN leak
- BUG D: clicking "Bulk Edit" with no invoices selected 500'd. selected->ids
  returns nil with no selection, and all-ids-not-locked fed that nil into a
  Datomic `:in $ [?i ...]` query ("Unable to find data source"). Guard the body
  with (when (seq all-ids) ...) so an empty selection yields [] and the modal
  opens cleanly. Verified live: no "Oh, drat" toast, no 500.

- BUG B: modal-footer- called (hx/alpine-appear ...) twice; the 2nd return value
  (an attribute map) landed in child position and rendered as literal EDN
  ({:x-show ...}) in the red error banner whenever unexpectedError flipped true.
  Delete the duplicate. Verified: rendered HTML now has one alpine-appear and no
  EDN-text child. (Pre-existing defect, also present on master.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-27 13:21:50 -07:00

83 lines
4.3 KiB
Clojure

(ns auto-ap.ssr.components.dialog
(:require
[auto-ap.ssr.hiccup-helper :as hh]
[auto-ap.ssr.components.buttons :as b]
[auto-ap.ssr.hx :as hx]
[auto-ap.ssr.svg :as svg]))
(defn modal-
"This modal function is used to create a modal window with a stack that allows for transitioning between modals.
:params should include the following keys:
- :handle-unexpected-error? (default: true) - A boolean indicating whether to handle unexpected errors.
- :class (optional) - A string representing additional CSS classes to add to the modal.
&children should include the child components to be rendered within the modal."
[{:as params} & children]
[:div (-> params
(assoc "@click.outside" "open=false")
(dissoc :handle-unexpected-error?)
(update :class (fnil hh/add-class "") ""))
children])
(defn modal-card- [params header content footer]
[:div (update params
:class (fn [c] (-> c
(or "")
(hh/add-class "w-full p-4 modal-card flex max-h-[inherit]"))))
[:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col max-h-full overflow-hidden"}
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
[:div {:class "px-6 py-2 space-y-6 overflow-y-scroll w-full shrink"}
content]
(when footer [:div {:class "p-4"}
[:span.items-center.bg-red-100.text-red-800.text-xs.font-medium.mb-2.p-1.rounded-full.inline-flex (hx/alpine-appear {:x-show "unexpectedError" :class "dark:bg-red-900 dark:text-red-300"})
[:span {:class "w-2 h-2 mr-1 bg-red-500 rounded-full"}] [:span.px-2.py-0.5 "An unexpected error has occured. Integreat staff have been notified."]]
(when (:error params)
[:span.items-center.bg-red-100.text-red-800.text-xs.font-medium.mb-2.p-1.rounded-full.inline-flex {:class "dark:bg-red-900 dark:text-red-300"}
[:span {:class "w-2 h-2 mr-1 bg-red-500 rounded-full"}]
[:span.px-2.py-0.5 (:error params)]])
[:div {:class "shrink-0"}
footer]])]])
(defn modal-header- [params & children]
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"}
children])
(defn modal-header-attachment- [params & children]
[:div {:class "flex items-start justify-between p-4 border-b shrink-0"}
children])
(defn modal-body- [params & children]
[:div {:class "px-6 py-2 space-y-6 overflow-y-scroll w-full shrink grow"}
children])
(defn modal-footer- [params & children]
[:div {:class "p-4 border-t"}
[:span.items-center.bg-red-100.text-red-800.text-xs.font-medium.mb-2.p-1.rounded-full.inline-flex
(hx/alpine-appear {:x-show "unexpectedError" :class "dark:bg-red-900 dark:text-red-300"})
[:span {:class "w-2 h-2 bg-red-500 rounded-full"}]
[:span.px-2.py-0.5 "An unexpected error has occured. Integreat staff have been notified."]]
[:div {:class "shrink-0"}]
children])
(defn modal-card-advanced- [params & children]
[:div (merge params
{:class (hh/add-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" (:class params ""))})
children])
(defn success-modal- [{:keys [title]} & children]
(modal- {}
(modal-card-advanced-
{:class "transition duration-300 ease-in-out htmx-swapping:-translate-x-2/3 htmx-swapping:opacity-0 htmx-swapping:scale-0 htmx-added:translate-x-2/3 htmx-added:opacity-0 htmx-added:scale-0 scale-100 translate-x-0 opacity-100"}
(modal-body- {}
[:div.flex.flex-col.mt-4.space-y-4.items-center
[:div.w-24.h-24.bg-green-50.rounded-full.p-4.text-green-300.animate-gg
svg/thumbs-up]
[:div.text-center.mt-4
[:h3.text-xl.font-bold title]
children
[:div.mt-6
(b/button- {:color :primary
"@click" "$dispatch('modalclose');"} "Close")]]]))))