diff --git a/resources/public/output.css b/resources/public/output.css index 8df77b4b..15e78cd2 100644 --- a/resources/public/output.css +++ b/resources/public/output.css @@ -1123,6 +1123,10 @@ input:checked + .toggle-bg { z-index: 50; } +.z-\[99\] { + z-index: 99; +} + .col-span-1 { grid-column: span 1 / span 1; } @@ -1172,6 +1176,29 @@ input:checked + .toggle-bg { margin-bottom: 1rem; } +.mx-8 { + margin-left: 2rem; + margin-right: 2rem; +} + +.my-8 { + margin-top: 2rem; + margin-bottom: 2rem; +} + +.my-64 { + margin-top: 16rem; + margin-bottom: 16rem; +} + +.\!mt-0 { + margin-top: 0px !important; +} + +.\!mt-1 { + margin-top: 0.25rem !important; +} + .-mb-1 { margin-bottom: -0.25rem; } @@ -1252,24 +1279,16 @@ input:checked + .toggle-bg { margin-top: 1.25rem; } -.\!mt-0 { - margin-top: 0px !important; +.\!mt-64 { + margin-top: 16rem !important; } -.\!mt-3 { - margin-top: 0.75rem !important; +.\!mt-32 { + margin-top: 8rem !important; } -.mt-3 { - margin-top: 0.75rem; -} - -.\!mt-1 { - margin-top: 0.25rem !important; -} - -.ml-64 { - margin-left: 16rem; +.mr-5 { + margin-right: 1.25rem; } .block { @@ -1356,6 +1375,19 @@ input:checked + .toggle-bg { height: 100vh; } +.h-auto { + height: auto; +} + +.h-min { + height: -moz-min-content; + height: min-content; +} + +.h-64 { + height: 16rem; +} + .max-h-96 { max-height: 24rem; } @@ -1364,6 +1396,10 @@ input:checked + .toggle-bg { max-height: 100%; } +.max-h-screen { + max-height: 100vh; +} + .w-1\/2 { width: 50%; } @@ -1420,19 +1456,23 @@ input:checked + .toggle-bg { width: 24rem; } -.w-full { - width: 100%; -} - .w-auto { width: auto; } +.w-full { + width: 100%; +} + .w-max { width: -moz-max-content; width: max-content; } +.w-screen { + width: 100vw; +} + .max-w-2xl { max-width: 42rem; } @@ -1481,6 +1521,10 @@ input:checked + .toggle-bg { flex-grow: 1; } +.grow-0 { + flex-grow: 0; +} + .basis-1\/4 { flex-basis: 25%; } @@ -1520,6 +1564,26 @@ input:checked + .toggle-bg { 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)); } +.\!translate-y-0 { + --tw-translate-y: 0px !important; + 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)) !important; +} + +.\!translate-y-32 { + --tw-translate-y: 8rem !important; + 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)) !important; +} + +.translate-y-0 { + --tw-translate-y: 0px; + 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)); +} + +.translate-y-4 { + --tw-translate-y: 1rem; + 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)); +} + .rotate-180 { --tw-rotate: 180deg; 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)); @@ -1611,10 +1675,18 @@ input:checked + .toggle-bg { flex-wrap: wrap; } +.place-content-center { + place-content: center; +} + .place-items-center { place-items: center; } +.content-center { + align-content: center; +} + .items-start { align-items: flex-start; } @@ -1651,6 +1723,10 @@ input:checked + .toggle-bg { justify-content: space-between; } +.justify-items-center { + justify-items: center; +} + .justify-items-stretch { justify-items: stretch; } @@ -1747,22 +1823,6 @@ input:checked + .toggle-bg { border-color: rgb(243 244 246 / var(--tw-divide-opacity)); } -.place-self-start { - place-self: start; -} - -.place-self-end { - place-self: end; -} - -.self-start { - align-self: flex-start; -} - -.justify-self-start { - justify-self: start; -} - .justify-self-end { justify-self: end; } @@ -1775,6 +1835,10 @@ input:checked + .toggle-bg { overflow: hidden; } +.overflow-scroll { + overflow: scroll; +} + .overflow-x-auto { overflow-x: auto; } @@ -2060,10 +2124,31 @@ input:checked + .toggle-bg { background-color: rgb(253 246 178 / var(--tw-bg-opacity)); } +.bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + .bg-opacity-50 { --tw-bg-opacity: 0.5; } +.\!bg-opacity-0 { + --tw-bg-opacity: 0 !important; +} + +.\!bg-opacity-50 { + --tw-bg-opacity: 0.5 !important; +} + +.bg-opacity-40 { + --tw-bg-opacity: 0.4; +} + +.\!bg-opacity-100 { + --tw-bg-opacity: 1 !important; +} + .p-1 { padding: 0.25rem; } @@ -2088,6 +2173,10 @@ input:checked + .toggle-bg { padding: 1.5rem; } +.p-12 { + padding: 3rem; +} + .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; @@ -2148,6 +2237,16 @@ input:checked + .toggle-bg { padding-bottom: 1.25rem; } +.px-7 { + padding-left: 1.75rem; + padding-right: 1.75rem; +} + +.py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + .pb-2 { padding-bottom: 0.5rem; } @@ -2371,10 +2470,19 @@ input:checked + .toggle-bg { color: rgb(114 59 19 / var(--tw-text-opacity)); } +.text-gray-200 { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} + .underline { text-decoration-line: underline; } +.\!opacity-0 { + opacity: 0 !important; +} + .opacity-0 { opacity: 0; } @@ -2383,8 +2491,12 @@ input:checked + .toggle-bg { opacity: 1; } -.\!opacity-0 { - opacity: 0 !important; +.\!opacity-50 { + opacity: 0.5 !important; +} + +.\!opacity-100 { + opacity: 1 !important; } .shadow { @@ -2464,6 +2576,10 @@ input:checked + .toggle-bg { transition-duration: 100ms; } +.duration-200 { + transition-duration: 200ms; +} + .duration-300 { transition-duration: 300ms; } @@ -2476,8 +2592,12 @@ input:checked + .toggle-bg { transition-duration: 75ms; } -.duration-200 { - transition-duration: 200ms; +.duration-1000 { + transition-duration: 1000ms; +} + +.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] { + transition-timing-function: cubic-bezier(.3,2.3,.6,1); } .ease-in-out { @@ -2488,8 +2608,8 @@ input:checked + .toggle-bg { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } -.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] { - transition-timing-function: cubic-bezier(.3,2.3,.6,1); +.ease-in { + transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } .htmx-added .fade-in { @@ -2920,6 +3040,11 @@ input:checked + .toggle-bg { background-color: rgb(73 109 28 / var(--tw-bg-opacity)); } +.hover\:bg-neutral-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(245 245 245 / var(--tw-bg-opacity)); +} + .hover\:bg-primary-100:hover { --tw-bg-opacity: 1; background-color: rgb(228 240 213 / var(--tw-bg-opacity)); @@ -2935,9 +3060,9 @@ input:checked + .toggle-bg { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.hover\:bg-neutral-100:hover { +.hover\:bg-gray-50:hover { --tw-bg-opacity: 1; - background-color: rgb(245 245 245 / var(--tw-bg-opacity)); + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); } .hover\:text-blue-600:hover { @@ -3483,6 +3608,43 @@ input:checked + .toggle-bg { display: block; } + .sm\:max-h-\[80vh\] { + max-height: 80vh; + } + + .sm\:max-w-lg { + max-width: 32rem; + } + + .sm\:max-w-xl { + max-width: 36rem; + } + + .sm\:max-w-2xl { + max-width: 42rem; + } + + .sm\:max-w-4xl { + max-width: 56rem; + } + + .sm\:translate-y-0 { + --tw-translate-y: 0px; + 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)); + } + + .sm\:scale-100 { + --tw-scale-x: 1; + --tw-scale-y: 1; + 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)); + } + + .sm\:scale-95 { + --tw-scale-x: .95; + --tw-scale-y: .95; + 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)); + } + .sm\:rounded-lg { border-radius: 0.5rem; } @@ -3608,12 +3770,17 @@ input:checked + .toggle-bg { } } -.\[\&\.active\]\:bg-red-500.active { - --tw-bg-opacity: 1; - background-color: rgb(255 3 3 / var(--tw-bg-opacity)); -} - .\[\&\.active\]\:bg-primary-500.active { --tw-bg-opacity: 1; background-color: rgb(121 181 46 / var(--tw-bg-opacity)); } + +.\[\&\.active\]\:bg-primary-300.active { + --tw-bg-opacity: 1; + background-color: rgb(175 211 130 / var(--tw-bg-opacity)); +} + +:is(.dark .\[\&\.active\]\:dark\:bg-primary-700).active { + --tw-bg-opacity: 1; + background-color: rgb(73 109 28 / var(--tw-bg-opacity)); +} diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj index 34928a2b..dbb4d10b 100644 --- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj +++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj @@ -196,7 +196,7 @@ :action-buttons (fn [request] [(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-new-dialog)) - :hx-target "#modal-holder" + :hx-target "#modal-content" :hx-swap "innerHTML" :color :primary} "New Transaction Rule")]) @@ -204,7 +204,7 @@ [(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-dialog :db/id (:db/id entity))) - :hx-target "#modal-holder" + :hx-target "#modal-content" :hx-swap "innerHTML"} svg/pencil)]) :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes @@ -409,154 +409,153 @@ svg/x)))) ;; TODO dialog is no longer closeable -(defn dialog* [& {:keys [ entity form-params form-errors]}] +(defn dialog* [& {:keys [entity form-params form-errors]}] (com/modal - {:modal-class "max-w-4xl"} - (com/modal-card - {} - [:div.flex [:div.p-2 "Transaction Rule"] ] - [:form#edit-form (merge {:hx-ext "response-targets" - :hx-swap "outerHTML swap:300ms" - :hx-target "#modal-holder" - :hx-target-400 "#form-errors .error-content" - #_#_:x-trap "true"} - form-params) - [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"} - - (fc/start-form entity form-errors - [:div.space-y-2 - (when-let [id (:db/id entity)] - (com/hidden {:name "db/id" - :value id})) + {:modal-class "max-w-4xl"} + (com/modal-card + {} + [:div.flex [:div.p-2 "Transaction Rule"]] + [:form#edit-form (merge {:hx-ext "response-targets" + :hx-swap "outerHTML swap:300ms" + :hx-target "#modal-holder" + :hx-target-400 "#form-errors .error-content" + :x-trap "true"} + form-params) + [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"} - (fc/with-field :transaction-rule/client + (fc/start-form entity form-errors + [:div.space-y-2 + (when-let [id (:db/id entity)] + (com/hidden {:name "db/id" + :value id})) - (com/validated-field - {:label "Client" - :errors (fc/field-errors)} - [:div.w-96 - (com/typeahead-2 {:name (fc/field-name) - :x-init "$el.focus()" - :error? (fc/error?) - :class "w-96" - :placeholder "Search..." - :url (bidi/path-for ssr-routes/only-routes :company-search) - :id (str "form-client-search") - :value (fc/field-value) - :value-fn (some-fn :db/id identity) - :content-fn (fn [c] (cond->> c - (nat-int? c) (dc/pull (dc/db conn) '[:client/name]) - true :client/name))})])) - + (fc/with-field :transaction-rule/client - (fc/with-field :transaction-rule/bank-account - (com/validated-field {:label "Bank Account" - :errors (fc/field-errors)} - [:div#bank-account-spot.w-96 {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead) - :hx-trigger (hx/trigger-field-change :name "transaction-rule/client" - :from "#edit-form") - :hx-swap "innerHTML" - :hx-ext "rename-params" - :hx-include "#edit-form" - :hx-vals (hx/vals {:name (fc/field-name)}) - :hx-rename-params-ex (cheshire/generate-string {"transaction-rule/client" "client-id" - "name" "name"})} - (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity)) - :name (fc/field-name) - :value (fc/field-value)})])) + (com/validated-field + {:label "Client" + :errors (fc/field-errors)} + [:div.w-96 + (com/typeahead-2 {:name (fc/field-name) + :x-init "$el.focus()" + :error? (fc/error?) + :class "w-96" + :placeholder "Search..." + :url (bidi/path-for ssr-routes/only-routes :company-search) + :id (str "form-client-search") + :value (fc/field-value) + :value-fn (some-fn :db/id identity) + :content-fn (fn [c] (cond->> c + (nat-int? c) (dc/pull (dc/db conn) '[:client/name]) + true :client/name))})])) - (fc/with-field :transaction-rule/description - (com/validated-field {:label "Description" - :errors (fc/field-errors)} - (com/text-input {:name (fc/field-name) - :error? (fc/error?) - :placeholder "HOME DEPOT" - :class "w-96" - :value (fc/field-value)}))) + (fc/with-field :transaction-rule/bank-account + (com/validated-field {:label "Bank Account" + :errors (fc/field-errors)} + [:div#bank-account-spot.w-96 {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead) + :hx-trigger (hx/trigger-field-change :name "transaction-rule/client" + :from "#edit-form") + :hx-swap "innerHTML" + :hx-ext "rename-params" + :hx-include "#edit-form" + :hx-vals (hx/vals {:name (fc/field-name)}) + :hx-rename-params-ex (cheshire/generate-string {"transaction-rule/client" "client-id" + "name" "name"})} + (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity)) + :name (fc/field-name) + :value (fc/field-value)})])) - (com/field {:label "Amount"} - [:div.flex.gap-2 - (fc/with-field :transaction-rule/amount-gte - [:div.flex.flex-col - (com/money-input {:name (fc/field-name) - :placeholder ">=" - :class "w-24" - :value (fc/field-value)}) - (com/errors {:errors (fc/field-errors)})]) - (fc/with-field :transaction-rule/amount-lte - [:div.flex.flex-col - (com/money-input {:name (fc/field-name) - :placeholder "<=" - :class "w-24" - :value (fc/field-value)}) - (com/errors {:errors (fc/field-errors)})])]) + (fc/with-field :transaction-rule/description + (com/validated-field {:label "Description" + :errors (fc/field-errors)} + (com/text-input {:name (fc/field-name) + :error? (fc/error?) + :placeholder "HOME DEPOT" + :class "w-96" + :value (fc/field-value)}))) - (com/field {:label "Day of month"} - [:div.flex.gap-2 - (fc/with-field :transaction-rule/dom-gte - (com/validated-field - {:errors (fc/field-errors)} - (com/int-input {:name (fc/field-name) - :placeholder ">=" - :class "w-24" - :value (fc/field-value)}))) - (fc/with-field :transaction-rule/dom-lte - (com/validated-field - {:errors (fc/field-errors)} - (com/int-input {:name (fc/field-name) - :placeholder ">=" - :class "w-24" - :value (fc/field-value)})))]) + (com/field {:label "Amount"} + [:div.flex.gap-2 + (fc/with-field :transaction-rule/amount-gte + [:div.flex.flex-col + (com/money-input {:name (fc/field-name) + :placeholder ">=" + :class "w-24" + :value (fc/field-value)}) + (com/errors {:errors (fc/field-errors)})]) + (fc/with-field :transaction-rule/amount-lte + [:div.flex.flex-col + (com/money-input {:name (fc/field-name) + :placeholder "<=" + :class "w-24" + :value (fc/field-value)}) + (com/errors {:errors (fc/field-errors)})])]) - [:h2.text-lg "Outcomes"] - (fc/with-field :transaction-rule/vendor - (com/validated-field {:label "Assign Vendor" - :errors (fc/field-errors)} - [:div.w-96 - (com/typeahead-2 {:name (fc/field-name) - :placeholder "Search..." - :url (bidi/path-for ssr-routes/only-routes :vendor-search) - :id (str "form-vendor-search") - :value (fc/field-value) - :value-fn (some-fn :db/id identity) - :content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})])) + (com/field {:label "Day of month"} + [:div.flex.gap-2 + (fc/with-field :transaction-rule/dom-gte + (com/validated-field + {:errors (fc/field-errors)} + (com/int-input {:name (fc/field-name) + :placeholder ">=" + :class "w-24" + :value (fc/field-value)}))) + (fc/with-field :transaction-rule/dom-lte + (com/validated-field + {:errors (fc/field-errors)} + (com/int-input {:name (fc/field-name) + :placeholder ">=" + :class "w-24" + :value (fc/field-value)})))]) - (fc/with-field :transaction-rule/accounts - (list - (com/data-grid {:headers [(com/data-grid-header {} - "Account") - (com/data-grid-header {:class "w-32"} "Location") - (com/data-grid-header {:class "w-16"} "%") - (com/data-grid-header {:class "w-16"})] - :id "transaction-rule-account-table"} - (when @fc/*current* - (doall (for [tra fc/*current*] - (fc/with-cursor tra - (transaction-rule-account-row* entity tra)))))) - (com/errors {:errors (fc/field-errors)}))) - (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes - :admin-transaction-rule-new-account) - :hx-include "#edit-form" - :hx-ext "rename-params" - :hx-rename-params-ex (cheshire/generate-string {"transaction-rule/client" "client-id" - "index" "index"}) - :hx-vals (hiccup/raw "js:{index: countRows(\"#transaction-rule-account-table\")}") - :hx-target "#transaction-rule-account-table tbody" - :hx-swap "beforeend"} - "New account") - (fc/with-field :transaction-rule/transaction-approval-status - (com/validated-field {:label "Approval status" - :errors (fc/field-errors)} - (com/radio {:options (ref->radio-options "transaction-approval-status") - :value (fc/field-value) - :name (fc/field-name) - :orientation :horizontal}))) - - [:div#form-errors [:span.error-content - (com/errors {:errors (:errors fc/*form-errors*)})]] - (com/button {:color :primary :form "edit-form" :type "submit"} - "Save")])]] - [:div]))) + [:h2.text-lg "Outcomes"] + (fc/with-field :transaction-rule/vendor + (com/validated-field {:label "Assign Vendor" + :errors (fc/field-errors)} + [:div.w-96 + (com/typeahead-2 {:name (fc/field-name) + :placeholder "Search..." + :url (bidi/path-for ssr-routes/only-routes :vendor-search) + :id (str "form-vendor-search") + :value (fc/field-value) + :value-fn (some-fn :db/id identity) + :content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})])) + + (fc/with-field :transaction-rule/accounts + (list + (com/data-grid {:headers [(com/data-grid-header {} + "Account") + (com/data-grid-header {:class "w-32"} "Location") + (com/data-grid-header {:class "w-16"} "%") + (com/data-grid-header {:class "w-16"})] + :id "transaction-rule-account-table"} + (when @fc/*current* + (doall (for [tra fc/*current*] + (fc/with-cursor tra + (transaction-rule-account-row* entity tra)))))) + (com/errors {:errors (fc/field-errors)}))) + (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes + :admin-transaction-rule-new-account) + :hx-include "#edit-form" + :hx-ext "rename-params" + :hx-rename-params-ex (cheshire/generate-string {"transaction-rule/client" "client-id" + "index" "index"}) + :hx-vals (hiccup/raw "js:{index: countRows(\"#transaction-rule-account-table\")}") + :hx-target "#transaction-rule-account-table tbody" + :hx-swap "beforeend"} + "New account") + (fc/with-field :transaction-rule/transaction-approval-status + (com/validated-field {:label "Approval status" + :errors (fc/field-errors)} + (com/radio {:options (ref->radio-options "transaction-approval-status") + :value (fc/field-value) + :name (fc/field-name) + :orientation :horizontal}))) + + [:div#form-errors [:span.error-content + (com/errors {:errors (:errors fc/*form-errors*)})]] + (com/button {:color :primary :form "edit-form" :type "submit" :class "w-32"} + "Save")])]] + [:div]))) ;; TODO Should forms have some kind of helper to render an individual field? saving diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj index 4087c83c..937716be 100644 --- a/src/clj/auto_ap/ssr/components/dialog.clj +++ b/src/clj/auto_ap/ssr/components/dialog.clj @@ -1,16 +1,17 @@ (ns auto-ap.ssr.components.dialog - (:require [hiccup2.core :as hiccup])) + (:require [hiccup2.core :as hiccup] + [auto-ap.ssr.hx :as hx])) (defn modal- [params & children] - [:div {:class (str "relative w-full max-h-full " (or (:modal-class params) " max-w-2xl ")) - "@click.outside" "open=false"} - (into [:div#modal-content] - children)]) + [:div#modal-content {:class "flex items-center justify-between pb-2"} + children]) (defn modal-card- [params header content footer] [:div#modal-card params - [:div {:class "relative bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white fade-in-settle slide-up-settle duration-300 transition-all modal-content"} + [:div {:class "relative bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content"} [:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600"} header] [:div {:class "p-6 space-y-6"} content] [:div footer]]]) + +;; fade-in-settle slide-up-settle duration-300 transition-all diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj index a19199e6..6057270f 100644 --- a/src/clj/auto_ap/ssr/components/inputs.clj +++ b/src/clj/auto_ap/ssr/components/inputs.clj @@ -80,31 +80,30 @@ c.clearChoices(); :active 0 :elements (if (:value params) [{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}] - [])}) - } + [])})} [:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes) - (hh/add-class "cursor-pointer")) + (hh/add-class "cursor-pointer")) "@click.prevent.stop" "open = !open;" "@keydown.enter.prevent.stop" "open = !open;" - :x-init (:x-init params) - :tabindex 0} + :tabindex 0 + :x-init (:x-init params)} [:input (-> params (dissoc :class) (dissoc :value-fn) (dissoc :content-fn) - (dissoc :x-init) + (dissoc :placeholder) - (assoc - "x-ref" "hidden" - :type "hidden" - ":value" "value.value" - :x-init "$watch('value', v => $dispatch('change'))"))] - [:div.flex.w-full.justify-items-stretch + (assoc + "x-ref" "hidden" + :type "hidden" + ":value" "value.value" + :x-init (hiccup/raw (str "$watch('value', v => $dispatch('change')); "))))] + [:div.flex.w-full.justify-items-stretch [:span.flex-grow.text-left {"x-text" "value.label"}] [:div {:class "w-5 h-5 inline ml-1 justify-self-end"} svg/drop-down]]] - - [:ul.dropdown-contents {:class "absolute bg-white rounded-lg shadow-lg py-1 w-max z-10 mt-1" + + [:ul.dropdown-contents {:class "absolute bg-gray-50 dark:bg-gray-600 rounded-lg shadow-lg py-1 w-max z-10 mt-1" "@keydown.escape.window" "open = false" "x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200" "x-transition:enter-start" "!opacity-0 !mt-0" @@ -112,9 +111,9 @@ c.clearChoices(); "x-transition:leave" "ease-out duration-200" "x-transition:leave-start" "!opacity-1 !mt-1" "x-transition:leave-end" "!opacity-0 !mt-0" - "x-show ""open" + "x-show " "open" "x-trap" "open" - "@click.outside" "open=false"} + "@click.outside" "open=false; console.log('is this ihid')"} [:input {:type "text" :class (hh/add-class (or (:class params) "") default-input-classes) "x-model" "search" "placeholder" (:placeholder params) @@ -124,16 +123,15 @@ c.clearChoices(); "x-init" "$watch('search', s => { if($el.value.length > 2) {fetch(baseUrl + s).then(data=>data.json()).then(data => {elements = data; active=-1}) }})"}] [:div.dropdown-options [:template {:x-for "(element, index) in elements"} - [:li [:a {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-500" + [:li [:a {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-300 [&.active]:dark:bg-primary-700 text-gray-800 dark:text-gray-100" :href "#" ":class" "active == index ? 'active' : ''" "@mouseover" "active = index" "@mouseout" "active = -1" "@click.prevent" "value = element; open=false; " - "x-html" "element.label" - }]]] + "x-html" "element.label"}]]] [:template {:x-if "elements.length == 0"} - [:li {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-500 text-gray-500 text-xs "} + [:li {:class "px-4 py-2 flex gap-2 items-center outline-0 focus:bg-neutral-100 hover:bg-neutral-100 whitespace-nowrap [&.active]:bg-primary-500 text-gray-800 dark:text-gray-100 text-xs "} "No results found"]]]]]) diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj index 2564987f..7527004e 100644 --- a/src/clj/auto_ap/ssr/ui.clj +++ b/src/clj/auto_ap/ssr/ui.clj @@ -36,7 +36,6 @@ [:script {:type "text/javascript" :src "https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.1.4/dist/js/datepicker-full.min.js"}] - [:link {:rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/styles/choices.min.css"}] [:script {:src "https://cdn.jsdelivr.net/npm/choices.js@9.0.1/public/assets/scripts/choices.min.js"}] [:script {:src "https://unpkg.com/htmx.org/dist/ext/response-targets.js"}] @@ -55,46 +54,39 @@ input::-webkit-inner-spin-button { } input[type=number] { -moz-appearance:textfield; /* Firefox */ -} +} "] - " - - ] - [:body {:hx-ext "disable-submit" - "x-data" (hx/json {:modalOpen false})} + [:body {:hx-ext "disable-submit"} contents [:script {:src "/js/flowbite.min.js"}] - [:div - {"x-data" (hx/json {"open" false}) + [:div#modal-holder + {:tabindex "-1", :class "fixed top-0 left-0 z-[99] flex items-center justify-center w-screen h-screen" + "x-show" "open" + ":aria-hidden" "!open" + "x-data" (hx/json {"open" false}) "@modalopen.document" "open=true" "@modalclose.document" "open=false"} - - [:div#modal-holder - { :tabindex "-1", :class "fixed top-0 left-0 right-0 z-50 w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full flex justify-center" - ":class" "open ? '' : 'hidden'" - ":aria-hidden" "!open" - }] - [:div {:class " bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40" - ":class" "open ? '' : 'hidden'" + + [:div {:class "bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40" + "x-show" "open" ":aria-hidden" "!open" - }] - #_[:script {:lang "text/javascript"} - (hiccup/raw " - var modal_element = document.getElementById('modal-holder'); - var modal_options = { - placement: 'center', - backdrop: 'dynamic', - backdropClasess: 'bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40', - closable: false, - onOpen: function() { - htmx.trigger(document.getElementById('modal-holder'), 'modalOpened', {}); + "x-transition:enter" "duration-300" + "x-transition:enter-start" "!bg-opacity-0" + "x-transition:enter-end" "!bg-opacity-50" + "x-transition:leave" "duration-300" + "x-transition:leave-start" "!bg-opacity-50" + "x-transition:leave-end" "!bg-opacity-0"} - }, - onHide: function() { - htmx.trigger(document.getElementById('modal-holder'), 'modalClosed', {}); - }, - }; - var curModal = new Modal(modal_element, modal_options); -") + [:div.flex.place-items-center.place-content-center.w-full.h-full.p-12 + [:div {:class (str "w-full sm:max-w-4xl sm:rounded-lg overflow-scroll max-h-full sm:max-h-[80vh]") + "@click.outside" "open=false" + "x-trap.inert" "open" + "x-show" "open" + "x-transition:enter" "ease-out duration-300" + "x-transition:enter-start" "!bg-opacity-0 !translate-y-32" + "x-transition:enter-end" "!bg-opacity-100 !translate-y-0" + "x-transition:leave" "duration-300" + "x-transition:leave-start" "!opacity-100 !translate-y-0" + "x-transition:leave-end" "!opacity-0 !translate-y-32"} - ]]]])) + [:div#modal-content {:class "flex items-center justify-between pb-2"}]]]]]]])) diff --git a/src/cljc/auto_ap/extract-line-items-from-invoice.repl b/src/cljc/auto_ap/extract-line-items-from-invoice.repl new file mode 100644 index 00000000..a4c2cbd7 --- /dev/null +++ b/src/cljc/auto_ap/extract-line-items-from-invoice.repl @@ -0,0 +1,31 @@ +;; This buffer is for Clojure experiments and evaluation. + +;; Press C-j to evaluate the last expression. + +;; You can also press C-u C-j to evaluate the expression and pretty-print its result. + +(user/init-repl) + +(dc/q '[:find ?nc + :in $ ?c + :where + [?je :journal-entry/client ?c] + ] + [:client/code "NGOP"]) + + + + + +(->> + (:line-items (first (:line-item-groups (first p)))) + (map (fn [li] + (->> (:line-item-expense-fields li) + (map + (fn [field] + [(:text (:label-detection field)) (:text (:value-detection field))]) + ) + (filter first) + (into {})))) + (clojure.data.json/pprint)) +