From 8684a684712205324894723a776f9392816c9fb1 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Fri, 20 Oct 2023 13:56:59 -0700
Subject: [PATCH 01/34] stacked radios
---
resources/public/output.css | 8 ++++++++
.../auto_ap/ssr/admin/transaction_rules.clj | 9 ++++++++-
src/clj/auto_ap/ssr/components/radio.clj | 18 +++++++++++++-----
3 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index fd7ea057..5029ff16 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1404,6 +1404,10 @@ input:checked + .toggle-bg {
width: 100%;
}
+.w-auto {
+ width: auto;
+}
+
.max-w-2xl {
max-width: 42rem;
}
@@ -1444,6 +1448,10 @@ input:checked + .toggle-bg {
flex-shrink: 1;
}
+.shrink-0 {
+ flex-shrink: 0;
+}
+
.basis-1\/4 {
flex-basis: 25%;
}
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 17b95695..01fcbdca 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -546,7 +546,8 @@
:errors (fc/field-errors)}
(com/radio {:options (ref->radio-options "transaction-approval-status")
:value (fc/field-value)
- :name (fc/field-name)})))
+ :name (fc/field-name)
+ :orientation :horizontal})))
[:div#form-errors [:span.error-content
(com/errors {:errors (:errors fc/*form-errors*)})]]
@@ -554,6 +555,12 @@
"Save")])]]
[:div])))
+
+;; TODO Should forms have some kind of helper to render an individual field? saving
+;; could generate the entire form and swap if there are errors
+;; but also when you tab out it could call the same function, and just
+;; pull out the single field to swap
+
(defn new-account [{{:keys [client-id index]} :query-params}]
(let [index (or index 0) ;; TODO schema decode is not working
transaction-rule {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
diff --git a/src/clj/auto_ap/ssr/components/radio.clj b/src/clj/auto_ap/ssr/components/radio.clj
index a793a901..bd27c9bb 100644
--- a/src/clj/auto_ap/ssr/components/radio.clj
+++ b/src/clj/auto_ap/ssr/components/radio.clj
@@ -1,10 +1,15 @@
-(ns auto-ap.ssr.components.radio)
+(ns auto-ap.ssr.components.radio
+ (:require [auto-ap.ssr.hiccup-helper :as hh]))
-(defn radio- [{:keys [options name title size] :or {size :medium} selected-value :value}]
+(defn radio- [{:keys [options name title size orientation] :or {size :medium} selected-value :value}]
[:h3 {:class "mb-4 font-semibold text-gray-900 dark:text-white"} title]
- [:ul {:class "w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white"}
+ [:ul {:class (cond-> "w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white"
+ (= orientation :horizontal) (-> (hh/add-class "flex gap-8")
+ (hh/remove-wildcard ["w-" "rounded-lg" "border" "bg-"])))}
(for [{:keys [value content]} options]
- [:li {:class "w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600"}
+ [:li {:class (cond-> "w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600"
+ (= orientation :horizontal) (-> (hh/remove-wildcard ["w-full" "rounded-"])
+ (hh/add-class "w-auto shrink-0 block rounded-lg border border-gray-200 dark:border-gray-600 px-3")))}
[:div {:class "flex items-center pl-3"}
[:input (cond-> {:id (str "list-" name "-" value)
:type "radio",
@@ -25,4 +30,7 @@
(str " " "text-xs py-2")
(= size :medium)
- (str " " "text-sm py-3"))} content]]])])
+ (str " " "text-sm py-3")
+
+ (= orientation :horizontal)
+ (hh/remove-class "w-full"))} content]]])])
From ffcc43ba5e5894fa6ca30293100d6dcfe58138af Mon Sep 17 00:00:00 2001
From: Bryce
Date: Fri, 20 Oct 2023 17:52:15 -0700
Subject: [PATCH 02/34] alpine for dropdown.
---
resources/public/output.css | 85 +++++++++++++++++++
.../auto_ap/ssr/admin/transaction_rules.clj | 49 ++++++-----
src/clj/auto_ap/ssr/company.clj | 19 ++---
src/clj/auto_ap/ssr/components.clj | 1 +
src/clj/auto_ap/ssr/components/dialog.clj | 6 +-
src/clj/auto_ap/ssr/components/inputs.clj | 70 ++++++++++++++-
src/clj/auto_ap/ssr/svg.clj | 2 +-
src/clj/auto_ap/ssr/ui.clj | 32 ++++---
8 files changed, 215 insertions(+), 49 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 5029ff16..fc47979a 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1252,6 +1252,26 @@ input:checked + .toggle-bg {
margin-top: 1.25rem;
}
+.\!mt-0 {
+ margin-top: 0px !important;
+}
+
+.\!mt-3 {
+ margin-top: 0.75rem !important;
+}
+
+.mt-3 {
+ margin-top: 0.75rem;
+}
+
+.\!mt-1 {
+ margin-top: 0.25rem !important;
+}
+
+.ml-64 {
+ margin-left: 16rem;
+}
+
.block {
display: block;
}
@@ -1408,6 +1428,11 @@ input:checked + .toggle-bg {
width: auto;
}
+.w-max {
+ width: -moz-max-content;
+ width: max-content;
+}
+
.max-w-2xl {
max-width: 42rem;
}
@@ -1452,6 +1477,10 @@ input:checked + .toggle-bg {
flex-shrink: 0;
}
+.flex-grow {
+ flex-grow: 1;
+}
+
.basis-1\/4 {
flex-basis: 25%;
}
@@ -1622,6 +1651,10 @@ input:checked + .toggle-bg {
justify-content: space-between;
}
+.justify-items-stretch {
+ justify-items: stretch;
+}
+
.gap-1 {
gap: 0.25rem;
}
@@ -1714,6 +1747,22 @@ 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;
+}
+
+.justify-self-start {
+ justify-self: start;
+}
+
+.justify-self-end {
+ justify-self: end;
+}
+
.overflow-auto {
overflow: auto;
}
@@ -2326,6 +2375,10 @@ input:checked + .toggle-bg {
opacity: 1;
}
+.\!opacity-0 {
+ opacity: 0 !important;
+}
+
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -2354,6 +2407,10 @@ input:checked + .toggle-bg {
outline-style: solid;
}
+.outline-0 {
+ outline-width: 0px;
+}
+
.ring {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
@@ -2411,6 +2468,10 @@ input:checked + .toggle-bg {
transition-duration: 75ms;
}
+.duration-200 {
+ transition-duration: 200ms;
+}
+
.ease-in-out {
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -2419,6 +2480,10 @@ 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);
+}
+
.htmx-added .fade-in {
opacity: 0.0 !important;
}
@@ -2862,6 +2927,11 @@ input:checked + .toggle-bg {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
+.hover\:bg-neutral-100:hover {
+ --tw-bg-opacity: 1;
+ background-color: rgb(245 245 245 / var(--tw-bg-opacity));
+}
+
.hover\:text-blue-600:hover {
--tw-text-opacity: 1;
color: rgb(0 125 187 / var(--tw-text-opacity));
@@ -2910,6 +2980,11 @@ input:checked + .toggle-bg {
border-color: rgb(121 181 46 / var(--tw-border-opacity));
}
+.focus\:bg-neutral-100:focus {
+ --tw-bg-opacity: 1;
+ background-color: rgb(245 245 245 / var(--tw-bg-opacity));
+}
+
.focus\:text-green-700:focus {
--tw-text-opacity: 1;
color: rgb(73 109 28 / var(--tw-text-opacity));
@@ -3524,3 +3599,13 @@ input:checked + .toggle-bg {
padding-left: 16rem;
}
}
+
+.\[\&\.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));
+}
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 01fcbdca..d7b0cc0d 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -306,7 +306,7 @@
(or (get tempids (:db/id entity)) (:db/id entity)))]
(html-response
(row* identity updated-account {:flash? true})
- :headers {"hx-trigger" "modalClosing"
+ :headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#transaction-rule-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
@@ -330,7 +330,7 @@
(defn- account-typeahead*
[{:keys [name value client-id]}]
[:div.flex.flex-col
- (com/typeahead {:name name
+ (com/typeahead-2 {:name name
:placeholder "Search..."
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
:id name
@@ -408,6 +408,7 @@
:href "#"}
svg/x))))
+;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [ entity form-params form-errors]}]
(com/modal
{:modal-class "max-w-4xl"}
@@ -417,7 +418,8 @@
[:form#edit-form (merge {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms"
:hx-target "#modal-holder"
- :hx-target-400 "#form-errors .error-content"}
+ :hx-target-400 "#form-errors .error-content"
+ #_#_:x-trap "true"}
form-params)
[:fieldset {:class "hx-disable" :hx-disinherit "hx-target"}
@@ -433,17 +435,18 @@
{:label "Client"
:errors (fc/field-errors)}
[:div.w-96
- (com/typeahead {:name (fc/field-name)
- :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))})]))
+ (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/bank-account
@@ -510,13 +513,13 @@
(com/validated-field {:label "Assign Vendor"
:errors (fc/field-errors)}
[:div.w-96
- (com/typeahead {: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/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
@@ -609,7 +612,7 @@
(html-response (dialog* :entity entity
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))})
- :headers {"hx-trigger" "modalOpening"})))
+ :headers {"hx-trigger" "modalopen"})))
(defn transaction-rule-error [request]
(let [entity (some-> request :last-form)]
@@ -629,7 +632,7 @@
:form-errors {}
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))})
- :headers {"hx-trigger" "modalOpening"}))
+ :headers {"hx-trigger" "modalopen"}))
(def transaction-rule-schema (mc/schema
[:map
diff --git a/src/clj/auto_ap/ssr/company.clj b/src/clj/auto_ap/ssr/company.clj
index 3891bb3a..075bae63 100644
--- a/src/clj/auto_ap/ssr/company.clj
+++ b/src/clj/auto_ap/ssr/company.clj
@@ -95,7 +95,7 @@
selected-client-id)
:client/bank-accounts
(filter (fn [{:keys [bank-account/name]}]
- (str/includes? (str/upper-case name)
+ (str/includes? (or (some-> name str/upper-case) "")
(or (some-> query-params
(get "q")
str/upper-case)
@@ -108,15 +108,14 @@
(defn bank-account-typeahead* [{:keys [client-id name value]}]
(if client-id
- (com/typeahead {:name name
- :class "w-96"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes :bank-account-search
- :db/id client-id)
- :id (str "form-bank-account-search")
- :value value
- :value-fn (some-fn :db/id identity)
- :content-fn (some-fn :bank-account/name #(pull-attr (dc/db conn) :bank-account/name %))})
+ (com/typeahead-2 {:name name
+ :class "w-96"
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes :bank-account-search
+ :db/id client-id)
+ :value value
+ :value-fn (some-fn :db/id identity)
+ :content-fn (some-fn :bank-account/name #(pull-attr (dc/db conn) :bank-account/name %))})
[:span.text-xs.text-gray-500 "Please select a client before selecting a bank account."
[:input {:type "hidden"
:name name}]]))
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index e7f6782d..41fff258 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -31,6 +31,7 @@
(def hidden inputs/hidden-)
(def select inputs/select-)
(def typeahead inputs/typeahead-)
+(def typeahead-2 inputs/typeahead-2-)
(def field-errors inputs/field-errors-)
(def field inputs/field-)
(def validated-field inputs/validated-field-)
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index e6e2e99e..4087c83c 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -2,10 +2,10 @@
(:require [hiccup2.core :as hiccup]))
(defn modal- [params & children]
- [:div {:class (str "relative w-full max-h-full " (or (:modal-class params) " max-w-2xl "))}
+ [: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)]
- )
+ children)])
(defn modal-card- [params header content footer]
[:div#modal-card params
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index 02678df7..a19199e6 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -2,7 +2,9 @@
(:require
[hiccup2.core :as hiccup]
[auto-ap.ssr.hiccup-helper :as hh]
- [clojure.string :as str]))
+ [clojure.string :as str]
+ [auto-ap.ssr.svg :as svg]
+ [auto-ap.ssr.hx :as hx]))
(def default-input-classes
@@ -68,6 +70,72 @@ c.clearChoices();
(:url params)
))]])
+(defn typeahead-2- [params]
+ [:div {:x-data (hx/json {:open false
+ :baseUrl (if (str/includes? (:url params) "?")
+ (str (:url params) "&q=")
+ (str (:url params) "?q="))
+ :value {:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}
+ :search ""
+ :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"))
+ "@click.prevent.stop" "open = !open;"
+ "@keydown.enter.prevent.stop" "open = !open;"
+ :x-init (:x-init params)
+ :tabindex 0}
+ [: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
+ [: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"
+ "@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"
+ "x-transition:enter-end" "!opacity-1 !mt-1"
+ "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-trap" "open"
+ "@click.outside" "open=false"}
+ [:input {:type "text" :class (hh/add-class (or (:class params) "") default-input-classes)
+ "x-model" "search"
+ "placeholder" (:placeholder params)
+ "@keydown.down.prevent" "active ++; active = active >= elements.length - 1 ? elements.length - 1 : active"
+ "@keydown.up.prevent" "active --; active = active < 0 ? 0 : active"
+ "@keydown.enter.prevent" "open = false; value = elements.length > 0 ? $data.elements[active] : {'value': '', label: ''}; console.log('are we here')"
+ "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"
+ :href "#"
+ ":class" "active == index ? 'active' : ''"
+ "@mouseover" "active = index"
+ "@mouseout" "active = -1"
+ "@click.prevent" "value = element; open=false; "
+ "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 "}
+ "No results found"]]]]])
+
(defn use-size [size]
(if (= :small size)
diff --git a/src/clj/auto_ap/ssr/svg.clj b/src/clj/auto_ap/ssr/svg.clj
index 385bbc1b..077f0988 100644
--- a/src/clj/auto_ap/ssr/svg.clj
+++ b/src/clj/auto_ap/ssr/svg.clj
@@ -200,7 +200,7 @@
:stroke-linejoin "round"}]])
(def drop-down
- [:svg {:class "w-4 h-4 ml-2", :aria-hidden "true", :fill "none", :stroke "currentColor", :viewbox "0 0 24 24", :xmlns "http://www.w3.org/2000/svg"}
+ [:svg {:aria-hidden "true", :fill "none", :stroke "currentColor", :viewbox "0 0 24 24", :xmlns "http://www.w3.org/2000/svg"}
[:path {:stroke-linecap "round", :stroke-linejoin "round", :stroke-width "2", :d "M19 9l-7 7-7-7"}]])
(def download
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index 41ba3fe2..2564987f 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -1,6 +1,7 @@
(ns auto-ap.ssr.ui
(:require
- [hiccup2.core :as hiccup]))
+ [hiccup2.core :as hiccup]
+ [auto-ap.ssr.hx :as hx]))
(defn html-page [hiccup]
{:status 200
@@ -42,7 +43,8 @@
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js"}]
[:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
- #_[:script {:defer true :src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"}]
+ [:script {:defer true :src "https://cdn.jsdelivr.net/npm/@alpinejs/focus@3.x.x/dist/cdn.min.js"}]
+ [:script {:defer true :src "https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"}]
[:style
"
input::-webkit-outer-spin-button,
@@ -58,24 +60,32 @@ input[type=number] {
"
]
- [:body {:hx-ext "disable-submit"}
+ [:body {:hx-ext "disable-submit"
+ "x-data" (hx/json {:modalOpen false})}
contents
[:script {:src "/js/flowbite.min.js"}]
- [:div [: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 hidden"
- :aria-hidden true
- "_" (hiccup/raw "on \"modalClosed\" remove my children
- on \"modalOpening\" from call curModal.show()
- on \"modalClosing\" from call curModal.hide()")
+ [:div
+ {"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"
}]
- [:script {:lang "text/javascript"}
+ [:div {:class " bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40"
+ ":class" "open ? '' : 'hidden'"
+ ":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: true,
+ closable: false,
onOpen: function() {
htmx.trigger(document.getElementById('modal-holder'), 'modalOpened', {});
From 2fc9a7157727adbd1747e728dcc88290d22f8dd3 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Fri, 20 Oct 2023 22:23:47 -0700
Subject: [PATCH 03/34] vertical alignment
---
resources/public/output.css | 8 ++++++++
src/clj/auto_ap/ssr/admin/transaction_rules.clj | 10 +++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index fc47979a..8df77b4b 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1755,6 +1755,10 @@ input:checked + .toggle-bg {
place-self: end;
}
+.self-start {
+ align-self: flex-start;
+}
+
.justify-self-start {
justify-self: start;
}
@@ -2208,6 +2212,10 @@ input:checked + .toggle-bg {
vertical-align: baseline;
}
+.align-top {
+ vertical-align: top;
+}
+
.text-2xl {
font-size: 1.5rem;
line-height: 2rem;
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index d7b0cc0d..34928a2b 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -402,11 +402,11 @@
:value (some-> (fc/field-value)
(* 100 )
(long ))}))))))
- (com/data-grid-cell
- (com/a-icon-button
- {"_" (hiccup/raw "on click halt the event then transition the closest
's opacity to 0 then remove closest
")
- :href "#"}
- svg/x))))
+ (com/data-grid-cell {:class "align-top"}
+ (com/a-icon-button
+ {"_" (hiccup/raw "on click halt the event then transition the closest
's opacity to 0 then remove closest
")
+ :href "#"}
+ svg/x))))
;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [ entity form-params form-errors]}]
From aa14a310ab69d540fde455b3e00ca2151b358404 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sat, 21 Oct 2023 07:37:05 -0700
Subject: [PATCH 04/34] big ui improvemet
---
resources/public/output.css | 261 +++++++++++++---
.../auto_ap/ssr/admin/transaction_rules.clj | 281 +++++++++---------
src/clj/auto_ap/ssr/components/dialog.clj | 13 +-
src/clj/auto_ap/ssr/components/inputs.clj | 38 ++-
src/clj/auto_ap/ssr/ui.clj | 64 ++--
.../extract-line-items-from-invoice.repl | 31 ++
6 files changed, 438 insertions(+), 250 deletions(-)
create mode 100644 src/cljc/auto_ap/extract-line-items-from-invoice.repl
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))
+
From fc3634c6bd12e42c711ad5890f9e67ea2bc64585 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sat, 21 Oct 2023 12:43:01 -0700
Subject: [PATCH 05/34] does not change now.
---
resources/public/output.css | 208 +++++-------------
.../auto_ap/ssr/admin/transaction_rules.clj | 11 +-
src/clj/auto_ap/ssr/components/inputs.clj | 65 +++---
src/clj/auto_ap/ssr/ui.clj | 3 +-
4 files changed, 103 insertions(+), 184 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 15e78cd2..c83024f1 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1151,6 +1151,10 @@ input:checked + .toggle-bg {
margin: 1rem;
}
+.m-1 {
+ margin: 0.25rem;
+}
+
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
@@ -1176,29 +1180,6 @@ 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;
}
@@ -1279,16 +1260,24 @@ input:checked + .toggle-bg {
margin-top: 1.25rem;
}
-.\!mt-64 {
- margin-top: 16rem !important;
+.\!mt-0 {
+ margin-top: 0px !important;
}
-.\!mt-32 {
- margin-top: 8rem !important;
+.\!mt-3 {
+ margin-top: 0.75rem !important;
}
-.mr-5 {
- margin-right: 1.25rem;
+.mt-3 {
+ margin-top: 0.75rem;
+}
+
+.\!mt-1 {
+ margin-top: 0.25rem !important;
+}
+
+.ml-64 {
+ margin-left: 16rem;
}
.block {
@@ -1375,19 +1364,6 @@ 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;
}
@@ -1396,10 +1372,6 @@ input:checked + .toggle-bg {
max-height: 100%;
}
-.max-h-screen {
- max-height: 100vh;
-}
-
.w-1\/2 {
width: 50%;
}
@@ -1456,14 +1428,14 @@ input:checked + .toggle-bg {
width: 24rem;
}
-.w-auto {
- width: auto;
-}
-
.w-full {
width: 100%;
}
+.w-auto {
+ width: auto;
+}
+
.w-max {
width: -moz-max-content;
width: max-content;
@@ -1521,10 +1493,6 @@ input:checked + .toggle-bg {
flex-grow: 1;
}
-.grow-0 {
- flex-grow: 0;
-}
-
.basis-1\/4 {
flex-basis: 25%;
}
@@ -1574,16 +1542,6 @@ 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)) !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));
@@ -1683,10 +1641,6 @@ input:checked + .toggle-bg {
place-items: center;
}
-.content-center {
- align-content: center;
-}
-
.items-start {
align-items: flex-start;
}
@@ -1723,10 +1677,6 @@ input:checked + .toggle-bg {
justify-content: space-between;
}
-.justify-items-center {
- justify-items: center;
-}
-
.justify-items-stretch {
justify-items: stretch;
}
@@ -1823,6 +1773,26 @@ 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;
+}
+
+.self-center {
+ align-self: center;
+}
+
+.justify-self-start {
+ justify-self: start;
+}
+
.justify-self-end {
justify-self: end;
}
@@ -2124,11 +2094,6 @@ 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;
}
@@ -2137,18 +2102,14 @@ input:checked + .toggle-bg {
--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;
}
+.\!bg-opacity-50 {
+ --tw-bg-opacity: 0.5 !important;
+}
+
.p-1 {
padding: 0.25rem;
}
@@ -2237,16 +2198,6 @@ 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;
}
@@ -2479,10 +2430,6 @@ input:checked + .toggle-bg {
text-decoration-line: underline;
}
-.\!opacity-0 {
- opacity: 0 !important;
-}
-
.opacity-0 {
opacity: 0;
}
@@ -2491,8 +2438,8 @@ input:checked + .toggle-bg {
opacity: 1;
}
-.\!opacity-50 {
- opacity: 0.5 !important;
+.\!opacity-0 {
+ opacity: 0 !important;
}
.\!opacity-100 {
@@ -2576,10 +2523,6 @@ input:checked + .toggle-bg {
transition-duration: 100ms;
}
-.duration-200 {
- transition-duration: 200ms;
-}
-
.duration-300 {
transition-duration: 300ms;
}
@@ -2592,12 +2535,8 @@ input:checked + .toggle-bg {
transition-duration: 75ms;
}
-.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);
+.duration-200 {
+ transition-duration: 200ms;
}
.ease-in-out {
@@ -2608,8 +2547,8 @@ input:checked + .toggle-bg {
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
-.ease-in {
- transition-timing-function: cubic-bezier(0.4, 0, 1, 1);
+.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] {
+ transition-timing-function: cubic-bezier(.3,2.3,.6,1);
}
.htmx-added .fade-in {
@@ -3040,11 +2979,6 @@ 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));
@@ -3060,9 +2994,9 @@ input:checked + .toggle-bg {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
-.hover\:bg-gray-50:hover {
+.hover\:bg-neutral-100:hover {
--tw-bg-opacity: 1;
- background-color: rgb(249 250 251 / var(--tw-bg-opacity));
+ background-color: rgb(245 245 245 / var(--tw-bg-opacity));
}
.hover\:text-blue-600:hover {
@@ -3612,39 +3546,14 @@ input:checked + .toggle-bg {
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-h-\[90vh\] {
+ max-height: 90vh;
}
.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;
}
@@ -3770,6 +3679,11 @@ 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));
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index dbb4d10b..2e5d8353 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -424,7 +424,7 @@
[:fieldset {:class "hx-disable" :hx-disinherit "hx-target"}
(fc/start-form entity form-errors
- [:div.space-y-2
+ [:div.space-y-1
(when-let [id (:db/id entity)]
(com/hidden {:name "db/id"
:value id}))
@@ -551,8 +551,9 @@
:name (fc/field-name)
:orientation :horizontal})))
- [:div#form-errors [:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})]]
+ [:div#form-errors (when (:errors fc/*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])))
@@ -611,7 +612,7 @@
(html-response (dialog* :entity entity
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))})
- :headers {"hx-trigger" "modalopen"})))
+ :headers {"hx-trigger-after-settle" "modalopen"})))
(defn transaction-rule-error [request]
(let [entity (some-> request :last-form)]
@@ -631,7 +632,7 @@
:form-errors {}
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))})
- :headers {"hx-trigger" "modalopen"}))
+ :headers {"hx-trigger-after-settle" "modalopen"}))
(def transaction-rule-schema (mc/schema
[:map
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index 6057270f..af06787d 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -81,12 +81,14 @@ c.clearChoices();
: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"))
- "@click.prevent.stop" "open = !open;"
+ [:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
+ (hh/add-class "cursor-pointer"))
+ "@click.prevent" "open = !open;"
"@keydown.enter.prevent.stop" "open = !open;"
- :tabindex 0
- :x-init (:x-init params)}
+ "@keydown.down.prevent.stop" "open = true;"
+ "@keydown.backspace" "value = {value: '', label: '' }"
+ :tabindex 0
+ :x-init (:x-init params)}
[:input (-> params
(dissoc :class)
(dissoc :value-fn)
@@ -94,42 +96,43 @@ c.clearChoices();
(dissoc :placeholder)
(assoc
- "x-ref" "hidden"
- :type "hidden"
- ":value" "value.value"
- :x-init (hiccup/raw (str "$watch('value', v => $dispatch('change')); "))))]
+ "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"}
+ [:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
- [: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"
+
+ [: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" "open = false; value = {value: '', label: '' }"
+ "x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
"x-transition:enter-start" "!opacity-0 !mt-0"
- "x-transition:enter-end" "!opacity-1 !mt-1"
- "x-transition:leave" "ease-out duration-200"
+ "x-transition:enter-end" "!opacity-1 !mt-1"
+ "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-trap" "open"
- "@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)
- "@keydown.down.prevent" "active ++; active = active >= elements.length - 1 ? elements.length - 1 : active"
- "@keydown.up.prevent" "active --; active = active < 0 ? 0 : active"
+ "x-transition:leave-end" "!opacity-0 !mt-0"
+ "x-show " "open"
+ "x-trap" "open"
+ "@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)
+ "@keydown.down.prevent" "active ++; active = active >= elements.length - 1 ? elements.length - 1 : active"
+ "@keydown.up.prevent" "active --; active = active < 0 ? 0 : active"
"@keydown.enter.prevent" "open = false; value = elements.length > 0 ? $data.elements[active] : {'value': '', label: ''}; console.log('are we here')"
- "x-init" "$watch('search', s => { if($el.value.length > 2) {fetch(baseUrl + s).then(data=>data.json()).then(data => {elements = data; active=-1}) }})"}]
+ "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-300 [&.active]:dark:bg-primary-700 text-gray-800 dark:text-gray-100"
- :href "#"
- ":class" "active == index ? 'active' : ''"
- "@mouseover" "active = index"
- "@mouseout" "active = -1"
+ [: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-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 7527004e..a32ba532 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -78,8 +78,9 @@ input[type=number] {
"x-transition:leave-end" "!bg-opacity-0"}
[: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]")
+ [:div {:class (str "w-full sm:max-w-4xl sm:rounded-lg overflow-scroll max-h-full sm:max-h-[90vh]")
"@click.outside" "open=false"
+ "x-trap.inert.noscroll" "open"
"x-trap.inert" "open"
"x-show" "open"
"x-transition:enter" "ease-out duration-300"
From 9ddbd31cc8ddea1529cc6e23efc03ccb5eb5bb96 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sat, 21 Oct 2023 13:04:42 -0700
Subject: [PATCH 06/34] almost perfect user experience
---
resources/public/output.css | 9 ++++
.../auto_ap/ssr/admin/transaction_rules.clj | 45 ++++++++++---------
src/clj/auto_ap/ssr/components/buttons.clj | 17 ++++---
src/clj/auto_ap/ssr/components/radio.clj | 2 +-
src/clj/auto_ap/ssr/ui.clj | 2 +-
5 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index c83024f1..72b2faea 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -2094,6 +2094,11 @@ input:checked + .toggle-bg {
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
}
+.bg-gray-300 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
+}
+
.bg-opacity-50 {
--tw-bg-opacity: 0.5;
}
@@ -3554,6 +3559,10 @@ input:checked + .toggle-bg {
max-width: 56rem;
}
+ .sm\:max-w-2xl {
+ max-width: 42rem;
+ }
+
.sm\:rounded-lg {
border-radius: 0.5rem;
}
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 2e5d8353..50ddec11 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -55,11 +55,6 @@
;; as to which one to generate.
-;; TODO lots of escaping concerns (urls in javascript), all these weird name filters
-
-;; TODO better generation of names?
-
-
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
@@ -411,7 +406,7 @@
;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [entity form-params form-errors]}]
(com/modal
- {:modal-class "max-w-4xl"}
+ {:modal-class "max-w-2xl"}
(com/modal-card
{}
[:div.flex [:div.p-2 "Transaction Rule"]]
@@ -516,14 +511,14 @@
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
:id (str "form-vendor-search")
+ :class "w-96"
: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 {: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"})]
@@ -531,24 +526,33 @@
(when @fc/*current*
(doall (for [tra fc/*current*]
(fc/with-cursor tra
- (transaction-rule-account-row* entity tra))))))
+ (transaction-rule-account-row* entity tra)))))
+ (com/data-grid-row
+ {:class "new-row"}
+ (com/data-grid-cell {:colspan 4
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :color :secondary
+ :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 "#edit-form .new-row"
+ :hx-swap "beforebegin"}
+ "New account")])))
(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)
+ :size :small
:orientation :horizontal})))
[:div#form-errors (when (:errors fc/*form-errors*)
@@ -568,7 +572,7 @@
(let [index (or index 0) ;; TODO schema decode is not working
transaction-rule {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
client-id)
- :transaction-rule/accounts (conj (into [] (repeat (inc index) {} ))
+ :transaction-rule/accounts (conj (into [] (repeat index {} ))
{:db/id (str (java.util.UUID/randomUUID))
:transaction-rule-account/location "Shared"})}]
(html-response
@@ -582,7 +586,6 @@
;; TODO check to see if it should be called "Shared" or "shared" for the value
-;; TODO blank location is being allowed
;; TODO hydrate nested types more easily. make it easy to hydrate so you don't do weird sometimes pulls
;; TODO is it possible to make it easy to get a virtual cursor in the case of adding a new row? setting up
;; fake data doesn't feel right - maybe have a "prelude" that's dynamic
diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj
index 40574e20..9edd6529 100644
--- a/src/clj/auto_ap/ssr/components/buttons.clj
+++ b/src/clj/auto_ap/ssr/components/buttons.clj
@@ -98,13 +98,16 @@
(into [:div.htmx-indicator-hidden.inline-flex.gap-2.items-center.justify-center] children)])
(defn a-button- [params & children]
- [:a (update params
- :class #(cond-> %
- true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center")
- (= :secondary (:color params)) (str " text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
- (= :primary (:color params)) (str " text-white bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")
- (nil? (:color params))
- (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")))
+ [:a (-> params
+ (update :class #(cond-> %
+ true (str " focus:ring-4 font-bold rounded-lg text-xs p-3 text-center mr-2 inline-flex items-center hover:scale-105 transition duration-100 justify-center")
+ (= :secondary (:color params)) (str " text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700")
+ (= :primary (:color params)) (str " text-white bg-green-500 hover:bg-green-600 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 ")
+ (nil? (:color params))
+ (str " bg-white dark:bg-gray-600 border-gray-300 dark:border-gray-700 text-gray-500 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-100 font-medium border border-gray-300 dark:border-gray-700")
+ ))
+ (assoc :tabindex 0)
+ (assoc :href (:href params "#")))
[:div.htmx-indicator.flex.items-center
(svg/spinner {:class "inline w-4 h-4 text-white"})
[:div.ml-3 "Loading..."]]
diff --git a/src/clj/auto_ap/ssr/components/radio.clj b/src/clj/auto_ap/ssr/components/radio.clj
index bd27c9bb..17d9bf95 100644
--- a/src/clj/auto_ap/ssr/components/radio.clj
+++ b/src/clj/auto_ap/ssr/components/radio.clj
@@ -4,7 +4,7 @@
(defn radio- [{:keys [options name title size orientation] :or {size :medium} selected-value :value}]
[:h3 {:class "mb-4 font-semibold text-gray-900 dark:text-white"} title]
[:ul {:class (cond-> "w-48 text-sm font-medium text-gray-900 bg-white border border-gray-200 rounded-lg dark:bg-gray-700 dark:border-gray-600 dark:text-white"
- (= orientation :horizontal) (-> (hh/add-class "flex gap-8")
+ (= orientation :horizontal) (-> (hh/add-class "flex gap-2 flex-wrap")
(hh/remove-wildcard ["w-" "rounded-lg" "border" "bg-"])))}
(for [{:keys [value content]} options]
[:li {:class (cond-> "w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600"
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index a32ba532..d2ef40b1 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -78,7 +78,7 @@ input[type=number] {
"x-transition:leave-end" "!bg-opacity-0"}
[: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-[90vh]")
+ [:div {:class (str "w-full sm:max-w-2xl sm:rounded-lg overflow-scroll max-h-full sm:max-h-[90vh]")
"@click.outside" "open=false"
"x-trap.inert.noscroll" "open"
"x-trap.inert" "open"
From 34f4a12b2e7b86b77ac5e10a7609fa3f045573a3 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sat, 21 Oct 2023 13:25:00 -0700
Subject: [PATCH 07/34] Makes appear logic work right
---
.../auto_ap/ssr/admin/transaction_rules.clj | 159 ++++++++++--------
src/clj/auto_ap/ssr/components/inputs.clj | 3 +-
src/clj/auto_ap/ssr/components/radio.clj | 6 +-
src/clj/auto_ap/ssr/form_cursor.clj | 5 +-
src/clj/auto_ap/ssr/hx.clj | 6 +
5 files changed, 107 insertions(+), 72 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 50ddec11..99963ce0 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -423,84 +423,109 @@
(when-let [id (:db/id entity)]
(com/hidden {:name "db/id"
:value id}))
-
- (fc/with-field :transaction-rule/client
-
- (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/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)})]))
-
(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?)
+ :error? (fc/error?)
+ :x-init "$el.focus()"
:placeholder "HOME DEPOT"
:class "w-96"
:value (fc/field-value)})))
+ [:div.filters {:x-data (hx/json {:clientFilter (boolean (fc/field-value (:transaction-rule/client fc/*current*)))
+ :bankAccountFilter (boolean (fc/field-value (:transaction-rule/bank-account fc/*current*)))
+ :amountFilter (boolean (or (fc/field-value (:transaction-rule/amount-gte fc/*current*))
+ (fc/field-value (:transaction-rule/amount-lte fc/*current*))))
+ :domFilter (boolean (or (fc/field-value (:transaction-rule/dom-gte fc/*current*))
+ (fc/field-value (:transaction-rule/dom-lte fc/*current*))))})}
- (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)
+ [:div.flex.gap-2.mb-2
+ (com/a-button {"@click" "clientFilter=true"
+ "x-show" "!clientFilter"} "Filter client")
+ (com/a-button {"@click" "bankAccountFilter=true"
+ "x-show" "clientFilter && !bankAccountFilter"} "Filter bank account")
+ (com/a-button {"@click" "amountFilter=true"
+ "x-show" "!amountFilter"} "Filter amount")
+ (com/a-button {"@click" "domFilter=true"
+ "x-show" "!domFilter"} "Filter day of month")]
+ (fc/with-field :transaction-rule/client
+
+ (com/validated-field
+ (-> {:label "Client"
+ :errors (fc/field-errors)
+ :x-show "clientFilter"}
+ (hx/alpine-appear))
+ [:div.w-96
+ (com/typeahead-2 {:name (fc/field-name)
+ :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/bank-account
+ (com/validated-field
+ (-> {:label "Bank Account"
+ :errors (fc/field-errors)
+ :x-show "bankAccountFilter"}
+ hx/alpine-appear)
+ [: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"
+ :x-show "amountFilter"}
+ hx/alpine-appear)
+ [: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)})])])
+
+ (com/field (-> {:label "Day of month"
+ :x-show "domFilter"}
+ hx/alpine-appear)
+ [: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)})
- (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 "<="
+ :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/errors {:errors (fc/field-errors)})])])
-
- (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)})))])
+ :value (fc/field-value)})))])]
[:h2.text-lg "Outcomes"]
(fc/with-field :transaction-rule/vendor
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index af06787d..e1de230a 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -193,7 +193,8 @@ c.clearChoices();
[:p.mt-2.text-xs.text-red-600.dark:text-red-500.h-4 (str/join ", " errors)]))
(defn field- [params & rest]
- [:div {:id (:id params) :class (hh/add-class "group" (:class params))}
+ [:div (-> params
+ (update :class #(hh/add-class (or % "") "group" )))
(when (:label params)
[:label {:class "block mb-2 text-sm font-medium text-gray-900 dark:text-white"} (:label params)])
rest
diff --git a/src/clj/auto_ap/ssr/components/radio.clj b/src/clj/auto_ap/ssr/components/radio.clj
index 17d9bf95..e02dc4d5 100644
--- a/src/clj/auto_ap/ssr/components/radio.clj
+++ b/src/clj/auto_ap/ssr/components/radio.clj
@@ -1,5 +1,6 @@
(ns auto-ap.ssr.components.radio
- (:require [auto-ap.ssr.hiccup-helper :as hh]))
+ (:require [auto-ap.ssr.hiccup-helper :as hh]
+ [auto-ap.ssr.hx :as hx]))
(defn radio- [{:keys [options name title size orientation] :or {size :medium} selected-value :value}]
[:h3 {:class "mb-4 font-semibold text-gray-900 dark:text-white"} title]
@@ -10,7 +11,8 @@
[:li {:class (cond-> "w-full border-b border-gray-200 rounded-t-lg dark:border-gray-600"
(= orientation :horizontal) (-> (hh/remove-wildcard ["w-full" "rounded-"])
(hh/add-class "w-auto shrink-0 block rounded-lg border border-gray-200 dark:border-gray-600 px-3")))}
- [:div {:class "flex items-center pl-3"}
+ [:div {:class (cond-> "flex items-center"
+ (not= orientation :horizontal) (hh/add-class "pl-3"))}
[:input (cond-> {:id (str "list-" name "-" value)
:type "radio",
:value value
diff --git a/src/clj/auto_ap/ssr/form_cursor.clj b/src/clj/auto_ap/ssr/form_cursor.clj
index 1170afc0..eef97db2 100644
--- a/src/clj/auto_ap/ssr/form_cursor.clj
+++ b/src/clj/auto_ap/ssr/form_cursor.clj
@@ -26,8 +26,9 @@
([cursor]
(apply path->name2 (cursor/path cursor))))
-(defn field-value []
- @*current*)
+(defn field-value
+ ([] (field-value *current*))
+ ([cursor] @cursor))
(defn field-errors
([]
diff --git a/src/clj/auto_ap/ssr/hx.clj b/src/clj/auto_ap/ssr/hx.clj
index d5c59d85..cb5e5c00 100644
--- a/src/clj/auto_ap/ssr/hx.clj
+++ b/src/clj/auto_ap/ssr/hx.clj
@@ -18,3 +18,9 @@
(defn triggers [& triggers]
(str/join ", " triggers))
+
+(defn alpine-appear [m]
+ (assoc m
+ "x-transition:enter" "transition duration-500"
+ "x-transition:enter-start" "opacity-0"
+ "x-transition:enter-end" "opacity-100"))
From 998d29690e3c3bde5ebf94f6105f1cfa75c32054 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sat, 21 Oct 2023 20:08:08 -0700
Subject: [PATCH 08/34] animates with shake
---
resources/public/output.css | 215 ++++++++----------
.../auto_ap/ssr/admin/transaction_rules.clj | 122 +++++-----
src/clj/auto_ap/ssr/components/inputs.clj | 6 +-
tailwind.config.js | 16 ++
4 files changed, 178 insertions(+), 181 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 72b2faea..a0cad0e2 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1147,14 +1147,14 @@ input:checked + .toggle-bg {
grid-column-start: 1;
}
-.m-4 {
- margin: 1rem;
-}
-
.m-1 {
margin: 0.25rem;
}
+.m-4 {
+ margin: 1rem;
+}
+
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
@@ -1180,6 +1180,14 @@ input:checked + .toggle-bg {
margin-bottom: 1rem;
}
+.\!mt-0 {
+ margin-top: 0px !important;
+}
+
+.\!mt-1 {
+ margin-top: 0.25rem !important;
+}
+
.-mb-1 {
margin-bottom: -0.25rem;
}
@@ -1260,26 +1268,6 @@ input:checked + .toggle-bg {
margin-top: 1.25rem;
}
-.\!mt-0 {
- margin-top: 0px !important;
-}
-
-.\!mt-3 {
- margin-top: 0.75rem !important;
-}
-
-.mt-3 {
- margin-top: 0.75rem;
-}
-
-.\!mt-1 {
- margin-top: 0.25rem !important;
-}
-
-.ml-64 {
- margin-left: 16rem;
-}
-
.block {
display: block;
}
@@ -1352,10 +1340,6 @@ input:checked + .toggle-bg {
height: 24rem;
}
-.h-\[calc\(100\%-1rem\)\] {
- height: calc(100% - 1rem);
-}
-
.h-full {
height: 100%;
}
@@ -1428,14 +1412,14 @@ 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;
@@ -1497,6 +1481,16 @@ input:checked + .toggle-bg {
flex-basis: 25%;
}
+.\!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-x-1\/2 {
--tw-translate-x: -50%;
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));
@@ -1532,16 +1526,6 @@ 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;
-}
-
.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));
@@ -1565,6 +1549,48 @@ input:checked + .toggle-bg {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
+@keyframes shake {
+ 0% {
+ transform: translateX(0px);
+ }
+
+ 12.5% {
+ transform: translateX(-5px);
+ }
+
+ 25% {
+ transform: translateX(0px);
+ }
+
+ 37.5% {
+ transform: translateX(5px);
+ }
+
+ 50% {
+ transform: translateX(0px);
+ }
+
+ 62.5% {
+ transform: translateX(-5px);
+ }
+
+ 75% {
+ transform: translateX(5px);
+ }
+
+ 87.5% {
+ transform: translateX(5px);
+ }
+
+ 100% {
+ transform: translateX(0px);
+ }
+}
+
+.animate-shake {
+ animation: shake 0.5s ease-out 1;
+}
+
@keyframes spin {
to {
transform: rotate(360deg);
@@ -1773,26 +1799,10 @@ 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;
-}
-
.self-center {
align-self: center;
}
-.justify-self-start {
- justify-self: start;
-}
-
.justify-self-end {
justify-self: end;
}
@@ -1817,10 +1827,6 @@ input:checked + .toggle-bg {
overflow-y: auto;
}
-.overflow-x-hidden {
- overflow-x: hidden;
-}
-
.truncate {
overflow: hidden;
text-overflow: ellipsis;
@@ -2094,15 +2100,6 @@ input:checked + .toggle-bg {
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
}
-.bg-gray-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(209 213 219 / var(--tw-bg-opacity));
-}
-
-.bg-opacity-50 {
- --tw-bg-opacity: 0.5;
-}
-
.\!bg-opacity-0 {
--tw-bg-opacity: 0 !important;
}
@@ -2115,10 +2112,18 @@ input:checked + .toggle-bg {
--tw-bg-opacity: 0.5 !important;
}
+.bg-opacity-50 {
+ --tw-bg-opacity: 0.5;
+}
+
.p-1 {
padding: 0.25rem;
}
+.p-12 {
+ padding: 3rem;
+}
+
.p-2 {
padding: 0.5rem;
}
@@ -2139,10 +2144,6 @@ input:checked + .toggle-bg {
padding: 1.5rem;
}
-.p-12 {
- padding: 3rem;
-}
-
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
@@ -2426,23 +2427,10 @@ 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;
-}
-
-.opacity-100 {
- opacity: 1;
-}
-
.\!opacity-0 {
opacity: 0 !important;
}
@@ -2451,6 +2439,14 @@ input:checked + .toggle-bg {
opacity: 1 !important;
}
+.opacity-0 {
+ opacity: 0;
+}
+
+.opacity-100 {
+ opacity: 1;
+}
+
.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -2528,6 +2524,10 @@ input:checked + .toggle-bg {
transition-duration: 100ms;
}
+.duration-200 {
+ transition-duration: 200ms;
+}
+
.duration-300 {
transition-duration: 300ms;
}
@@ -2540,8 +2540,8 @@ input:checked + .toggle-bg {
transition-duration: 75ms;
}
-.duration-200 {
- transition-duration: 200ms;
+.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] {
+ transition-timing-function: cubic-bezier(.3,2.3,.6,1);
}
.ease-in-out {
@@ -2552,10 +2552,6 @@ 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);
-}
-
.htmx-added .fade-in {
opacity: 0.0 !important;
}
@@ -2984,6 +2980,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));
@@ -2999,11 +3000,6 @@ input:checked + .toggle-bg {
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
-.hover\:bg-neutral-100:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(245 245 245 / var(--tw-bg-opacity));
-}
-
.hover\:text-blue-600:hover {
--tw-text-opacity: 1;
color: rgb(0 125 187 / var(--tw-text-opacity));
@@ -3547,18 +3543,10 @@ input:checked + .toggle-bg {
display: block;
}
- .sm\:max-h-\[80vh\] {
- max-height: 80vh;
- }
-
.sm\:max-h-\[90vh\] {
max-height: 90vh;
}
- .sm\:max-w-4xl {
- max-width: 56rem;
- }
-
.sm\:max-w-2xl {
max-width: 42rem;
}
@@ -3583,10 +3571,6 @@ input:checked + .toggle-bg {
}
@media (min-width: 768px) {
- .md\:inset-0 {
- inset: 0px;
- }
-
.md\:ml-2 {
margin-left: 0.5rem;
}
@@ -3688,9 +3672,9 @@ input:checked + .toggle-bg {
}
}
-.\[\&\.active\]\:bg-red-500.active {
+.\[\&\.active\]\:bg-primary-300.active {
--tw-bg-opacity: 1;
- background-color: rgb(255 3 3 / var(--tw-bg-opacity));
+ background-color: rgb(175 211 130 / var(--tw-bg-opacity));
}
.\[\&\.active\]\:bg-primary-500.active {
@@ -3698,11 +3682,6 @@ input:checked + .toggle-bg {
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 99963ce0..4b285630 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -47,7 +47,8 @@
[hiccup2.core :as hiccup]
[iol-ion.query :refer [ident]]
[malli.core :as mc]
- [auto-ap.cursor :as cursor]))
+ [auto-ap.cursor :as cursor]
+ [auto-ap.ssr.hiccup-helper :as hh]))
;; TODO with dependencies, I really don't like that you have to be ultra specific in what
;; you want to include, and generating the routes and interconnection is weird too.
@@ -310,25 +311,26 @@
[{:keys [ name account-location client-locations value]}]
(com/select {:options (into [["" ""]]
(cond account-location
- [[account-location account-location]]
+ [[account-location account-location]]
- (seq client-locations)
- (into [["Shared" "Shared"]]
- (for [cl client-locations]
- [cl cl]))
- :else
- [["Shared" "Shared"]]))
- :name name
+ (seq client-locations)
+ (into [["Shared" "Shared"]]
+ (for [cl client-locations]
+ [cl cl]))
+ :else
+ [["Shared" "Shared"]]))
+ :name name
:value value
:class "w-full"}))
(defn- account-typeahead*
- [{:keys [name value client-id]}]
+ [{:keys [name value client-id x-model]}]
[:div.flex.flex-col
(com/typeahead-2 {:name name
:placeholder "Search..."
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
:id name
+ :x-model x-model
:value value
:value-fn (some-fn :db/id identity)
:content-fn (fn [value]
@@ -338,9 +340,11 @@
(defn- transaction-rule-account-row*
[transaction-rule account]
- (com/data-grid-row {}
+ (com/data-grid-row {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
+ (fc/field-value (:transaction-rule-account/account account)))})}
(let [account-name (fc/field-name (:transaction-rule-account/account account))]
(list
+
(fc/with-field :db/id
(com/hidden {:name (fc/field-name)
:value (fc/field-value)}))
@@ -349,44 +353,34 @@
{}
(com/validated-field
{:errors (fc/field-errors)}
- [:div {:hx-trigger (hx/trigger-field-change :name "transaction-rule/client"
- :from "#edit-form")
- :hx-include "#edit-form"
- :hx-vals (hx/vals {:name account-name})
- :hx-ext "rename-params"
- :hx-rename-params-ex (hx/json {:transaction-rule/client "client-id"
- :name "name"
- account-name "value"})
- :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
- :hx-swap "innerHTML"}
- (account-typeahead* {:value (fc/field-value)
- :client-id (:db/id (:transaction-rule/client transaction-rule))
- :name (fc/field-name)})])))
+ [:div {:hx-trigger "changed"
+ :hx-target "next div"
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
+ :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+ (account-typeahead* {:value (fc/field-value)
+ :client-id (:db/id (:transaction-rule/client transaction-rule))
+ :name (fc/field-name)
+ :x-model "accountId"
+ }))))
(fc/with-field :transaction-rule-account/location
(com/data-grid-cell
{}
(com/validated-field
- {:errors (fc/field-errors)}
- [:div [:div {:hx-trigger (hx/triggers
- (hx/trigger-field-change :name "transaction-rule/client"
- :from "#edit-form")
- (hx/trigger-field-change :name account-name
- :from "#edit-form"))
- :hx-include "#edit-form"
- :hx-vals (hx/vals {:name (fc/field-name)})
- :hx-ext "rename-params"
- :hx-rename-params-ex (hx/json {"transaction-rule/client" "client-id"
- account-name "account-id"
- "name" "name"
- (fc/field-name) "value"})
- :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
- :hx-swap "innerHTML"}
- (location-select* {:name (fc/field-name)
- :account-location (:account/location (cond->> (:transaction-rule-account/account @account)
- (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
- '[:account/location])))
- :client-locations (:client/locations (:transaction-rule/client transaction-rule))
- :value (fc/field-value)})]])))
+ {:errors (fc/field-errors)
+ :x-data (hx/json {:location (fc/field-value)})}
+ [:div {:hx-trigger "changed"
+ :hx-target "next *"
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
+ :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data))"}]
+ (location-select* {:name (fc/field-name)
+ :account-location (:account/location (cond->> (:transaction-rule-account/account @account)
+ (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
+ '[:account/location])))
+ :client-locations (:client/locations (:transaction-rule/client transaction-rule))
+ :hx-model "location"
+ :value (fc/field-value)}))))
(fc/with-field :transaction-rule-account/percentage
(com/data-grid-cell
{}
@@ -414,9 +408,12 @@
:hx-swap "outerHTML swap:300ms"
:hx-target "#modal-holder"
:hx-target-400 "#form-errors .error-content"
- :x-trap "true"}
+ :x-trap "true"
+ :class "group/form"}
form-params)
- [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"}
+ [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"
+ :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
+ (:transaction-rule/client entity))})}
(fc/start-form entity form-errors
[:div.space-y-1
@@ -461,7 +458,7 @@
:class "w-96"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :company-search)
- :id (str "form-client-search")
+ :x-model "clientId"
:value (fc/field-value)
:value-fn (some-fn :db/id identity)
:content-fn (fn [c] (cond->> c
@@ -472,23 +469,23 @@
(com/validated-field
(-> {:label "Bank Account"
:errors (fc/field-errors)
- :x-show "bankAccountFilter"}
+ :x-show "bankAccountFilter"
+ }
hx/alpine-appear)
- [: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"})}
+ [:div.w-96
+ [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead)
+ :hx-trigger "changed"
+ :hx-target "next *"
+ :hx-include "#bank-account-changer"
+ :hx-swap "innerHTML"
+
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+
(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"
:x-show "amountFilter"}
hx/alpine-appear)
@@ -557,7 +554,6 @@
(com/data-grid-cell {:colspan 4
:class "bg-gray-100"}
[:div.flex.justify-center
-
(com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-new-account)
:color :secondary
@@ -583,7 +579,9 @@
[:div#form-errors (when (:errors fc/*form-errors*)
[:span.error-content
(com/errors {:errors (:errors fc/*form-errors*)})])]
- (com/button {:color :primary :form "edit-form" :type "submit" :class "w-32"}
+ (com/button {:color :primary :form "edit-form" :type "submit" :class (cond-> "w-32"
+ (seq form-errors) (->
+ (hh/add-class "animate-shake")))}
"Save")])]]
[:div])))
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index e1de230a..fa9b8f88 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -80,7 +80,10 @@ c.clearChoices();
:active 0
:elements (if (:value params)
[{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}]
- [])})}
+ [])})
+ :x-modelable "value.value"
+ :x-model (:x-model params)
+ }
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
"@click.prevent" "open = !open;"
@@ -95,6 +98,7 @@ c.clearChoices();
(dissoc :content-fn)
(dissoc :placeholder)
+ (dissoc :x-model)
(assoc
"x-ref" "hidden"
:type "hidden"
diff --git a/tailwind.config.js b/tailwind.config.js
index b2056c91..dc5cc907 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -5,6 +5,22 @@ module.exports = {
"./node_modules/flowbite/**/*.js"],
theme: {
extend: {
+ "keyframes": {
+ shake: {
+ '0%': { transform: 'translateX(0px)' },
+ '12.5%': { transform: 'translateX(-5px)' },
+ '25%': { transform: 'translateX(0px)' },
+ '37.5%': { transform: 'translateX(5px)' },
+ '50%': { transform: 'translateX(0px)' },
+ '62.5%': { transform: 'translateX(-5px)' },
+ '75%': { transform: 'translateX(5px)' },
+ '87.5%': { transform: 'translateX(5px)' },
+ '100%': { transform: 'translateX(0px)' },
+ },
+ },
+ animation: {
+ 'shake': 'shake 0.5s ease-out 1',
+ },
"fontFamily": {
"sans": ["Calibri", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"]
From a6032e2be296e42a440613e05660fffe3c89075a Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 06:27:55 -0700
Subject: [PATCH 09/34] progress on updating users
---
resources/public/output.css | 4 +
.../auto_ap/ssr/admin/transaction_rules.clj | 179 +++++++++---------
src/clj/auto_ap/ssr/components/dialog.clj | 8 +-
src/clj/auto_ap/ssr/components/inputs.clj | 16 +-
src/clj/auto_ap/ssr/users.clj | 7 +-
5 files changed, 109 insertions(+), 105 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index a0cad0e2..6b7c19ec 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1356,6 +1356,10 @@ input:checked + .toggle-bg {
max-height: 100%;
}
+.max-h-\[90vh\] {
+ max-height: 90vh;
+}
+
.w-1\/2 {
width: 50%;
}
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 4b285630..40911e8a 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -59,19 +59,19 @@
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-table)
+ :admin-transaction-rule-table)
"hx-target" "#transaction-rule-table"
"hx-indicator" "#transaction-rule-table"}
- [:fieldset.space-y-6
+ [:fieldset.space-y-6
(com/field {:label "Vendor"}
- (com/typeahead {:name "vendor"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :vendor-search)
- :id (str "vendor-search")
- :value [(:db/id (:vendor (:parsed-query-params request)))
- (:vendor/name (:vendor (:parsed-query-params request)))]}))
+ (com/typeahead-2 {:name "vendor"
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :vendor-search)
+ :id (str "vendor-search")
+ :value [(:db/id (:vendor (:parsed-query-params request)))
+ (:vendor/name (:vendor (:parsed-query-params request)))]}))
(com/field {:label "Note"}
(com/text-input {:name "note"
:id "note"
@@ -193,7 +193,7 @@
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-new-dialog))
:hx-target "#modal-content"
- :hx-swap "innerHTML"
+ :hx-swap "outerHTML"
:color :primary}
"New Transaction Rule")])
:row-buttons (fn [request entity]
@@ -201,7 +201,7 @@
:admin-transaction-rule-edit-dialog
:db/id (:db/id entity)))
:hx-target "#modal-content"
- :hx-swap "innerHTML"}
+ :hx-swap "outerHTML"}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -220,7 +220,8 @@
{:key "bank-account"
:name "Bank account"
:sort-key "bank-account"
- :render #(-> % :transaction-rule/bank-account :bank-account/name)}
+ :render #(-> % :transaction-rule/bank-account :bank-account/name)
+ :show-starting "lg"}
{:key "description"
:name "Description"
:sort-key "description"
@@ -233,7 +234,8 @@
(com/pill {:color :red} (format "more than $%.2f" amount-gte)))
(when amount-lte
- (com/pill {:color :primary} (format "less than $%.2f" amount-lte)))])}
+ (com/pill {:color :primary} (format "less than $%.2f" amount-lte)))])
+ :show-starting "md"}
{:key "note"
:name "Note"
:sort-key "note"
@@ -401,16 +403,17 @@
(defn dialog* [& {:keys [entity form-params form-errors]}]
(com/modal
{:modal-class "max-w-2xl"}
- (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"
- :class "group/form"}
- form-params)
+
+ [: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"
+ :class "group/form"}
+ form-params)
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "Transaction Rule"]]
[:fieldset {:class "hx-disable" :hx-disinherit "hx-target"
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
(:transaction-rule/client entity))})}
@@ -448,43 +451,42 @@
(fc/with-field :transaction-rule/client
(com/validated-field
- (-> {:label "Client"
- :errors (fc/field-errors)
- :x-show "clientFilter"}
- (hx/alpine-appear))
- [:div.w-96
- (com/typeahead-2 {:name (fc/field-name)
- :error? (fc/error?)
- :class "w-96"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes :company-search)
- :x-model "clientId"
- :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))})]))
+ (-> {:label "Client"
+ :errors (fc/field-errors)
+ :x-show "clientFilter"}
+ (hx/alpine-appear))
+ [:div.w-96
+ (com/typeahead-2 {:name (fc/field-name)
+ :error? (fc/error?)
+ :class "w-96"
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes :company-search)
+ :x-model "clientId"
+ :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/bank-account
(com/validated-field
- (-> {:label "Bank Account"
- :errors (fc/field-errors)
- :x-show "bankAccountFilter"
- }
- hx/alpine-appear)
- [:div.w-96
- [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead)
- :hx-trigger "changed"
- :hx-target "next *"
- :hx-include "#bank-account-changer"
- :hx-swap "innerHTML"
+ (-> {:label "Bank Account"
+ :errors (fc/field-errors)
+ :x-show "bankAccountFilter"}
+ hx/alpine-appear)
+ [:div.w-96
+ [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead)
+ :hx-trigger "changed"
+ :hx-target "next *"
+ :hx-include "#bank-account-changer"
+ :hx-swap "innerHTML"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
- :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
-
- (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity))
- :name (fc/field-name)
- :value (fc/field-value)})]))
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+
+ (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"
:x-show "amountFilter"}
@@ -511,18 +513,18 @@
[: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)})))
+ {: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)})))])]
+ {:errors (fc/field-errors)}
+ (com/int-input {:name (fc/field-name)
+ :placeholder ">="
+ :class "w-24"
+ :value (fc/field-value)})))])]
[:h2.text-lg "Outcomes"]
(fc/with-field :transaction-rule/vendor
@@ -549,24 +551,24 @@
(doall (for [tra fc/*current*]
(fc/with-cursor tra
(transaction-rule-account-row* entity tra)))))
- (com/data-grid-row
- {:class "new-row"}
- (com/data-grid-cell {:colspan 4
- :class "bg-gray-100"}
- [:div.flex.justify-center
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-new-account)
- :color :secondary
- :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 "#edit-form .new-row"
- :hx-swap "beforebegin"}
- "New account")])))
+ (com/data-grid-row
+ {:class "new-row"}
+ (com/data-grid-cell {:colspan 4
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :color :secondary
+ :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 "#edit-form .new-row"
+ :hx-swap "beforebegin"}
+ "New account")])))
(com/errors {:errors (fc/field-errors)})))
-
+
(fc/with-field :transaction-rule/transaction-approval-status
(com/validated-field {:label "Approval status"
:errors (fc/field-errors)}
@@ -578,12 +580,11 @@
[:div#form-errors (when (:errors fc/*form-errors*)
[:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})])]
- (com/button {:color :primary :form "edit-form" :type "submit" :class (cond-> "w-32"
- (seq form-errors) (->
- (hh/add-class "animate-shake")))}
- "Save")])]]
- [:div])))
+ (com/errors {:errors (:errors fc/*form-errors*)})])]])]
+ [:div (com/button {:color :primary :form "edit-form" :type "submit" :class (cond-> "w-32"
+ (seq form-errors) (->
+ (hh/add-class "animate-shake")))}
+ "Save")])]))
;; 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 937716be..f4ae762d 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -3,15 +3,15 @@
[auto-ap.ssr.hx :as hx]))
(defn modal- [params & children]
- [:div#modal-content {:class "flex items-center justify-between pb-2"}
+ [:div#modal-content {:class ""}
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 modal-content"}
+ [:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full"}
[: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"}
+ [:div {:class "p-6 space-y-6 overflow-scroll "}
content]
- [:div footer]]])
+ (when footer [:div {:class "p-4 "} 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 fa9b8f88..480854f1 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -77,13 +77,12 @@ c.clearChoices();
(str (:url params) "?q="))
:value {:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}
:search ""
- :active 0
- :elements (if (:value params)
+ :active -1
+ :elements (if ((:value-fn params first) (:value params))
[{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}]
[])})
:x-modelable "value.value"
- :x-model (:x-model params)
- }
+ :x-model (:x-model params)}
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
"@click.prevent" "open = !open;"
@@ -100,16 +99,15 @@ c.clearChoices();
(dissoc :placeholder)
(dissoc :x-model)
(assoc
- "x-ref" "hidden"
- :type "hidden"
- ":value" "value.value"
- :x-init (hiccup/raw (str "$watch('value', v => $dispatch('change')); "))))]
+ "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-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
-
[: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" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index d1ba7b58..2e4df1ac 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -206,7 +206,7 @@
(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:user-edit-dialog
:db/id (:db/id entity)))
- :hx-target "#modal-holder"
+ :hx-target "#modal-content"
:hx-swap "outerHTML"}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
@@ -265,7 +265,7 @@
(html-response
(row* identity user {:flash? true})
- :headers {"hx-trigger" "closeModal"
+ :headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#user-table tr[data-id=\"%d\"]" (:db/id user))})))
(defn user-edit-dialog [request]
@@ -315,7 +315,8 @@
[:div#form-errors [:span.error-content]]
(com/button {:color :primary :type "submit"}
"Save")]
- [:div])]]))))
+ [:div])]])
+ :headers {"hx-trigger" "modalopen"})))
(def key->handler
(apply-middleware-to-all-handlers
From fc0392a235d757159520bdfc7b2e50ec4e2d9fa5 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 21:00:04 -0700
Subject: [PATCH 10/34] improvements
---
resources/public/output.css | 71 ++++++++++++++++
src/clj/auto_ap/ssr/admin/accounts.clj | 81 +++++++++++--------
.../auto_ap/ssr/admin/transaction_rules.clj | 9 +--
src/clj/auto_ap/ssr/components.clj | 1 +
src/clj/auto_ap/ssr/components/buttons.clj | 16 +++-
src/clj/auto_ap/ssr/components/dialog.clj | 25 ++++--
src/clj/auto_ap/ssr/components/inputs.clj | 3 +-
src/clj/auto_ap/ssr/ui.clj | 28 +++----
src/clj/auto_ap/ssr/users.clj | 19 ++---
9 files changed, 179 insertions(+), 74 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 6b7c19ec..96983899 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1348,6 +1348,19 @@ input:checked + .toggle-bg {
height: 100vh;
}
+.h-64 {
+ height: 16rem;
+}
+
+.h-min {
+ height: -moz-min-content;
+ height: min-content;
+}
+
+.h-\[90vh\] {
+ height: 90vh;
+}
+
.max-h-96 {
max-height: 24rem;
}
@@ -1360,6 +1373,14 @@ input:checked + .toggle-bg {
max-height: 90vh;
}
+.max-h-\[100vh\] {
+ max-height: 100vh;
+}
+
+.max-h-\[80vh\] {
+ max-height: 80vh;
+}
+
.w-1\/2 {
width: 50%;
}
@@ -1433,6 +1454,23 @@ input:checked + .toggle-bg {
width: 100vw;
}
+.w-min {
+ width: -moz-min-content;
+ width: min-content;
+}
+
+.w-8\/12 {
+ width: 66.666667%;
+}
+
+.w-6\/12 {
+ width: 50%;
+}
+
+.w-1\/4 {
+ width: 25%;
+}
+
.max-w-2xl {
max-width: 42rem;
}
@@ -1457,6 +1495,10 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
+.max-w-xs {
+ max-width: 20rem;
+}
+
.flex-1 {
flex: 1 1 0%;
}
@@ -1481,6 +1523,10 @@ input:checked + .toggle-bg {
flex-grow: 1;
}
+.grow {
+ flex-grow: 1;
+}
+
.basis-1\/4 {
flex-basis: 25%;
}
@@ -1671,6 +1717,10 @@ input:checked + .toggle-bg {
place-items: center;
}
+.content-center {
+ align-content: center;
+}
+
.items-start {
align-items: flex-start;
}
@@ -1819,6 +1869,10 @@ input:checked + .toggle-bg {
overflow: hidden;
}
+.overflow-visible {
+ overflow: visible;
+}
+
.overflow-scroll {
overflow: scroll;
}
@@ -1831,6 +1885,10 @@ input:checked + .toggle-bg {
overflow-y: auto;
}
+.overflow-y-scroll {
+ overflow-y: scroll;
+}
+
.truncate {
overflow: hidden;
text-overflow: ellipsis;
@@ -2208,6 +2266,11 @@ input:checked + .toggle-bg {
padding-bottom: 1.25rem;
}
+.px-6 {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+}
+
.pb-2 {
padding-bottom: 0.5rem;
}
@@ -3543,6 +3606,10 @@ input:checked + .toggle-bg {
}
@media (min-width: 640px) {
+ .sm\:m-12 {
+ margin: 3rem;
+ }
+
.sm\:block {
display: block;
}
@@ -3563,6 +3630,10 @@ input:checked + .toggle-bg {
padding: 1.5rem;
}
+ .sm\:p-12 {
+ padding: 3rem;
+ }
+
.sm\:py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 895921b0..f3657e02 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -21,8 +21,8 @@
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers
entity-id
- forced-vector
html-response
+ many-entity
map->db-id-decoder
ref->enum-schema
ref->select-options
@@ -135,16 +135,16 @@
:action-buttons (fn [request]
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-new-dialog))
- :hx-target "#modal-holder"
- :hx-swap "outerHTML"
+ :hx-target "#modal-content"
+ :hx-swap "innerHTML"
:color :primary}
"New Account")])
:row-buttons (fn [request entity]
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-edit-dialog
:db/id (:db/id entity)))
- :hx-target "#modal-holder"
- :hx-swap "outerHTML"}
+ :hx-target "#modal-content"
+ :hx-swap "innerHTML"}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -207,22 +207,26 @@
"account_client_override_id" (:db/id o)})))
(html-response
(row* identity updated-account {:flash? true})
- :headers {"hx-trigger" "closeModal"
+ :headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#account-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
+;; TODO use cursor
+;; TODO index based list not dbid
-(defn client-override* [override]
+(defn client-override* [override index]
[:div.flex.gap-2.mb-2.client-override
[:div.w-96
- (com/typeahead {:name (format "account/client-overrides[%s][account-client-override/client]" (:db/id override))
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id (str "account-client-override-" (:db/id override))
- :value [(:db/id (:account-client-override/client override))
- (:client/name (:account-client-override/client override))]})]
+ (com/hidden {:name (format "account/client-overrides[%s][db/id]" index)
+ :value (:db/id override)})
+ (com/typeahead-2 {:name (format "account/client-overrides[%s][account-client-override/client]" index)
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :id (str "account-client-override-" (:db/id override))
+ :value [(:db/id (:account-client-override/client override))
+ (:client/name (:account-client-override/client override))]})]
[:div.w-96
- (com/text-input {:name (format "account/client-overrides[%s][account-client-override/name]" (:db/id override))
+ (com/text-input {:name (format "account/client-overrides[%s][account-client-override/name]" index)
:class "w-full"
:value (:account-client-override/name override)})]
[:div (com/a-icon-button {"_" (hiccup/raw "on click halt the event then transition the closest <.client-override />'s opacity to 0 then remove closest <.client-override />") } svg/x)]])
@@ -230,7 +234,7 @@
(defn dialog* [& {:keys [ account form-params]}]
(com/modal
- {:modal-class "max-w-4xl"}
+ {}
[:form#edit-form (merge {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content"}
@@ -282,33 +286,37 @@
:options (ref->select-options "account-applicability")}))
(com/field {:label "Client Overrides" :id "client-overrides"}
- (for [override (:account/client-overrides account)]
- (client-override* override)))
+ (for [[override index] (map vector (:account/client-overrides account) (range))]
+ (client-override* override index)))
(com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-account-client-override-new)
- :hx-target "#client-overrides"
- :hx-swap "beforeend"}
+ :admin-account-client-override-new)
+ :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
+ :hx-target "#client-overrides"
+ :hx-swap "beforeend"}
"New override")
[:div#form-errors [:span.error-content]]
- (com/button {:color :primary :form "edit-form" :type "submit"}
- "Save")]
- [:div])]]))
+ ]
+ (com/validated-save-button {:errors []}
+ "Save account"))]]))
-(defn new-client-override [_]
+(defn new-client-override [{ {:keys [index]} :query-params}]
(html-response
- (client-override* {:db/id (str (java.util.UUID/randomUUID))})))
+ (client-override* {:db/id (str (java.util.UUID/randomUUID))}
+ index)))
(defn account-edit-dialog [request]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
(html-response (dialog* :account account
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
- :admin-account-edit-save))}))))
+ :admin-account-edit-save))})
+ :headers {"hx-trigger" "modalopen"})))
(defn account-new-dialog [_]
(html-response (dialog* :account nil
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :admin-account-new-save))})))
+ :admin-account-new-save))})
+ :headers {"hx-trigger" "modalopen"}))
(def account-schema (mc/schema
[:map
@@ -320,20 +328,23 @@
[:account/applicability (ref->enum-schema "account-applicability")]
[:account/invoice-allowance (ref->enum-schema "allowance")]
[:account/vendor-allowance (ref->enum-schema "allowance")]
- [:account/client-overrides {:decode/json map->db-id-decoder
- :optional true}
+ [:account/client-overrides {:optional true}
[:maybe
- (forced-vector [:map
- [:db/id [:or entity-id temp-id]]
- [:account-client-override/client [:or entity-id :string]]
- [:account-client-override/name :string]])]]]))
+ (many-entity {}
+ [:db/id [:or entity-id temp-id]]
+ [:account-client-override/client [:or entity-id :string]]
+ [:account-client-override/name :string])]]]))
(def key->handler
(apply-middleware-to-all-handlers
(->>
{:admin-accounts (helper/page-route grid-page)
:admin-account-table (helper/table-route grid-page)
- :admin-account-client-override-new (-> new-client-override wrap-admin wrap-client-redirect-unauthenticated)
+ :admin-account-client-override-new (-> new-client-override
+ (wrap-schema-decode :query-schema [:map
+ [:index {:optional true
+ :default 0} [nat-int? {:default 0}]]])
+ wrap-admin wrap-client-redirect-unauthenticated)
:admin-account-save (-> account-save
(wrap-schema-decode :form-schema account-schema)
(wrap-nested-form-params)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 40911e8a..ffe7a84f 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -193,7 +193,7 @@
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-new-dialog))
:hx-target "#modal-content"
- :hx-swap "outerHTML"
+ :hx-swap "innerHTML"
:color :primary}
"New Transaction Rule")])
:row-buttons (fn [request entity]
@@ -201,7 +201,7 @@
:admin-transaction-rule-edit-dialog
:db/id (:db/id entity)))
:hx-target "#modal-content"
- :hx-swap "outerHTML"}
+ :hx-swap "innerHTML"}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -581,10 +581,7 @@
[:div#form-errors (when (:errors fc/*form-errors*)
[:span.error-content
(com/errors {:errors (:errors fc/*form-errors*)})])]])]
- [:div (com/button {:color :primary :form "edit-form" :type "submit" :class (cond-> "w-32"
- (seq form-errors) (->
- (hh/add-class "animate-shake")))}
- "Save")])]))
+ (com/validated-save-button {:errors form-errors} "Save rule"))]))
;; TODO Should forms have some kind of helper to render an individual field? saving
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index 41fff258..cee70ef2 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -15,6 +15,7 @@
(def breadcrumbs breadcrumbs/breadcrumbs-)
(def button buttons/button-)
+(def validated-save-button buttons/validated-save-button-)
(def a-button buttons/a-button-)
(def button-icon buttons/button-icon-)
(def icon-button buttons/icon-button-)
diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj
index 9edd6529..076945f9 100644
--- a/src/clj/auto_ap/ssr/components/buttons.clj
+++ b/src/clj/auto_ap/ssr/components/buttons.clj
@@ -1,5 +1,6 @@
(ns auto-ap.ssr.components.buttons
- (:require [auto-ap.ssr.svg :as svg]))
+ (:require [auto-ap.ssr.svg :as svg]
+ [auto-ap.ssr.hiccup-helper :as hh]))
(defn button-icon- [_ i]
[:div.h-4.w-4 i])
@@ -170,3 +171,16 @@
:hx-on:click "this.querySelector(\"input\").value = event.target.value; this.querySelector(\"input\").dispatchEvent(new Event('change', {bubbles: true}));"}
[:input {:type "hidden" :name name}]]
children)))
+
+
+(defn validated-save-button- [{:keys [errors class] :as params} & children]
+ (button- (-> {:color :primary :form "edit-form"
+ :type "submit" :class (cond-> (or class "")
+ true (hh/add-class "w-32")
+ (seq errors) (hh/add-class "animate-shake"))}
+ (merge params)
+ (dissoc :errors))
+ (if (seq children)
+ children
+ "Save"))
+ )
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index f4ae762d..d2109e35 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -1,17 +1,26 @@
(ns auto-ap.ssr.components.dialog
(:require [hiccup2.core :as hiccup]
- [auto-ap.ssr.hx :as hx]))
+ [auto-ap.ssr.hx :as hx]
+ [auto-ap.ssr.hiccup-helper :as hh]))
(defn modal- [params & children]
- [:div#modal-content {:class ""}
- children])
+ [:div {:class (-> (:class params)
+ (or "max-w-4xl w-1/4 overflow-visible")
+ (hh/add-class "h-min"))
+ "@click.outside" "open=false"
+ } children])
(defn modal-card- [params header content footer]
- [:div#modal-card params
- [:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full"}
- [: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 overflow-scroll "}
+ [:div#modal-card (update params
+ :class (fn [c] (-> c
+ (or "w-full")
+ )))
+ [:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col max-h-[80vh]"}
+ [:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
+ [:div {:class "px-6 space-y-6 overflow-y-scroll w-full shrink"}
+ #_[:div.bg-green-300.w-full.h-64
+ "hello"]
content]
- (when footer [:div {:class "p-4 "} footer])]])
+ (when footer [:div {:class "p-4 shrink-0"} 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 480854f1..2704c2b6 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -82,7 +82,8 @@ c.clearChoices();
[{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}]
[])})
:x-modelable "value.value"
- :x-model (:x-model params)}
+ :x-model (:x-model params)
+ :class "relative"}
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
"@click.prevent" "open = !open;"
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index d2ef40b1..3cccfa40 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -77,17 +77,17 @@ input[type=number] {
"x-transition:leave-start" "!bg-opacity-50"
"x-transition:leave-end" "!bg-opacity-0"}
- [:div.flex.place-items-center.place-content-center.w-full.h-full.p-12
- [:div {:class (str "w-full sm:max-w-2xl sm:rounded-lg overflow-scroll max-h-full sm:max-h-[90vh]")
- "@click.outside" "open=false"
- "x-trap.inert.noscroll" "open"
- "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"}]]]]]]]))
+ ;; TODO to get this right i think what needs to happen is to just set this up as having a single
+ ;; div that is forced to the maximum allowed size. inside that will be a div that just centers
+ ;; the elements, allowing it to grow as necessar. Then make the modal on the inside of this
+ ;; div just use flexbox to make the inside part be the part that scrolls
+ [:div#modal-content {:class (str "inset-0 max-h-[80vh] sm:m-12 flex justify-center items-center shrink h-full")
+ "x-trap.inert.noscroll" "open"
+ "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"}]]]]]))
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 2e4df1ac..aad8b8f5 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -71,13 +71,13 @@
{:value "none"
:content "None"}]}))
(com/field {:label "Client"}
- (com/typeahead {:name "client"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id (str "client-search")
- :value [(:db/id (:client (:parsed-query-params request)))
- (:client/name (:client (:parsed-query-params request)))]}))]])
+ (com/typeahead-2 {:name "client"
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :id (str "client-search")
+ :value [(:db/id (:client (:parsed-query-params request)))
+ (:client/name (:client (:parsed-query-params request)))]}))]])
(def default-read '[:db/id
:user/name
@@ -207,7 +207,7 @@
:user-edit-dialog
:db/id (:db/id entity)))
:hx-target "#modal-content"
- :hx-swap "outerHTML"}
+ :hx-swap "innerHTML"}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -281,7 +281,8 @@
:user-edit-save
:request-method :put))
:hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
+ :hx-target-400 "#form-errors .error-content"
+ :class "w-full"}
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
From bd1d603eb62ab1c72b60a165f0cb85c0f0c641f6 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 21:07:58 -0700
Subject: [PATCH 11/34] submit buttons
---
resources/public/output.css | 33 ---------
src/clj/auto_ap/ssr/admin/accounts.clj | 2 +-
src/clj/auto_ap/ssr/users.clj | 95 +++++++++++++-------------
3 files changed, 48 insertions(+), 82 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 96983899..73530dec 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1357,10 +1357,6 @@ input:checked + .toggle-bg {
height: min-content;
}
-.h-\[90vh\] {
- height: 90vh;
-}
-
.max-h-96 {
max-height: 24rem;
}
@@ -1373,10 +1369,6 @@ input:checked + .toggle-bg {
max-height: 90vh;
}
-.max-h-\[100vh\] {
- max-height: 100vh;
-}
-
.max-h-\[80vh\] {
max-height: 80vh;
}
@@ -1454,19 +1446,6 @@ input:checked + .toggle-bg {
width: 100vw;
}
-.w-min {
- width: -moz-min-content;
- width: min-content;
-}
-
-.w-8\/12 {
- width: 66.666667%;
-}
-
-.w-6\/12 {
- width: 50%;
-}
-
.w-1\/4 {
width: 25%;
}
@@ -1495,10 +1474,6 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
-.max-w-xs {
- max-width: 20rem;
-}
-
.flex-1 {
flex: 1 1 0%;
}
@@ -1717,10 +1692,6 @@ input:checked + .toggle-bg {
place-items: center;
}
-.content-center {
- align-content: center;
-}
-
.items-start {
align-items: flex-start;
}
@@ -3630,10 +3601,6 @@ input:checked + .toggle-bg {
padding: 1.5rem;
}
- .sm\:p-12 {
- padding: 3rem;
- }
-
.sm\:py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index f3657e02..6978f1d5 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -296,7 +296,7 @@
"New override")
[:div#form-errors [:span.error-content]]
]
- (com/validated-save-button {:errors []}
+ (com/validated-save-button {:errors []} ;; TODO
"Save account"))]]))
(defn new-client-override [{ {:keys [index]} :query-params}]
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index aad8b8f5..2b327f95 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -270,54 +270,53 @@
(defn user-edit-dialog [request]
(let [user (some-> request
- :route-params
- :db/id
- (#(dc/pull (dc/db conn) default-read %)))]
- (html-response
- (com/modal
- {}
- [:form {:hx-ext "response-targets"
- :hx-put (str (bidi/path-for ssr-routes/only-routes
- :user-edit-save
- :request-method :put))
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"
- :class "w-full"}
- [:fieldset {:class "hx-disable"}
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "User"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:user/name user)]]
- [:div.space-y-6
- (com/hidden {:name "db/id"
- :value (:db/id user)})
- (com/field {:label "Role"}
- (com/select {:name "user/role"
- :class "w-36"
- :autofocus true
- :id "role"
- :value (name (:user/role user))
- :options [["none" "None"]
- ["power-user" "Power user"]
- ["manager" "Manager"]
- ["admin" "Admin"]
- ["user" "User"]]}))
- (com/field {:label "Clients"}
- (com/typeahead {:name "user/clients"
- :class "w-full"
- :multiple "multiple"
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id "clients"
- :value (map
- (fn [client]
- [(:db/id client) (:client/name client)])
- (:user/clients user))
- :size :small}))
- [:div#form-errors [:span.error-content]]
- (com/button {:color :primary :type "submit"}
- "Save")]
- [:div])]])
- :headers {"hx-trigger" "modalopen"})))
+ :route-params
+ :db/id
+ (#(dc/pull (dc/db conn) default-read %)))]
+ (html-response
+ (com/modal
+ {}
+ [:form {:hx-ext "response-targets"
+ :hx-put (str (bidi/path-for ssr-routes/only-routes
+ :user-edit-save
+ :request-method :put))
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :class "w-full"}
+ [:fieldset {:class "hx-disable"}
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "User"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:user/name user)]]
+ [:div.space-y-6
+ (com/hidden {:name "db/id"
+ :value (:db/id user)})
+ (com/field {:label "Role"}
+ (com/select {:name "user/role"
+ :class "w-36"
+ :autofocus true
+ :id "role"
+ :value (name (:user/role user))
+ :options [["none" "None"]
+ ["power-user" "Power user"]
+ ["manager" "Manager"]
+ ["admin" "Admin"]
+ ["user" "User"]]}))
+ (com/field {:label "Clients"}
+ (com/typeahead {:name "user/clients"
+ :class "w-full"
+ :multiple "multiple"
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :id "clients"
+ :value (map
+ (fn [client]
+ [(:db/id client) (:client/name client)])
+ (:user/clients user))
+ :size :small}))
+ [:div#form-errors [:span.error-content]]]
+ (com/validated-save-button {:errors []} ;; TODO
+ "Save user"))]])
+ :headers {"hx-trigger" "modalopen"})))
(def key->handler
(apply-middleware-to-all-handlers
From 76760b7bcfed5fab52438bb87fb4f7f24f956456 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 21:32:36 -0700
Subject: [PATCH 12/34] progress for accounts
---
src/clj/auto_ap/ssr/admin/accounts.clj | 189 ++++++++++--------
.../auto_ap/ssr/admin/transaction_rules.clj | 6 +-
2 files changed, 112 insertions(+), 83 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 6978f1d5..28ddfc5e 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -34,7 +34,8 @@
[clojure.string :as str]
[datomic.api :as dc]
[hiccup2.core :as hiccup]
- [malli.core :as mc]))
+ [malli.core :as mc]
+ [auto-ap.ssr.form-cursor :as fc]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
@@ -213,96 +214,122 @@
;; TODO use cursor
;; TODO index based list not dbid
-(defn client-override* [override index]
+(defn client-override* [override]
[:div.flex.gap-2.mb-2.client-override
[:div.w-96
- (com/hidden {:name (format "account/client-overrides[%s][db/id]" index)
- :value (:db/id override)})
- (com/typeahead-2 {:name (format "account/client-overrides[%s][account-client-override/client]" index)
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id (str "account-client-override-" (:db/id override))
- :value [(:db/id (:account-client-override/client override))
- (:client/name (:account-client-override/client override))]})]
- [:div.w-96
- (com/text-input {:name (format "account/client-overrides[%s][account-client-override/name]" index)
- :class "w-full"
- :value (:account-client-override/name override)})]
- [:div (com/a-icon-button {"_" (hiccup/raw "on click halt the event then transition the closest <.client-override />'s opacity to 0 then remove closest <.client-override />") } svg/x)]])
+ (fc/with-field :db/id
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)}))
+ (fc/with-field :account-client-override/client
+ (com/typeahead-2 {:name (fc/field-name)
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :value (fc/field-value)
+ :value-fn :db/id ;; TODO hydration something here
+ :content-fn :client/name}))]
+ (fc/with-field :account-client-override/name
+ [:div.w-96
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)})])
+ [:div (com/a-icon-button {"_" (hiccup/raw "on click halt the event then transition the closest <.client-override />'s opacity to 0 then remove closest <.client-override />")} svg/x)]])
+
+;; TODO each form:
+;; elimante typeahead1
+;; work with new dialog
+;; use cursor
+;; ensure all dialogs are opened the same way
+;; form level validation
+;; form level validation
+;; componentize
+;; ensure all dependency oriented stuff works the same way
+;; make sure that "new row index" stuff works ok
-(defn dialog* [& {:keys [ account form-params]}]
+(defn dialog* [& {:keys [account form-params form-errors]}]
(com/modal
- {}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
- form-params)
- [:fieldset {:class "hx-disable"}
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "Account"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:account/numeric-code account) " - " (:account/name account)]]
- [:div.space-y-6
- (when-let [id (:db/id account)]
- (com/hidden {:name "db/id"
- :value id}))
-
- (when (nil? account)
- (com/field {:label "Numeric code"}
- (com/text-input {:name "account/numeric-code"
- :autofocus true
- :class "w-32"})))
- (com/field {:label "Name"}
- (com/text-input {:name "account/name"
- :autofocus true
- :class "w-32"
- :value (:account/name account)}))
- (com/field {:label "Account Type"}
- (com/select {:name "account/type"
- :class "w-36"
- :id "type"
- :value (some-> account :account/type name)
- :options (ref->select-options "account-type")}))
- (com/field {:label "Location"}
- (com/text-input {:name "account/location"
- :class "w-16"
- :value (:account/location account)}))
+ {}
+ [:form#edit-form (merge {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"}
+ form-params)
+ [:fieldset {:class "hx-disable"}
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "Account"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:account/numeric-code account) " - " (:account/name account)]]
- (com/field {:label "Invoice Allowance"}
- (com/select {:name "account/invoice-allowance"
- :value (some-> account :account/invoice-allowance name)
- :class "w-36"
- :options (ref->select-options "allowance")}))
- (com/field {:label "Vendor Allowance"}
- (com/select {:name "account/vendor-allowance"
- :class "w-36"
- :value (some-> account :account/vendor-allowance name)
- :options (ref->select-options "allowance")}))
- (com/field {:label "Applicability"}
- (com/select {:name "account/applicability"
- :class "w-36"
- :value (some-> account :account/applicability name)
- :options (ref->select-options "account-applicability")}))
+ (fc/start-form
+ account form-errors
+ [:div.space-y-1
+ (when-let [id (:db/id account)]
+ (com/hidden {:name "db/id"
+ :value id}))
- (com/field {:label "Client Overrides" :id "client-overrides"}
- (for [[override index] (map vector (:account/client-overrides account) (range))]
- (client-override* override index)))
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-account-client-override-new)
- :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
- :hx-target "#client-overrides"
- :hx-swap "beforeend"}
- "New override")
- [:div#form-errors [:span.error-content]]
- ]
- (com/validated-save-button {:errors []} ;; TODO
- "Save account"))]]))
+ (fc/with-field :account/numeric-code
+ (when (nil? (fc/field-value))
+ (com/field {:label "Numeric code"}
+ (com/text-input {:name (fc/field-name)
+ :autofocus true
+ :class "w-32"}))))
+ (fc/with-field :account/name
+ (com/field {:label "Name"}
+ (com/text-input {:name (fc/field-name)
+ :autofocus true
+ :class "w-32"
+ :value (fc/field-value)})))
+ (fc/with-field :account/type
+ (com/field {:label "Account Type"}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :id "type"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "account-type")})))
+ (fc/with-field :account/location
+ (com/field {:label "Location"}
+ (com/text-input {:name (fc/field-name)
+ :class "w-16"
+ :value (fc/field-value)})))
+
+ (fc/with-field :account/invoice-allowance
+ (com/field {:label "Invoice Allowance"}
+ (com/select {:name (fc/field-name)
+ :value (some-> (fc/field-value) name)
+ :class "w-36"
+ :options (ref->select-options "allowance")})))
+ (fc/with-field :account/vendor-allowance
+ (com/field {:label "Vendor Allowance"}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "allowance")})))
+ (fc/with-field :account/applicability
+ (com/field {:label "Applicability"}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "account-applicability")})))
+
+ (fc/with-field :account/client-overrides
+ (com/field {:label "Client Overrides" :id "client-overrides"}
+ (when (fc/field-value)
+ (doall
+ (for [override fc/*current*]
+ (fc/with-cursor override
+ (client-override* override)))))))
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-account-client-override-new)
+ :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
+ :hx-target "#client-overrides"
+ :hx-swap "beforeend"}
+ "New override")
+ [:div#form-errors [:span.error-content]]])
+ (com/validated-save-button {:errors []} ;; TODO
+ "Save account"))]]))
(defn new-client-override [{ {:keys [index]} :query-params}]
(html-response
- (client-override* {:db/id (str (java.util.UUID/randomUUID))}
- index)))
+ (client-override* {:db/id (str (java.util.UUID/randomUUID))})))
(defn account-edit-dialog [request]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index ffe7a84f..972ec8a6 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -406,7 +406,7 @@
[:form#edit-form (merge {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms"
- :hx-target "#modal-holder"
+ :hx-target "#modal-holder" ;; TODO sort
:hx-target-400 "#form-errors .error-content"
:x-trap "true"
:class "group/form"}
@@ -414,7 +414,8 @@
(com/modal-card
{}
[:div.flex [:div.p-2 "Transaction Rule"]]
- [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"
+ [:fieldset {:class "hx-disable"
+ :hx-disinherit "hx-target" ;; TODO why disinherit
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
(:transaction-rule/client entity))})}
@@ -561,6 +562,7 @@
:color :secondary
:hx-include "#edit-form"
:hx-ext "rename-params"
+ ;; TODO
: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\")}")
From dd5063c72d04526b10eda9301eae07dfac066eb8 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 21:47:36 -0700
Subject: [PATCH 13/34] account new override
---
resources/public/output.css | 33 ++++++++++++++++++++++++++
src/clj/auto_ap/ssr/admin/accounts.clj | 12 +++++++---
2 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 73530dec..96983899 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1357,6 +1357,10 @@ input:checked + .toggle-bg {
height: min-content;
}
+.h-\[90vh\] {
+ height: 90vh;
+}
+
.max-h-96 {
max-height: 24rem;
}
@@ -1369,6 +1373,10 @@ input:checked + .toggle-bg {
max-height: 90vh;
}
+.max-h-\[100vh\] {
+ max-height: 100vh;
+}
+
.max-h-\[80vh\] {
max-height: 80vh;
}
@@ -1446,6 +1454,19 @@ input:checked + .toggle-bg {
width: 100vw;
}
+.w-min {
+ width: -moz-min-content;
+ width: min-content;
+}
+
+.w-8\/12 {
+ width: 66.666667%;
+}
+
+.w-6\/12 {
+ width: 50%;
+}
+
.w-1\/4 {
width: 25%;
}
@@ -1474,6 +1495,10 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
+.max-w-xs {
+ max-width: 20rem;
+}
+
.flex-1 {
flex: 1 1 0%;
}
@@ -1692,6 +1717,10 @@ input:checked + .toggle-bg {
place-items: center;
}
+.content-center {
+ align-content: center;
+}
+
.items-start {
align-items: flex-start;
}
@@ -3601,6 +3630,10 @@ input:checked + .toggle-bg {
padding: 1.5rem;
}
+ .sm\:p-12 {
+ padding: 3rem;
+ }
+
.sm\:py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 28ddfc5e..35eca1b0 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -35,7 +35,8 @@
[datomic.api :as dc]
[hiccup2.core :as hiccup]
[malli.core :as mc]
- [auto-ap.ssr.form-cursor :as fc]))
+ [auto-ap.ssr.form-cursor :as fc]
+ [clj-time.format :as f]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
@@ -328,8 +329,13 @@
"Save account"))]]))
(defn new-client-override [{ {:keys [index]} :query-params}]
- (html-response
- (client-override* {:db/id (str (java.util.UUID/randomUUID))})))
+ (let [index (or index 0)
+ account {:account/client-overrides (conj (into [] (repeat index {}))
+ {:db/id (str (java.util.UUID/randomUUID))})}] ;; TODO schema decode is not working
+ (html-response
+ (fc/start-form account []
+ (fc/with-cursor (get-in fc/*current* [:account/client-overrides index])
+ (client-override* fc/*current*))))))
(defn account-edit-dialog [request]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
From 2f05197f5bf641500258222982014acb60d288c7 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Sun, 22 Oct 2023 21:53:47 -0700
Subject: [PATCH 14/34] progress.
---
src/clj/auto_ap/ssr/admin/accounts.clj | 75 ++++++++++++++++----------
1 file changed, 48 insertions(+), 27 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 35eca1b0..e10eb667 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -15,6 +15,7 @@
[auto-ap.solr :as solr]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
+ [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
@@ -23,20 +24,17 @@
entity-id
html-response
many-entity
- map->db-id-decoder
ref->enum-schema
ref->select-options
temp-id
validation-error
- wrap-form-4xx
+ wrap-form-4xx-2
wrap-schema-decode]]
[bidi.bidi :as bidi]
[clojure.string :as str]
[datomic.api :as dc]
[hiccup2.core :as hiccup]
- [malli.core :as mc]
- [auto-ap.ssr.form-cursor :as fc]
- [clj-time.format :as f]))
+ [malli.core :as mc]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
@@ -222,18 +220,20 @@
(com/hidden {:name (fc/field-name)
:value (fc/field-value)}))
(fc/with-field :account-client-override/client
- (com/typeahead-2 {:name (fc/field-name)
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :value (fc/field-value)
- :value-fn :db/id ;; TODO hydration something here
- :content-fn :client/name}))]
+ (com/validated-field {:errors (fc/field-errors)}
+ (com/typeahead-2 {:name (fc/field-name)
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :value (fc/field-value)
+ :value-fn :db/id ;; TODO hydration something here
+ :content-fn :client/name})))]
(fc/with-field :account-client-override/name
[:div.w-96
- (com/text-input {:name (fc/field-name)
- :class "w-full"
- :value (fc/field-value)})])
+ (com/validated-field {:errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)}))])
[:div (com/a-icon-button {"_" (hiccup/raw "on click halt the event then transition the closest <.client-override />'s opacity to 0 then remove closest <.client-override />")} svg/x)]])
;; TODO each form:
@@ -269,43 +269,50 @@
(fc/with-field :account/numeric-code
(when (nil? (fc/field-value))
- (com/field {:label "Numeric code"}
- (com/text-input {:name (fc/field-name)
- :autofocus true
- :class "w-32"}))))
+ (com/validated-field {:label "Numeric code"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :autofocus true
+ :class "w-32"}))))
(fc/with-field :account/name
- (com/field {:label "Name"}
+ (com/validated-field {:label "Name"
+ :errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
:autofocus true
:class "w-32"
:value (fc/field-value)})))
(fc/with-field :account/type
- (com/field {:label "Account Type"}
+ (com/validated-field {:label "Account Type"
+ :errors (fc/field-errors)}
(com/select {:name (fc/field-name)
:class "w-36"
:id "type"
:value (some-> (fc/field-value) name)
:options (ref->select-options "account-type")})))
(fc/with-field :account/location
- (com/field {:label "Location"}
+ (com/validated-field {:label "Location"
+ :errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
:class "w-16"
:value (fc/field-value)})))
(fc/with-field :account/invoice-allowance
- (com/field {:label "Invoice Allowance"}
+ (com/validated-field {:label "Invoice Allowance"
+ :errors (fc/field-errors)}
(com/select {:name (fc/field-name)
:value (some-> (fc/field-value) name)
:class "w-36"
:options (ref->select-options "allowance")})))
(fc/with-field :account/vendor-allowance
- (com/field {:label "Vendor Allowance"}
+ (com/validated-field {:label "Vendor Allowance"
+ :errors (fc/field-errors)}
(com/select {:name (fc/field-name)
:class "w-36"
:value (some-> (fc/field-value) name)
:options (ref->select-options "allowance")})))
(fc/with-field :account/applicability
- (com/field {:label "Applicability"}
+ (com/validated-field {:label "Applicability"
+ :errors (fc/field-errors)}
(com/select {:name (fc/field-name)
:class "w-36"
:value (some-> (fc/field-value) name)
@@ -351,6 +358,20 @@
:admin-account-new-save))})
:headers {"hx-trigger" "modalopen"}))
+(defn account-save-error [request]
+ ;; TODO hydration
+ ;; TODO consistency of error handling and passing, on all form examples
+ (let [entity (some-> request :last-form)]
+ (html-response (dialog* :account entity
+ :form-errors (:form-errors request)
+ :form-params (if (:db/id entity)
+ {:hx-put (str (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-edit-save))}
+ {:hx-post (str (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-edit-save))}))
+ :headers {"hx-retarget" "#edit-form fieldset"
+ "hx-reselect" "#edit-form fieldset"})))
+
(def account-schema (mc/schema
[:map
[:db/id {:optional true} [:maybe entity-id]]
@@ -366,7 +387,7 @@
(many-entity {}
[:db/id [:or entity-id temp-id]]
[:account-client-override/client [:or entity-id :string]]
- [:account-client-override/name :string])]]]))
+ [:account-client-override/name [:string {:min 2}]])]]]))
(def key->handler
(apply-middleware-to-all-handlers
@@ -381,7 +402,7 @@
:admin-account-save (-> account-save
(wrap-schema-decode :form-schema account-schema)
(wrap-nested-form-params)
- (wrap-form-4xx))
+ (wrap-form-4xx-2 account-save-error))
:admin-account-edit-dialog (-> account-edit-dialog
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
:admin-account-new-dialog account-new-dialog})
From 825443ef2c4724fc5478a9f306a69222ef7be6b8 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Mon, 23 Oct 2023 10:57:35 -0700
Subject: [PATCH 15/34] Made accounts page look great
---
src/clj/auto_ap/ssr/admin/accounts.clj | 235 +++++++-----
.../auto_ap/ssr/admin/transaction_rules.clj | 347 +++++++++---------
src/clj/auto_ap/ssr/components/buttons.clj | 4 +-
src/clj/auto_ap/ssr/hx.clj | 14 +
src/clj/auto_ap/ssr/utils.clj | 2 +
5 files changed, 337 insertions(+), 265 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index e10eb667..ca2af3b1 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -7,6 +7,7 @@
audit-transact
conn
merge-query
+ pull-attr
pull-many
query2]]
[auto-ap.query-params :as query-params]
@@ -17,17 +18,19 @@
[auto-ap.ssr.components :as com]
[auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
+ [auto-ap.ssr.hx :as hx]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers
entity-id
+ field-validation-error
+ form-validation-error
html-response
many-entity
ref->enum-schema
ref->select-options
temp-id
- validation-error
wrap-form-4xx-2
wrap-schema-decode]]
[bidi.bidi :as bidi]
@@ -181,7 +184,28 @@
(= :post request-method) (assoc :db/id "new"))
_ (cond (= :post request-method)
(when-let [extant (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))]
- (validation-error (format "The code %d is already in use." (:account/numeric-code entity)))))
+ (field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
+ [:account/numeric-code]
+ :form form-params))
+ )
+ ;; TODO the following would work better if the schema was hydrated automatically with needed values
+ _ (some->> form-params
+ :account/client-overrides
+ (group-by :account-client-override/client)
+ (filter (fn [[client overrides]]
+ (> (count overrides) 1)))
+ (map first)
+ seq
+ (#(form-validation-error (format "Client(s) %s have more than one override."
+ (str/join ", "
+ (map (fn [client]
+ (format "'%s'" (pull-attr (dc/db conn)
+ :client/name
+ (-> client)))
+ ) %)))
+ :form form-params))
+
+ )
{:keys [tempids]} (audit-transact [[:upsert-entity (cond-> entity
(:account/numeric-code entity) (assoc :account/code (str (:account/numeric-code entity))))]]
(:identity request))
@@ -213,11 +237,21 @@
;; TODO use cursor
;; TODO index based list not dbid
+;; TODO lots of weird edge cases with indexes
+;; for example, what happens when you have 0, 1, 2, but then delete 1?
+;; what happens when you delete 2 but then add another one?
+;; preference is that the field parsing logic does better grouping of what
+;; goes with what, building index on the server side
+;; not needing to pass index in
+
(defn client-override* [override]
- [:div.flex.gap-2.mb-2.client-override
+ [:div.flex.gap-2.mb-2.client-override (-> {"x-ref" "p"
+ :data-key "show"
+ }
+ hx/alpine-mount-then-appear)
[:div.w-96
(fc/with-field :db/id
- (com/hidden {:name (fc/field-name)
+ (com/hidden {:name (fc/field-name)
:value (fc/field-value)}))
(fc/with-field :account-client-override/client
(com/validated-field {:errors (fc/field-errors)}
@@ -226,15 +260,17 @@
:url (bidi/path-for ssr-routes/only-routes
:company-search)
:value (fc/field-value)
- :value-fn :db/id ;; TODO hydration something here
- :content-fn :client/name})))]
+ :value-fn (some-fn :db/id identity) ;; TODO better hydration
+ :content-fn (fn [value]
+ (:client/name (cond->> value
+ (nat-int? value) (dc/pull (dc/db conn) [:client/name]))))})))]
(fc/with-field :account-client-override/name
[:div.w-96
(com/validated-field {:errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
:class "w-full"
:value (fc/field-value)}))])
- [:div (com/a-icon-button {"_" (hiccup/raw "on click halt the event then transition the closest <.client-override />'s opacity to 0 then remove closest <.client-override />")} svg/x)]])
+ [:div (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)]])
;; TODO each form:
;; elimante typeahead1
@@ -246,94 +282,108 @@
;; componentize
;; ensure all dependency oriented stuff works the same way
;; make sure that "new row index" stuff works ok
+;; TODO figure out when hx-targets are decided
+;; ensure that adding a new one results in a new row
-(defn dialog* [& {:keys [account form-params form-errors]}]
- (com/modal
- {}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
- form-params)
- [:fieldset {:class "hx-disable"}
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "Account"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:account/numeric-code account) " - " (:account/name account)]]
+(defn dialog* [& {:keys [entity form-params form-errors]}]
+ (fc/start-form entity form-errors
+ [:div {:x-data (hx/json {"accountName" (:account/name entity)
+ "accountCode" (:account/numeric-code entity)})}
+ (com/modal
+ {}
+ [:form#edit-form (merge {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"}
+ form-params)
+ [:fieldset {:class "hx-disable"}
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "Account"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
+ [:span {:x-text "accountCode"}]
+ " - "
+ [:span {:x-text "accountName"}]]]
+ [:div.space-y-1
+ (when-let [id (:db/id entity)]
+ (com/hidden {:name "db/id"
+ :value id}))
- (fc/start-form
- account form-errors
- [:div.space-y-1
- (when-let [id (:db/id account)]
- (com/hidden {:name "db/id"
- :value id}))
+ (fc/with-field :account/numeric-code
+ (if (nil? (:db/id entity))
+ (com/validated-field {:label "Numeric code"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :x-model "accountCode"
+ :autofocus true
+ :class "w-32"}))
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)})))
+ (fc/with-field :account/name
+ (com/validated-field {:label "Name"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :x-model "accountName"
- (fc/with-field :account/numeric-code
- (when (nil? (fc/field-value))
- (com/validated-field {:label "Numeric code"
- :errors (fc/field-errors)}
- (com/text-input {:name (fc/field-name)
- :autofocus true
- :class "w-32"}))))
- (fc/with-field :account/name
- (com/validated-field {:label "Name"
- :errors (fc/field-errors)}
- (com/text-input {:name (fc/field-name)
- :autofocus true
- :class "w-32"
- :value (fc/field-value)})))
- (fc/with-field :account/type
- (com/validated-field {:label "Account Type"
- :errors (fc/field-errors)}
- (com/select {:name (fc/field-name)
- :class "w-36"
- :id "type"
- :value (some-> (fc/field-value) name)
- :options (ref->select-options "account-type")})))
- (fc/with-field :account/location
- (com/validated-field {:label "Location"
- :errors (fc/field-errors)}
- (com/text-input {:name (fc/field-name)
- :class "w-16"
- :value (fc/field-value)})))
+ :class "w-64"
+ :value (fc/field-value)})))
+ (fc/with-field :account/type
+ (com/validated-field {:label "Account Type"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :id "type"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "account-type")})))
+ (fc/with-field :account/location
+ (com/validated-field {:label "Location"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-16"
+ :value (fc/field-value)})))
- (fc/with-field :account/invoice-allowance
- (com/validated-field {:label "Invoice Allowance"
- :errors (fc/field-errors)}
- (com/select {:name (fc/field-name)
- :value (some-> (fc/field-value) name)
- :class "w-36"
- :options (ref->select-options "allowance")})))
- (fc/with-field :account/vendor-allowance
- (com/validated-field {:label "Vendor Allowance"
- :errors (fc/field-errors)}
- (com/select {:name (fc/field-name)
- :class "w-36"
- :value (some-> (fc/field-value) name)
- :options (ref->select-options "allowance")})))
- (fc/with-field :account/applicability
- (com/validated-field {:label "Applicability"
- :errors (fc/field-errors)}
- (com/select {:name (fc/field-name)
- :class "w-36"
- :value (some-> (fc/field-value) name)
- :options (ref->select-options "account-applicability")})))
+ [:div.flex.flex-wrap.gap-4
+ (fc/with-field :account/invoice-allowance
+ (com/validated-field {:label "Invoice Allowance"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :value (some-> (fc/field-value) name)
+ :class "w-36"
+ :options (ref->select-options "allowance")})))
+ (fc/with-field :account/vendor-allowance
+ (com/validated-field {:label "Vendor Allowance"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "allowance")})))]
+ (fc/with-field :account/applicability
+ (com/validated-field {:label "Applicability"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :value (some-> (fc/field-value) name)
+ :options (ref->select-options "account-applicability")})))
- (fc/with-field :account/client-overrides
- (com/field {:label "Client Overrides" :id "client-overrides"}
- (when (fc/field-value)
- (doall
- (for [override fc/*current*]
- (fc/with-cursor override
- (client-override* override)))))))
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-account-client-override-new)
- :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
- :hx-target "#client-overrides"
- :hx-swap "beforeend"}
- "New override")
- [:div#form-errors [:span.error-content]]])
- (com/validated-save-button {:errors []} ;; TODO
- "Save account"))]]))
+ (fc/with-field :account/client-overrides
+ (com/field {:label "Client Overrides" :id "client-overrides"}
+ (when (fc/field-value)
+ (doall
+ (for [override fc/*current*]
+ (fc/with-cursor override
+ (client-override* override)))))))
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-account-client-override-new)
+ :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
+ :hx-target "#client-overrides"
+ :hx-swap "beforeend"}
+ "New override")
+ ]
+ [:div
+ [:div [:div#form-errors (when (:errors fc/*form-errors*)
+ [:span.error-content
+ (com/errors {:errors (:errors fc/*form-errors*)})])]]
+ (com/validated-save-button {:errors (seq form-errors)}
+ "Save account")])]])]))
(defn new-client-override [{ {:keys [index]} :query-params}]
(let [index (or index 0)
@@ -346,14 +396,15 @@
(defn account-edit-dialog [request]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
- (html-response (dialog* :account account
+ (html-response (dialog* :entity account
:form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
:admin-account-edit-save))})
:headers {"hx-trigger" "modalopen"})))
(defn account-new-dialog [_]
- (html-response (dialog* :account nil
+ (html-response (dialog* :entity {}
+ :form-errors {}
:form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
:admin-account-new-save))})
:headers {"hx-trigger" "modalopen"}))
@@ -362,7 +413,7 @@
;; TODO hydration
;; TODO consistency of error handling and passing, on all form examples
(let [entity (some-> request :last-form)]
- (html-response (dialog* :account entity
+ (html-response (dialog* :entity entity
:form-errors (:form-errors request)
:form-params (if (:db/id entity)
{:hx-put (str (bidi/path-for ssr-routes/only-routes
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 972ec8a6..93ceadb2 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -401,189 +401,192 @@
;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [entity form-params form-errors]}]
- (com/modal
- {:modal-class "max-w-2xl"}
+ (fc/start-form entity form-errors
+ (com/modal
+ {:modal-class "max-w-2xl"}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target "#modal-holder" ;; TODO sort
- :hx-target-400 "#form-errors .error-content"
- :x-trap "true"
- :class "group/form"}
- form-params)
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "Transaction Rule"]]
- [:fieldset {:class "hx-disable"
- :hx-disinherit "hx-target" ;; TODO why disinherit
- :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
- (:transaction-rule/client entity))})}
+ [:form#edit-form (merge {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target "#modal-holder" ;; TODO sort
+ :hx-target-400 "#form-errors .error-content"
+ :x-trap "true"
+ :class "group/form"}
+ form-params)
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "Transaction Rule"]]
+ [:fieldset {:class "hx-disable"
+ :hx-disinherit "hx-target" ;; TODO why disinherit
+ :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
+ (:transaction-rule/client entity))})}
- (fc/start-form entity form-errors
- [:div.space-y-1
- (when-let [id (:db/id entity)]
- (com/hidden {:name "db/id"
- :value id}))
- (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?)
- :x-init "$el.focus()"
- :placeholder "HOME DEPOT"
- :class "w-96"
- :value (fc/field-value)})))
- [:div.filters {:x-data (hx/json {:clientFilter (boolean (fc/field-value (:transaction-rule/client fc/*current*)))
- :bankAccountFilter (boolean (fc/field-value (:transaction-rule/bank-account fc/*current*)))
- :amountFilter (boolean (or (fc/field-value (:transaction-rule/amount-gte fc/*current*))
- (fc/field-value (:transaction-rule/amount-lte fc/*current*))))
- :domFilter (boolean (or (fc/field-value (:transaction-rule/dom-gte fc/*current*))
- (fc/field-value (:transaction-rule/dom-lte fc/*current*))))})}
+ [:div.space-y-1
+ (when-let [id (:db/id entity)]
+ (com/hidden {:name "db/id"
+ :value id}))
+ (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?)
+ :x-init "$el.focus()"
+ :placeholder "HOME DEPOT"
+ :class "w-96"
+ :value (fc/field-value)})))
+ [:div.filters {:x-data (hx/json {:clientFilter (boolean (fc/field-value (:transaction-rule/client fc/*current*)))
+ :bankAccountFilter (boolean (fc/field-value (:transaction-rule/bank-account fc/*current*)))
+ :amountFilter (boolean (or (fc/field-value (:transaction-rule/amount-gte fc/*current*))
+ (fc/field-value (:transaction-rule/amount-lte fc/*current*))))
+ :domFilter (boolean (or (fc/field-value (:transaction-rule/dom-gte fc/*current*))
+ (fc/field-value (:transaction-rule/dom-lte fc/*current*))))})}
- [:div.flex.gap-2.mb-2
- (com/a-button {"@click" "clientFilter=true"
- "x-show" "!clientFilter"} "Filter client")
- (com/a-button {"@click" "bankAccountFilter=true"
- "x-show" "clientFilter && !bankAccountFilter"} "Filter bank account")
- (com/a-button {"@click" "amountFilter=true"
- "x-show" "!amountFilter"} "Filter amount")
- (com/a-button {"@click" "domFilter=true"
- "x-show" "!domFilter"} "Filter day of month")]
- (fc/with-field :transaction-rule/client
+ [:div.flex.gap-2.mb-2
+ (com/a-button {"@click" "clientFilter=true"
+ "x-show" "!clientFilter"} "Filter client")
+ (com/a-button {"@click" "bankAccountFilter=true"
+ "x-show" "clientFilter && !bankAccountFilter"} "Filter bank account")
+ (com/a-button {"@click" "amountFilter=true"
+ "x-show" "!amountFilter"} "Filter amount")
+ (com/a-button {"@click" "domFilter=true"
+ "x-show" "!domFilter"} "Filter day of month")]
+ (fc/with-field :transaction-rule/client
- (com/validated-field
- (-> {:label "Client"
- :errors (fc/field-errors)
- :x-show "clientFilter"}
- (hx/alpine-appear))
- [:div.w-96
- (com/typeahead-2 {:name (fc/field-name)
- :error? (fc/error?)
- :class "w-96"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes :company-search)
- :x-model "clientId"
- :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))})]))
+ (com/validated-field
+ (-> {:label "Client"
+ :errors (fc/field-errors)
+ :x-show "clientFilter"}
+ (hx/alpine-appear))
+ [:div.w-96
+ (com/typeahead-2 {:name (fc/field-name)
+ :error? (fc/error?)
+ :class "w-96"
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes :company-search)
+ :x-model "clientId"
+ :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/bank-account
- (com/validated-field
- (-> {:label "Bank Account"
- :errors (fc/field-errors)
- :x-show "bankAccountFilter"}
- hx/alpine-appear)
- [:div.w-96
- [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead)
- :hx-trigger "changed"
- :hx-target "next *"
- :hx-include "#bank-account-changer"
- :hx-swap "innerHTML"
+ (fc/with-field :transaction-rule/bank-account
+ (com/validated-field
+ (-> {:label "Bank Account"
+ :errors (fc/field-errors)
+ :x-show "bankAccountFilter"}
+ hx/alpine-appear)
+ [:div.w-96
+ [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead)
+ :hx-trigger "changed"
+ :hx-target "next *"
+ :hx-include "#bank-account-changer"
+ :hx-swap "innerHTML"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
- :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
- (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity))
- :name (fc/field-name)
- :value (fc/field-value)})]))
+ (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"
- :x-show "amountFilter"}
- hx/alpine-appear)
- [: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)})])])
+ (com/field (-> {:label "Amount"
+ :x-show "amountFilter"}
+ hx/alpine-appear)
+ [: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)})])])
- (com/field (-> {:label "Day of month"
- :x-show "domFilter"}
- hx/alpine-appear)
- [: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 "Day of month"
+ :x-show "domFilter"}
+ hx/alpine-appear)
+ [: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)})))])]
- [: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")
- :class "w-96"
- :value (fc/field-value)
- :value-fn (some-fn :db/id identity)
- :content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})]))
+ [: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")
+ :class "w-96"
+ :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/data-grid-row
- {:class "new-row"}
- (com/data-grid-cell {:colspan 4
- :class "bg-gray-100"}
- [:div.flex.justify-center
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-new-account)
- :color :secondary
- :hx-include "#edit-form"
- :hx-ext "rename-params"
- ;; TODO
- :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 "#edit-form .new-row"
- :hx-swap "beforebegin"}
- "New account")])))
- (com/errors {:errors (fc/field-errors)})))
+ (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/data-grid-row
+ {:class "new-row"}
+ (com/data-grid-cell {:colspan 4
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :color :secondary
+ :hx-include "#edit-form"
+ :hx-ext "rename-params"
+ ;; TODO
+ :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 "#edit-form .new-row"
+ :hx-swap "beforebegin"}
+ "New account")])))
+ (com/errors {:errors (fc/field-errors)})))
- (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)
- :size :small
- :orientation :horizontal})))
+ (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)
+ :size :small
+ :orientation :horizontal})))
- [:div#form-errors (when (:errors fc/*form-errors*)
- [:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})])]])]
- (com/validated-save-button {:errors form-errors} "Save rule"))]))
+ ;; TODO componentize
+ ]]
+ [:div
+ [:div#form-errors (when (:errors fc/*form-errors*)
+ [:span.error-content
+ (com/errors {:errors (:errors fc/*form-errors*)})])]
+ (com/validated-save-button {:errors form-errors} "Save rule")])])))
;; TODO Should forms have some kind of helper to render an individual field? saving
@@ -592,8 +595,8 @@
;; pull out the single field to swap
(defn new-account [{{:keys [client-id index]} :query-params}]
- (let [index (or index 0) ;; TODO schema decode is not working
- transaction-rule {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
+ (let [index (or index 0) ;; TODO schema decode is not working
+ transaction-rule {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
client-id)
:transaction-rule/accounts (conj (into [] (repeat index {} ))
{:db/id (str (java.util.UUID/randomUUID))
diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj
index 076945f9..9df54b67 100644
--- a/src/clj/auto_ap/ssr/components/buttons.clj
+++ b/src/clj/auto_ap/ssr/components/buttons.clj
@@ -134,7 +134,9 @@
(defn a-icon-button- [params & children]
(into
- [:a (update params :class str " inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center p-3 text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100")
+ [:a (-> params (update :class str " inline-flex items-center justify-center bg-white dark:bg-gray-600 items-center p-3 text-sm font-medium border border-gray-300 dark:border-gray-700 text-center text-gray-500 hover:text-gray-800 rounded-lg dark:text-gray-400 dark:hover:text-gray-100"
+ )
+ (update :href #(or % "")))
[:div.h-4.w-4 children]]))
(defn save-button- [params & children]
diff --git a/src/clj/auto_ap/ssr/hx.clj b/src/clj/auto_ap/ssr/hx.clj
index cb5e5c00..895d024e 100644
--- a/src/clj/auto_ap/ssr/hx.clj
+++ b/src/clj/auto_ap/ssr/hx.clj
@@ -24,3 +24,17 @@
"x-transition:enter" "transition duration-500"
"x-transition:enter-start" "opacity-0"
"x-transition:enter-end" "opacity-100"))
+
+(defn alpine-disappear [m]
+ (assoc m
+ "x-transition:leave" "transition duration-500"
+ "x-transition:leave-start" "opacity-100"
+ "x-transition:leave-end" "opacity-0"))
+
+(defn alpine-mount-then-appear [{:keys [data-key] :as params}]
+ (merge (-> {"x-data" (json {data-key false})
+ "x-init" (format "$nextTick(() => %s=true)" (name data-key))
+ "x-show" (name data-key)}
+ alpine-appear
+ alpine-disappear)
+ (dissoc params :data-key)))
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 6529aebb..b80c08bd 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -146,6 +146,8 @@
(defn keyword->str [k]
(subs (str k) 1))
+
+;; TODO need to remove or at least remove usages as the form is not included
(defn validation-error [m & {:as data}]
(throw+ (ex-info m (merge data {:type :validation}))))
From dc1fefd30c007c28388f875c009bf15521c0e796 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Mon, 23 Oct 2023 11:08:05 -0700
Subject: [PATCH 16/34] accounts and transactions work the same way
---
src/clj/auto_ap/ssr/admin/accounts.clj | 10 ++++++----
src/clj/auto_ap/ssr/admin/transaction_rules.clj | 16 +++++++++-------
2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index ca2af3b1..87f83db0 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -244,11 +244,12 @@
;; goes with what, building index on the server side
;; not needing to pass index in
+;; TODO decide when cursors are used. other cases it's not, some are
(defn client-override* [override]
- [:div.flex.gap-2.mb-2.client-override (-> {"x-ref" "p"
+ [:div.flex.gap-2.mb-2.client-override (-> {:x-ref "p"
:data-key "show"
- }
- hx/alpine-mount-then-appear)
+ :x-data (hx/json {:show (boolean (not (:new? override)))})}
+ hx/alpine-mount-then-appear)
[:div.w-96
(fc/with-field :db/id
(com/hidden {:name (fc/field-name)
@@ -388,7 +389,8 @@
(defn new-client-override [{ {:keys [index]} :query-params}]
(let [index (or index 0)
account {:account/client-overrides (conj (into [] (repeat index {}))
- {:db/id (str (java.util.UUID/randomUUID))})}] ;; TODO schema decode is not working
+ {:db/id (str (java.util.UUID/randomUUID))
+ :new? true})}] ;; TODO schema decode is not working
(html-response
(fc/start-form account []
(fc/with-cursor (get-in fc/*current* [:account/client-overrides index])
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 93ceadb2..fa27b0e5 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -342,8 +342,12 @@
(defn- transaction-rule-account-row*
[transaction-rule account]
- (com/data-grid-row {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
- (fc/field-value (:transaction-rule-account/account account)))})}
+ (com/data-grid-row (-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
+ (fc/field-value (:transaction-rule-account/account account)))
+ :show (boolean (not (fc/field-value (:new? account))))})
+ :data-key "show"
+ :x-ref "p"}
+ hx/alpine-mount-then-appear)
(let [account-name (fc/field-name (:transaction-rule-account/account account))]
(list
@@ -394,10 +398,7 @@
(* 100 )
(long ))}))))))
(com/data-grid-cell {:class "align-top"}
- (com/a-icon-button
- {"_" (hiccup/raw "on click halt the event then transition the closest
's opacity to 0 then remove closest
")
- :href "#"}
- svg/x))))
+ (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
;; TODO dialog is no longer closeable
(defn dialog* [& {:keys [entity form-params form-errors]}]
@@ -600,7 +601,8 @@
client-id)
:transaction-rule/accounts (conj (into [] (repeat index {} ))
{:db/id (str (java.util.UUID/randomUUID))
- :transaction-rule-account/location "Shared"})}]
+ :transaction-rule-account/location "Shared"
+ :new? true})}]
(html-response
(fc/start-form transaction-rule []
(fc/with-cursor (get-in fc/*current* [:transaction-rule/accounts index])
From be9d777a1778d917e691b706d7f39b5d58b5a218 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Mon, 23 Oct 2023 11:59:14 -0700
Subject: [PATCH 17/34] consistent user experience with new client
---
src/clj/auto_ap/ssr/admin/accounts.clj | 91 +++++----
.../auto_ap/ssr/admin/transaction_rules.clj | 2 +-
src/clj/auto_ap/ssr/users.clj | 182 ++++++++++++------
src/cljc/auto_ap/ssr_routes.cljc | 1 +
4 files changed, 184 insertions(+), 92 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 87f83db0..6146ef91 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -246,32 +246,35 @@
;; TODO decide when cursors are used. other cases it's not, some are
(defn client-override* [override]
- [:div.flex.gap-2.mb-2.client-override (-> {:x-ref "p"
- :data-key "show"
- :x-data (hx/json {:show (boolean (not (:new? override)))})}
- hx/alpine-mount-then-appear)
- [:div.w-96
- (fc/with-field :db/id
- (com/hidden {:name (fc/field-name)
- :value (fc/field-value)}))
- (fc/with-field :account-client-override/client
- (com/validated-field {:errors (fc/field-errors)}
- (com/typeahead-2 {:name (fc/field-name)
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :value (fc/field-value)
- :value-fn (some-fn :db/id identity) ;; TODO better hydration
- :content-fn (fn [value]
- (:client/name (cond->> value
- (nat-int? value) (dc/pull (dc/db conn) [:client/name]))))})))]
- (fc/with-field :account-client-override/name
- [:div.w-96
- (com/validated-field {:errors (fc/field-errors)}
- (com/text-input {:name (fc/field-name)
- :class "w-full"
- :value (fc/field-value)}))])
- [:div (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x)]])
+ (com/data-grid-row (-> {:x-ref "p"
+ :data-key "show"
+ :x-data (hx/json {:show (boolean (not (:new? override)))})}
+ hx/alpine-mount-then-appear)
+ (fc/with-field :db/id
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)}))
+ (fc/with-field :account-client-override/client
+ (com/data-grid-cell {}
+ (com/validated-field {:errors (fc/field-errors)}
+ (com/typeahead-2 {:name (fc/field-name)
+ :placeholder "Search..."
+ :class "w-96"
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :value (fc/field-value)
+ :value-fn (some-fn :db/id identity) ;; TODO better hydration
+ :content-fn (fn [value]
+ (:client/name (cond->> value
+ (nat-int? value) (dc/pull (dc/db conn) [:client/name]))))}))))
+ (fc/with-field :account-client-override/name
+ (com/data-grid-cell
+ {}
+ (com/validated-field {:errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-96"
+ :value (fc/field-value)}))))
+ (com/data-grid-cell {:class "align-top"}
+ (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
;; TODO each form:
;; elimante typeahead1
@@ -366,18 +369,32 @@
:options (ref->select-options "account-applicability")})))
(fc/with-field :account/client-overrides
+
(com/field {:label "Client Overrides" :id "client-overrides"}
- (when (fc/field-value)
- (doall
- (for [override fc/*current*]
- (fc/with-cursor override
- (client-override* override)))))))
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-account-client-override-new)
- :hx-vals (hiccup/raw "js:{index: document.getElementById('client-overrides').children.length - 1}")
- :hx-target "#client-overrides"
- :hx-swap "beforeend"}
- "New override")
+
+ (com/data-grid {:headers [(com/data-grid-header {} "Client")
+ (com/data-grid-header {} "Account name")
+ (com/data-grid-header {})]
+ :id "client-override-table"}
+ (when (fc/field-value)
+ (doall
+ (for [override fc/*current*]
+ (fc/with-cursor override
+ (client-override* override)))))
+ (com/data-grid-row
+ {:class "new-row"}
+ (com/data-grid-cell {:colspan 3
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-account-client-override-new)
+ :color :secondary
+ :hx-include "#edit-form"
+ :hx-vals (hiccup/raw "js:{index: countRows(\"#client-override-table\")}")
+ :hx-target "#edit-form .new-row"
+ :hx-swap "beforebegin"}
+ "New override")])))))
+
]
[:div
[:div [:div#form-errors (when (:errors fc/*form-errors*)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index fa27b0e5..5cd9dcf9 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -549,7 +549,7 @@
(com/data-grid-header {:class "w-16"} "%")
(com/data-grid-header {:class "w-16"})]
:id "transaction-rule-account-table"}
- (when @fc/*current*
+ (when (fc/field-value)
(doall (for [tra fc/*current*]
(fc/with-cursor tra
(transaction-rule-account-row* entity tra)))))
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 2b327f95..46c5ca19 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -14,14 +14,19 @@
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
+ [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
+ [auto-ap.ssr.hx :as hx]
+ [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers
entity-id
- forced-vector
html-response
+ many-entity
ref->enum-schema
+ ref->select-options
+ wrap-form-4xx-2
wrap-schema-decode]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
@@ -29,7 +34,9 @@
[clojure.string :as str]
[config.core :refer [env]]
[datomic.api :as dc]
- [malli.core :as mc]))
+ [hiccup2.core :as hiccup]
+ [malli.core :as mc]
+ [clj-time.format :as f]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
@@ -258,79 +265,146 @@
}
:session {:identity (dissoc (auth/user->jwt user "FAKE_TOKEN")
:exp)}}))
+(defn client-row* [client]
+ (com/data-grid-row (-> {:x-ref "p"
+ :data-key "show"
+ :x-data (hx/json {:show (boolean (not (fc/field-value (:new? client))))})}
+ hx/alpine-mount-then-appear)
+ (com/data-grid-cell {}
+ (com/validated-field {:errors (fc/field-errors (:db/id fc/*current*))}
+ (com/typeahead-2 {:name (fc/field-name (:db/id fc/*current*))
+ :class "w-full"
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)
+ :value (fc/field-value)
+
+ :value-fn :db/id ;; TODO better hydration
+ :content-fn (fn [value]
+ (:client/name (dc/pull (dc/db conn) [:client/name]
+ (or (:db/id value)
+ value))))
+ :size :small})))
+ (com/data-grid-cell {:class "align-top"}
+ (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
+
+(defn dialog* [{:keys [entity form-params form-errors]}]
+ (fc/start-form
+ entity form-errors
+ (com/modal
+ {}
+ [:form#edit-form (merge {:hx-ext "response-targets"
+ :hx-put (str (bidi/path-for ssr-routes/only-routes
+ :user-edit-save
+ :request-method :put))
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :class "w-full"}
+ form-params)
+ [:fieldset {:class "hx-disable"}
+ (com/modal-card
+ {}
+ [:div.flex [:div.p-2 "User"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:user/name entity)]]
+ [:div.space-y-6
+ (fc/with-field :db/id
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)}))
+ (fc/with-field :user/role
+ (com/validated-field {:label "Role"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :class "w-36"
+ :autofocus true
+ :value (some->> (fc/field-value) name)
+ :options (ref->select-options "user-role")})))
+ (fc/with-field :user/clients
+ (com/validated-field {:label "Clients"}
+ (com/data-grid {:headers [(com/data-grid-header {} "Client")
+ (com/data-grid-header {} )]
+ :id "client-table"}
+ (doall (for [client fc/*current*]
+ (fc/with-cursor client
+ (client-row* client))))
+ (com/data-grid-row
+ {:class "new-row"}
+ (com/data-grid-cell {:colspan 2
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+ (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
+ :user-client-new)
+ :color :secondary
+ :hx-include "#edit-form"
+ :hx-vals (hiccup/raw "js:{index: countRows(\"#client-table\")}")
+ :hx-target "#edit-form .new-row"
+ :hx-swap "beforebegin"}
+ "New override")])))
+ ))
+ [:div#form-errors [:span.error-content]]]
+ [:div
+ [:div [:div#form-errors (when (:errors fc/*form-errors*)
+ [:span.error-content
+ (com/errors {:errors (:errors fc/*form-errors*)})])]]
+ (com/validated-save-button {:errors (seq form-errors)}
+ "Save user")])]])))
+
+;; TODO rename edit-form or make it generic
(defn user-edit-save [{:keys [form-params identity] :as request}]
- (let [_ @(dc/transact conn [[:upsert-entity form-params]])
+ (let [_ @(dc/transact conn [[:upsert-entity form-params]])
user (some-> form-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
(html-response
(row* identity user {:flash? true})
- :headers {"hx-trigger" "modalclose"
+ :headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#user-table tr[data-id=\"%d\"]" (:db/id user))})))
+(defn user-save-error [request]
+ ;; TODO hydration
+ ;; TODO consistency of error handling and passing, on all form examples
+ (let [entity (some-> request :last-form)]
+ (html-response (dialog* {:entity entity
+ :form-errors (:form-errors request)})
+ :headers {"hx-retarget" "#edit-form fieldset"
+ "hx-reselect" "#edit-form fieldset"})))
+
(defn user-edit-dialog [request]
(let [user (some-> request
:route-params
:db/id
(#(dc/pull (dc/db conn) default-read %)))]
(html-response
- (com/modal
- {}
- [:form {:hx-ext "response-targets"
- :hx-put (str (bidi/path-for ssr-routes/only-routes
- :user-edit-save
- :request-method :put))
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"
- :class "w-full"}
- [:fieldset {:class "hx-disable"}
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "User"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:user/name user)]]
- [:div.space-y-6
- (com/hidden {:name "db/id"
- :value (:db/id user)})
- (com/field {:label "Role"}
- (com/select {:name "user/role"
- :class "w-36"
- :autofocus true
- :id "role"
- :value (name (:user/role user))
- :options [["none" "None"]
- ["power-user" "Power user"]
- ["manager" "Manager"]
- ["admin" "Admin"]
- ["user" "User"]]}))
- (com/field {:label "Clients"}
- (com/typeahead {:name "user/clients"
- :class "w-full"
- :multiple "multiple"
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id "clients"
- :value (map
- (fn [client]
- [(:db/id client) (:client/name client)])
- (:user/clients user))
- :size :small}))
- [:div#form-errors [:span.error-content]]]
- (com/validated-save-button {:errors []} ;; TODO
- "Save user"))]])
+ (dialog* {:entity user
+ :form-errors {}})
+
:headers {"hx-trigger" "modalopen"})))
+(defn new-client [{ {:keys [index]} :query-params}]
+ (let [index (or index 0)
+ account {:user/clients (conj (into [] (repeat index {}))
+ {:db/id nil
+ :new? true})}] ;; TODO schema decode is not working
+ (html-response
+ (fc/start-form account []
+ (fc/with-cursor (get-in fc/*current* [:user/clients index])
+ (client-row* fc/*current*))))))
+
(def key->handler
(apply-middleware-to-all-handlers
{:users (helper/page-route grid-page)
:user-table (helper/table-route grid-page)
:user-edit-save (-> user-edit-save
- (wrap-schema-decode
- :form-schema (mc/schema
- [:map
- [:db/id entity-id]
- [:user/clients {:optional true}
- [:maybe
- (forced-vector entity-id)]]
- [:user/role (ref->enum-schema "user-role")]])))
+ (wrap-schema-decode :form-schema (mc/schema
+ [:map
+ [:db/id entity-id]
+ [:user/clients {:optional true}
+ [:maybe
+ (many-entity {} [:db/id entity-id])]]
+ [:user/role (ref->enum-schema "user-role")]]))
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 user-save-error))
+ :user-client-new (-> new-client
+ (wrap-schema-decode :query-schema [:map
+ [:index {:optional true
+ :default 0} [nat-int? {:default 0}]]]))
:user-edit-dialog (-> user-edit-dialog
(wrap-schema-decode
:route-schema (mc/schema [:map [:db/id entity-id]])))
diff --git a/src/cljc/auto_ap/ssr_routes.cljc b/src/cljc/auto_ap/ssr_routes.cljc
index cad4d193..7da78c5e 100644
--- a/src/cljc/auto_ap/ssr_routes.cljc
+++ b/src/cljc/auto_ap/ssr_routes.cljc
@@ -16,6 +16,7 @@
["/inspect/" [#"\d+" :entity-id] #"/?"] :admin-history-inspect}
"/user" {"" {:get :users
:put :user-edit-save}
+ "/client/new" :user-client-new
"/table" :user-table
"/impersonate" :user-impersonate
[[#"\d+" :db/id] "/edit"] {:get :user-edit-dialog}}
From 84d6f455ffb4e5ad8b260877b95b136e362d62e6 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Mon, 23 Oct 2023 15:02:36 -0700
Subject: [PATCH 18/34] Makes cursor-seq for lists
---
src/clj/auto_ap/ssr/admin/accounts.clj | 7 ++-----
src/clj/auto_ap/ssr/admin/transaction_rules.clj | 5 +----
src/clj/auto_ap/ssr/form_cursor.clj | 10 ++++++++++
src/clj/auto_ap/ssr/users.clj | 8 ++------
4 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 6146ef91..c1ce0feb 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -376,11 +376,8 @@
(com/data-grid-header {} "Account name")
(com/data-grid-header {})]
:id "client-override-table"}
- (when (fc/field-value)
- (doall
- (for [override fc/*current*]
- (fc/with-cursor override
- (client-override* override)))))
+ (fc/cursor-map
+ #(client-override* %))
(com/data-grid-row
{:class "new-row"}
(com/data-grid-cell {:colspan 3
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 5cd9dcf9..16f7f10e 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -549,10 +549,7 @@
(com/data-grid-header {:class "w-16"} "%")
(com/data-grid-header {:class "w-16"})]
:id "transaction-rule-account-table"}
- (when (fc/field-value)
- (doall (for [tra fc/*current*]
- (fc/with-cursor tra
- (transaction-rule-account-row* entity tra)))))
+ (fc/cursor-map #(transaction-rule-account-row* entity %))
(com/data-grid-row
{:class "new-row"}
(com/data-grid-cell {:colspan 4
diff --git a/src/clj/auto_ap/ssr/form_cursor.clj b/src/clj/auto_ap/ssr/form_cursor.clj
index eef97db2..02c65ba4 100644
--- a/src/clj/auto_ap/ssr/form_cursor.clj
+++ b/src/clj/auto_ap/ssr/form_cursor.clj
@@ -45,3 +45,13 @@
(every? string? errors)))))
+(defn cursor-map
+ ([f] (cursor-map *current* f))
+ ([cursor f]
+ (when (field-value)
+ (doall
+ (for [n cursor]
+ (with-cursor n
+ (f n)))))))
+
+
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 46c5ca19..e225fef3 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -322,9 +322,7 @@
(com/data-grid {:headers [(com/data-grid-header {} "Client")
(com/data-grid-header {} )]
:id "client-table"}
- (doall (for [client fc/*current*]
- (fc/with-cursor client
- (client-row* client))))
+ (fc/cursor-map #(client-row* %))
(com/data-grid-row
{:class "new-row"}
(com/data-grid-cell {:colspan 2
@@ -337,9 +335,7 @@
:hx-vals (hiccup/raw "js:{index: countRows(\"#client-table\")}")
:hx-target "#edit-form .new-row"
:hx-swap "beforebegin"}
- "New override")])))
- ))
- [:div#form-errors [:span.error-content]]]
+ "New override")])))))]
[:div
[:div [:div#form-errors (when (:errors fc/*form-errors*)
[:span.error-content
From 48347bb8c543c73cc11d3540c8d7caa0b0c33ec5 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Mon, 23 Oct 2023 23:46:01 -0700
Subject: [PATCH 19/34] Uses cursors for simplicity, uses common grid bottom
---
src/clj/auto_ap/cursor.clj | 9 +++
src/clj/auto_ap/ssr/admin/accounts.clj | 37 ++++------
.../auto_ap/ssr/admin/transaction_rules.clj | 68 ++++++++-----------
src/clj/auto_ap/ssr/components.clj | 1 +
src/clj/auto_ap/ssr/components/data_grid.clj | 24 ++++++-
src/clj/auto_ap/ssr/form_cursor.clj | 13 +++-
src/clj/auto_ap/ssr/hx.clj | 6 +-
src/clj/auto_ap/ssr/users.clj | 30 +++-----
8 files changed, 98 insertions(+), 90 deletions(-)
diff --git a/src/clj/auto_ap/cursor.clj b/src/clj/auto_ap/cursor.clj
index 0ff1448d..6a7f25cc 100644
--- a/src/clj/auto_ap/cursor.clj
+++ b/src/clj/auto_ap/cursor.clj
@@ -125,6 +125,15 @@
[] nil))
+(defn synthetic-cursor [v prefix]
+ (let [internal-cursor (cursor v)]
+ (reify ICursor
+ (path [this]
+ (into prefix (path internal-cursor)))
+ (state [this]
+ (state internal-cursor)))))
+
+
(defn transact! [cursor f]
"Changes value beneath cursor by passing it to a single-argument
function f. Old value will be passed as function argument. Function
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index c1ce0feb..ef48ae82 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -248,7 +248,8 @@
(defn client-override* [override]
(com/data-grid-row (-> {:x-ref "p"
:data-key "show"
- :x-data (hx/json {:show (boolean (not (:new? override)))})}
+ :x-data (hx/json {:show (boolean (doto (not (fc/field-value (:new? override)))
+ println))})}
hx/alpine-mount-then-appear)
(fc/with-field :db/id
(com/hidden {:name (fc/field-name)
@@ -378,19 +379,12 @@
:id "client-override-table"}
(fc/cursor-map
#(client-override* %))
- (com/data-grid-row
- {:class "new-row"}
- (com/data-grid-cell {:colspan 3
- :class "bg-gray-100"}
- [:div.flex.justify-center
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-account-client-override-new)
- :color :secondary
- :hx-include "#edit-form"
- :hx-vals (hiccup/raw "js:{index: countRows(\"#client-override-table\")}")
- :hx-target "#edit-form .new-row"
- :hx-swap "beforebegin"}
- "New override")])))))
+
+ (com/data-grid-new-row {:colspan 3
+ :index (count (fc/field-value))
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-account-client-override-new)}
+ "New override"))))
]
[:div
@@ -401,14 +395,13 @@
"Save account")])]])]))
(defn new-client-override [{ {:keys [index]} :query-params}]
- (let [index (or index 0)
- account {:account/client-overrides (conj (into [] (repeat index {}))
- {:db/id (str (java.util.UUID/randomUUID))
- :new? true})}] ;; TODO schema decode is not working
- (html-response
- (fc/start-form account []
- (fc/with-cursor (get-in fc/*current* [:account/client-overrides index])
- (client-override* fc/*current*))))))
+ (html-response
+ (fc/start-form-with-prefix
+ [:account/client-overrides (or index 0)]
+ {:db/id (str (java.util.UUID/randomUUID))
+ :new? true}
+ []
+ (client-override* fc/*current*))))
(defn account-edit-dialog [request]
(let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 16f7f10e..0b0060e9 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -543,31 +543,18 @@
: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"}
- (fc/cursor-map #(transaction-rule-account-row* entity %))
- (com/data-grid-row
- {:class "new-row"}
- (com/data-grid-cell {:colspan 4
- :class "bg-gray-100"}
- [:div.flex.justify-center
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-new-account)
- :color :secondary
- :hx-include "#edit-form"
- :hx-ext "rename-params"
- ;; TODO
- :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 "#edit-form .new-row"
- :hx-swap "beforebegin"}
- "New account")])))
- (com/errors {:errors (fc/field-errors)})))
+ (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"}
+ (fc/cursor-map #(transaction-rule-account-row* entity %))
+ (com/data-grid-new-row {:colspan 4
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :index (count (fc/field-value))
+ :tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
+ "New account")))
(fc/with-field :transaction-rule/transaction-approval-status
(com/validated-field {:label "Approval status"
@@ -578,7 +565,6 @@
:size :small
:orientation :horizontal})))
- ;; TODO componentize
]]
[:div
[:div#form-errors (when (:errors fc/*form-errors*)
@@ -593,21 +579,21 @@
;; pull out the single field to swap
(defn new-account [{{:keys [client-id index]} :query-params}]
- (let [index (or index 0) ;; TODO schema decode is not working
- transaction-rule {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
- client-id)
- :transaction-rule/accounts (conj (into [] (repeat index {} ))
- {:db/id (str (java.util.UUID/randomUUID))
- :transaction-rule-account/location "Shared"
- :new? true})}]
- (html-response
- (fc/start-form transaction-rule []
- (fc/with-cursor (get-in fc/*current* [:transaction-rule/accounts index])
- (transaction-rule-account-row*
- ;; TODO store a pointer to the "head " cursor for errors instead of nesting them
- ;; makes it so you don't have to do this
- transaction-rule
- fc/*current*))))))
+ (html-response
+ (fc/start-form-with-prefix
+ [:transaction-rule/accounts (or index 0)]
+ {:db/id (str (java.util.UUID/randomUUID))
+ :transaction-rule-account/location "Shared"
+ :new? true}
+ []
+ (transaction-rule-account-row*
+ ;; TODO store a pointer to the "head " cursor for errors instead of nesting them
+ ;; makes it so you don't have to do this
+
+ {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
+ client-id)}
+
+ fc/*current*))))
;; TODO check to see if it should be called "Shared" or "shared" for the value
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index cee70ef2..56c410c0 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -59,6 +59,7 @@
(def data-grid-row data-grid/row-)
(def data-grid-cell data-grid/cell-)
(def data-grid-right-stack-cell data-grid/right-stack-cell-)
+(def data-grid-new-row data-grid/new-row-)
(defn link [params & children]
(into [:a (update params :class str " font-medium text-blue-600 dark:text-blue-500 hover:underline ")]
diff --git a/src/clj/auto_ap/ssr/components/data_grid.clj b/src/clj/auto_ap/ssr/components/data_grid.clj
index caf91017..f62c7f12 100644
--- a/src/clj/auto_ap/ssr/components/data_grid.clj
+++ b/src/clj/auto_ap/ssr/components/data_grid.clj
@@ -3,8 +3,10 @@
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components.card :refer [content-card-]]
[auto-ap.ssr.components.paginator :refer [paginator-]]
+ [auto-ap.ssr.components.buttons :refer [a-button-]]
[bidi.bidi :as bidi]
- [hiccup2.core :as hiccup]))
+ [hiccup2.core :as hiccup]
+ [auto-ap.ssr.hx :as hx]))
(defn header- [params & rest]
(into [:th.px-4.py-3 {:scope "col" :class (:class params)
@@ -103,3 +105,23 @@
[:div {:class "htmx-indicator absolute -translate-x-1/2 -translate-y-1/2 top-2/4 left-1/2 overflow-hidden w-full h-full"}
[:div {:class "flex items-center justify-center w-full h-full border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700 bg-opacity-50" }
[:div {:class "px-3 py-1 text-xs font-medium leading-none text-center text-blue-800 bg-blue-200 rounded-full animate-pulse dark:bg-blue-900 dark:text-blue-200"} "loading..."]]])])
+
+(defn new-row- [{:keys [index colspan tr-params] :as params} & content]
+ (row-
+ (merge {:class "new-row"
+ :x-data (hx/json {:newRowIndex index})
+ }
+ tr-params)
+ (cell- {:colspan colspan
+ :class "bg-gray-100"}
+ [:div.flex.justify-center
+ (a-button- (merge
+ (dissoc params :index :colspan)
+ {
+ "@click" "$dispatch('newRow', {index: newRowIndex++})"
+ :color :secondary
+ :hx-trigger "newRow"
+ :hx-vals (hiccup/raw "js:{index: event.detail.index}")
+ :hx-target "closest .new-row"
+ :hx-swap "beforebegin"})
+ content)])))
diff --git a/src/clj/auto_ap/ssr/form_cursor.clj b/src/clj/auto_ap/ssr/form_cursor.clj
index 02c65ba4..536a3a2f 100644
--- a/src/clj/auto_ap/ssr/form_cursor.clj
+++ b/src/clj/auto_ap/ssr/form_cursor.clj
@@ -2,17 +2,26 @@
(:require [auto-ap.ssr.utils :refer [path->name2]]
[auto-ap.cursor :as cursor]))
+(def ^:dynamic *prefix* [])
(def ^:dynamic *form-data*)
(def ^:dynamic *form-errors*)
(def ^:dynamic *prev-cursor* nil)
(def ^:dynamic *current* nil)
+
+
(defmacro start-form [form-data errors & rest]
`(binding [*form-data* ~form-data
*form-errors* (or ~errors {})]
- (binding [*current* (cursor/cursor *form-data*)]
+ (binding [*current* (if (cursor/cursor? *form-data*)
+ *form-data*
+ (cursor/cursor *form-data*))]
~@rest)))
+(defmacro start-form-with-prefix [prefix form-data errors & rest]
+ `(binding [*prefix* ~prefix]
+ (start-form ~form-data ~errors ~@rest)))
+
(defmacro with-cursor [cursor & rest]
`(binding [*current* ~cursor]
~@rest))
@@ -24,7 +33,7 @@
(defn field-name
([] (field-name *current*))
([cursor]
- (apply path->name2 (cursor/path cursor))))
+ (apply path->name2 (into (or *prefix* []) (cursor/path cursor)))))
(defn field-value
([] (field-value *current*))
diff --git a/src/clj/auto_ap/ssr/hx.clj b/src/clj/auto_ap/ssr/hx.clj
index 895d024e..0a069362 100644
--- a/src/clj/auto_ap/ssr/hx.clj
+++ b/src/clj/auto_ap/ssr/hx.clj
@@ -32,9 +32,9 @@
"x-transition:leave-end" "opacity-0"))
(defn alpine-mount-then-appear [{:keys [data-key] :as params}]
- (merge (-> {"x-data" (json {data-key false})
- "x-init" (format "$nextTick(() => %s=true)" (name data-key))
- "x-show" (name data-key)}
+ (merge (-> {:x-data (json {data-key false})
+ :x-init (format "$nextTick(() => %s=true)" (name data-key))
+ :x-show (name data-key)}
alpine-appear
alpine-disappear)
(dissoc params :data-key)))
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index e225fef3..e1d90816 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -323,19 +323,11 @@
(com/data-grid-header {} )]
:id "client-table"}
(fc/cursor-map #(client-row* %))
- (com/data-grid-row
- {:class "new-row"}
- (com/data-grid-cell {:colspan 2
- :class "bg-gray-100"}
- [:div.flex.justify-center
- (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes
- :user-client-new)
- :color :secondary
- :hx-include "#edit-form"
- :hx-vals (hiccup/raw "js:{index: countRows(\"#client-table\")}")
- :hx-target "#edit-form .new-row"
- :hx-swap "beforebegin"}
- "New override")])))))]
+ (com/data-grid-new-row {:colspan 2
+ :index (count (fc/field-value))
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :user-client-new)}
+ "Assign new client"))))]
[:div
[:div [:div#form-errors (when (:errors fc/*form-errors*)
[:span.error-content
@@ -374,14 +366,10 @@
:headers {"hx-trigger" "modalopen"})))
(defn new-client [{ {:keys [index]} :query-params}]
- (let [index (or index 0)
- account {:user/clients (conj (into [] (repeat index {}))
- {:db/id nil
- :new? true})}] ;; TODO schema decode is not working
- (html-response
- (fc/start-form account []
- (fc/with-cursor (get-in fc/*current* [:user/clients index])
- (client-row* fc/*current*))))))
+ (html-response
+ (fc/start-form-with-prefix [:user/clients (or index 0)] {:db/id nil
+ :new? true} []
+ (client-row* fc/*current*))))
(def key->handler
(apply-middleware-to-all-handlers
From 91f7e79aed465d380e977b3a3ff5b482c359e6b7 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Tue, 24 Oct 2023 11:12:31 -0700
Subject: [PATCH 20/34] a lot of streamlining for validation
---
src/clj/auto_ap/ssr/admin/accounts.clj | 73 +++++------
.../auto_ap/ssr/admin/transaction_rules.clj | 117 ++++++++----------
src/clj/auto_ap/ssr/components.clj | 1 +
src/clj/auto_ap/ssr/components/dialog.clj | 12 +-
src/clj/auto_ap/ssr/components/inputs.clj | 6 +
src/clj/auto_ap/ssr/users.clj | 94 +++++++-------
src/clj/auto_ap/ssr/utils.clj | 26 ++--
7 files changed, 161 insertions(+), 168 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index ef48ae82..755b5460 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -31,12 +31,12 @@
ref->enum-schema
ref->select-options
temp-id
+ wrap-entity
wrap-form-4xx-2
wrap-schema-decode]]
[bidi.bidi :as bidi]
[clojure.string :as str]
[datomic.api :as dc]
- [hiccup2.core :as hiccup]
[malli.core :as mc]))
(defn filters [request]
@@ -291,16 +291,21 @@
;; ensure that adding a new one results in a new row
-(defn dialog* [& {:keys [entity form-params form-errors]}]
- (fc/start-form entity form-errors
- [:div {:x-data (hx/json {"accountName" (:account/name entity)
- "accountCode" (:account/numeric-code entity)})}
+(defn dialog* [{:keys [entity form-params form-errors]}]
+ (fc/start-form form-params form-errors
+ [:div {:x-data (hx/json {"accountName" (or (:account/name form-params) (:account/numeric-code entity))
+ "accountCode" (or (:account/numeric-code form-params) (:account/numeric-code entity) )})
+ :hx-target "this"}
(com/modal
{}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
- form-params)
+ [:form#edit-form (-> {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"}
+ (assoc (if (:db/id entity)
+ :hx-put
+ :hx-post)
+ (str (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-edit-save))))
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
@@ -318,6 +323,7 @@
(com/validated-field {:label "Numeric code"
:errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
+ :value (fc/field-value)
:x-model "accountCode"
:autofocus true
:class "w-32"}))
@@ -388,9 +394,7 @@
]
[:div
- [:div [:div#form-errors (when (:errors fc/*form-errors*)
- [:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})])]]
+ (com/form-errors {:errors (:errors fc/*form-errors*)})
(com/validated-save-button {:errors (seq form-errors)}
"Save account")])]])]))
@@ -403,34 +407,15 @@
[]
(client-override* fc/*current*))))
-(defn account-edit-dialog [request]
- (let [account (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
- (html-response (dialog* :entity account
- :form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
- :admin-account-edit-save))})
- :headers {"hx-trigger" "modalopen"})))
-
-
-(defn account-new-dialog [_]
- (html-response (dialog* :entity {}
- :form-errors {}
- :form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :admin-account-new-save))})
+(defn account-dialog [{:keys [entity form-params form-errors]}]
+ (html-response (dialog* {:entity entity
+ :form-params (or (when (seq form-params)
+ form-params)
+ entity
+ {})
+ :form-errors form-errors})
:headers {"hx-trigger" "modalopen"}))
-(defn account-save-error [request]
- ;; TODO hydration
- ;; TODO consistency of error handling and passing, on all form examples
- (let [entity (some-> request :last-form)]
- (html-response (dialog* :entity entity
- :form-errors (:form-errors request)
- :form-params (if (:db/id entity)
- {:hx-put (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))}
- {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))}))
- :headers {"hx-retarget" "#edit-form fieldset"
- "hx-reselect" "#edit-form fieldset"})))
(def account-schema (mc/schema
[:map
@@ -439,14 +424,14 @@
[:account/name [:string {:min 1}]]
[:account/location [:maybe :string]]
[:account/type (ref->enum-schema "account-type")]
- [:account/applicability (ref->enum-schema "account-applicability")]
+ [:account/applicability (ref->enum-schema "account-applicability")] ;
[:account/invoice-allowance (ref->enum-schema "allowance")]
[:account/vendor-allowance (ref->enum-schema "allowance")]
[:account/client-overrides {:optional true}
[:maybe
(many-entity {}
[:db/id [:or entity-id temp-id]]
- [:account-client-override/client [:or entity-id :string]]
+ [:account-client-override/client entity-id]
[:account-client-override/name [:string {:min 2}]])]]]))
(def key->handler
@@ -460,12 +445,14 @@
:default 0} [nat-int? {:default 0}]]])
wrap-admin wrap-client-redirect-unauthenticated)
:admin-account-save (-> account-save
+ (wrap-entity [:form-params :db/id] default-read)
(wrap-schema-decode :form-schema account-schema)
(wrap-nested-form-params)
- (wrap-form-4xx-2 account-save-error))
- :admin-account-edit-dialog (-> account-edit-dialog
+ (wrap-form-4xx-2 (wrap-entity account-dialog [:form-params :db/id] default-read)))
+ :admin-account-edit-dialog (-> account-dialog
+ (wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
- :admin-account-new-dialog account-new-dialog})
+ :admin-account-new-dialog account-dialog})
(fn [h]
(-> h
(wrap-admin)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 0b0060e9..841c2160 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -18,9 +18,9 @@
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.company :refer [bank-account-typeahead*]]
[auto-ap.ssr.components :as com]
+ [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.hx :as hx]
- [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.utils
@@ -31,24 +31,20 @@
html-response
many-entity
money
- path->name2
percentage
ref->enum-schema
ref->radio-options
regex
temp-id
+ wrap-entity
wrap-form-4xx-2
wrap-schema-decode]]
[auto-ap.utils :refer [dollars=]]
[bidi.bidi :as bidi]
- [cheshire.core :as cheshire]
[clojure.string :as str]
[datomic.api :as dc]
- [hiccup2.core :as hiccup]
[iol-ion.query :refer [ident]]
- [malli.core :as mc]
- [auto-ap.cursor :as cursor]
- [auto-ap.ssr.hiccup-helper :as hh]))
+ [malli.core :as mc]))
;; TODO with dependencies, I really don't like that you have to be ultra specific in what
;; you want to include, and generating the routes and interconnection is weird too.
@@ -401,25 +397,29 @@
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
;; TODO dialog is no longer closeable
-(defn dialog* [& {:keys [entity form-params form-errors]}]
- (fc/start-form entity form-errors
+;; TODO might not need #edit-form id
+(defn dialog* [{:keys [entity form-params form-errors]}]
+ (fc/start-form form-params form-errors
(com/modal
- {:modal-class "max-w-2xl"}
+ {:modal-class "max-w-2xl"
+ :hx-target "this"}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target "#modal-holder" ;; TODO sort
- :hx-target-400 "#form-errors .error-content"
- :x-trap "true"
- :class "group/form"}
- form-params)
+ [:form#edit-form {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :x-trap "true"
+ :class "group/form"
+ (if (:db/id entity)
+ :hx-put
+ :hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
(com/modal-card
{}
[:div.flex [:div.p-2 "Transaction Rule"]]
[:fieldset {:class "hx-disable"
:hx-disinherit "hx-target" ;; TODO why disinherit
- :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity))
- (:transaction-rule/client entity))})}
+ :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client form-params))
+ (:transaction-rule/client form-params)
+ (:db/id (:transaction-rule/client entity)))})}
[:div.space-y-1
(when-let [id (:db/id entity)]
@@ -486,7 +486,7 @@
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
:x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
- (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity))
+ (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client form-params))
:name (fc/field-name)
:value (fc/field-value)})]))
@@ -543,18 +543,20 @@
:content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})]))
(fc/with-field :transaction-rule/accounts
- (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"}
- (fc/cursor-map #(transaction-rule-account-row* entity %))
- (com/data-grid-new-row {:colspan 4
- :hx-get (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-new-account)
- :index (count (fc/field-value))
- :tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
- "New account")))
+ (com/validated-field
+ {:errors (fc/field-errors)}
+ (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"}
+ (fc/cursor-map #(transaction-rule-account-row* form-params %))
+ (com/data-grid-new-row {:colspan 4
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :index (count (fc/field-value))
+ :tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
+ "New account"))))
(fc/with-field :transaction-rule/transaction-approval-status
(com/validated-field {:label "Approval status"
@@ -567,10 +569,8 @@
]]
[:div
- [:div#form-errors (when (:errors fc/*form-errors*)
- [:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})])]
- (com/validated-save-button {:errors form-errors} "Save rule")])])))
+ (com/form-errors {:errors (:errors fc/*form-errors*)})
+ (com/validated-save-button {:errors (:errors form-errors)} "Save rule")])])))
;; TODO Should forms have some kind of helper to render an individual field? saving
@@ -619,34 +619,14 @@
:value account
:client-id client-id}))))
-(defn transaction-rule-edit-dialog [request]
- (let [entity (or
- (some-> request :last-form)
- (some-> request :route-params :db/id (#(dc/pull (dc/db conn) default-read %))))]
- (html-response (dialog* :entity entity
- :form-params {:hx-put (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))})
- :headers {"hx-trigger-after-settle" "modalopen"})))
-
-(defn transaction-rule-error [request]
- (let [entity (some-> request :last-form)]
- (html-response (dialog* :entity entity
- :form-errors (:form-errors request)
- :form-params (if (:db/id entity)
- {:hx-put (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))}
- {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))}))
- :headers {"hx-retarget" "#edit-form fieldset"
- "hx-reselect" "#edit-form fieldset"})))
-
-
-(defn transaction-rule-new-dialog [_]
- (html-response (dialog* :entity {}
- :form-errors {}
- :form-params {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))})
- :headers {"hx-trigger-after-settle" "modalopen"}))
+(defn transaction-dialog [{:keys [entity form-params form-errors]}]
+ (html-response (dialog* {:entity entity
+ :form-params (or (when (seq form-params)
+ form-params)
+ entity ;; TODO coerce into form params
+ {})
+ :form-errors form-errors})
+ :headers {"hx-trigger" "modalopen"}))
(def transaction-rule-schema (mc/schema
[:map
@@ -695,12 +675,15 @@
[:value {:optional true}
[:maybe entity-id]]]))
:admin-transaction-rule-save (-> transaction-rule-save
+ (wrap-entity [:form-params :db/id] default-read)
(wrap-schema-decode :form-schema transaction-rule-schema)
(wrap-nested-form-params)
- (wrap-form-4xx-2 transaction-rule-error))
- :admin-transaction-rule-edit-dialog (-> transaction-rule-edit-dialog
+ (wrap-form-4xx-2 (-> transaction-dialog
+ (wrap-entity [:form-params :db/id] default-read))))
+ :admin-transaction-rule-edit-dialog (-> transaction-dialog
+ (wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
- :admin-transaction-rule-new-dialog transaction-rule-new-dialog})
+ :admin-transaction-rule-new-dialog transaction-dialog})
(fn [h]
(-> h
(wrap-admin)
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index 56c410c0..305afc49 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -37,6 +37,7 @@
(def field inputs/field-)
(def validated-field inputs/validated-field-)
(def errors inputs/errors-)
+(def form-errors inputs/form-errors-)
(def left-aside aside/left-aside-)
(def company-aside-nav aside/company-aside-nav-)
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index d2109e35..3ee49af6 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -4,11 +4,13 @@
[auto-ap.ssr.hiccup-helper :as hh]))
(defn modal- [params & children]
- [:div {:class (-> (:class params)
- (or "max-w-4xl w-1/4 overflow-visible")
- (hh/add-class "h-min"))
- "@click.outside" "open=false"
- } children])
+ [:div (-> params
+ (update :class #(-> %
+ (or "max-w-4xl w-1/4 overflow-visible")
+ (hh/add-class "h-min")))
+
+ (assoc "@click.outside" "open=false"))
+ children])
(defn modal-card- [params header content footer]
[:div#modal-card (update params
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index 2704c2b6..02251640 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -152,6 +152,7 @@ c.clearChoices();
[:input
(-> params
(dissoc :error?)
+ (assoc :type "text")
(update
:class (fnil hh/add-class "") default-input-classes)
(update :class #(str % (use-size size))))])
@@ -210,6 +211,11 @@ c.clearChoices();
(when (sequential? errors)
(str/join ", " (filter string? errors)))])
+(defn form-errors- [{:keys [errors]}]
+ [:div#form-errors (when errors
+ [:span.error-content
+ (errors- {:errors errors})])])
+
(defn validated-field- [params & rest]
(field- (cond-> params
true (dissoc :errors)
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index e1d90816..26f90161 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -26,6 +26,7 @@
many-entity
ref->enum-schema
ref->select-options
+ wrap-entity
wrap-form-4xx-2
wrap-schema-decode]]
[auto-ap.time :as atime]
@@ -34,9 +35,7 @@
[clojure.string :as str]
[config.core :refer [env]]
[datomic.api :as dc]
- [hiccup2.core :as hiccup]
- [malli.core :as mc]
- [clj-time.format :as f]))
+ [malli.core :as mc]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
@@ -257,14 +256,17 @@
(def table* (partial helper/table* grid-page))
(defn impersonate [request]
- (let [user (some-> request :params :db/id (#(dc/pull (dc/db conn) default-read %))) ]
+ (println (:entity request))
+ (if (:entity request)
{:status 200
- :headers {"hx-redirect" (str "/?jwt=" (jwt/sign (auth/user->jwt user "FAKE_TOKEN")
- (:jwt-secret env)
- {:alg :hs512}))
+ :headers {"hx-redirect" (str "/?jwt=" (jwt/sign (auth/user->jwt (:entity request) "FAKE_TOKEN")
+ (:jwt-secret env)
+ {:alg :hs512}))
}
- :session {:identity (dissoc (auth/user->jwt user "FAKE_TOKEN")
- :exp)}}))
+ :session {:identity (dissoc (auth/user->jwt (:entity request) "FAKE_TOKEN")
+ :exp)}}
+ {:status 404}))
+
(defn client-row* [client]
(com/data-grid-row (-> {:x-ref "p"
:data-key "show"
@@ -288,19 +290,20 @@
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
-(defn dialog* [{:keys [entity form-params form-errors]}]
+
+;; TODO hydrate user name
+(defn dialog* [{:keys [form-params form-errors entity]}]
(fc/start-form
- entity form-errors
+ form-params form-errors
(com/modal
- {}
- [:form#edit-form (merge {:hx-ext "response-targets"
- :hx-put (str (bidi/path-for ssr-routes/only-routes
- :user-edit-save
- :request-method :put))
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"
- :class "w-full"}
- form-params)
+ {:hx-target "this"}
+ [:form#edit-form {:hx-ext "response-targets"
+ :hx-put (str (bidi/path-for ssr-routes/only-routes
+ :user-edit-save
+ :request-method :put))
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :class "w-full"}
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
@@ -329,9 +332,7 @@
:user-client-new)}
"Assign new client"))))]
[:div
- [:div [:div#form-errors (when (:errors fc/*form-errors*)
- [:span.error-content
- (com/errors {:errors (:errors fc/*form-errors*)})])]]
+ (com/form-errors {:errors (:errors fc/*form-errors*)})
(com/validated-save-button {:errors (seq form-errors)}
"Save user")])]])))
@@ -348,22 +349,17 @@
(defn user-save-error [request]
;; TODO hydration
;; TODO consistency of error handling and passing, on all form examples
- (let [entity (some-> request :last-form)]
- (html-response (dialog* {:entity entity
- :form-errors (:form-errors request)})
- :headers {"hx-retarget" "#edit-form fieldset"
- "hx-reselect" "#edit-form fieldset"})))
+ (html-response (dialog* {:form-params (:form-params request)
+ :entity (:entity request)
+ :form-errors (:form-errors request)})))
(defn user-edit-dialog [request]
- (let [user (some-> request
- :route-params
- :db/id
- (#(dc/pull (dc/db conn) default-read %)))]
- (html-response
- (dialog* {:entity user
- :form-errors {}})
-
- :headers {"hx-trigger" "modalopen"})))
+ (html-response
+ (dialog* {:form-params (:entity request)
+ :entity (:entity request)
+ :form-errors {}})
+
+ :headers {"hx-trigger" "modalopen"}))
(defn new-client [{ {:keys [index]} :query-params}]
(html-response
@@ -371,28 +367,34 @@
:new? true} []
(client-row* fc/*current*))))
+(def user-form-schema
+ (mc/schema
+ [:map
+ [:db/id entity-id]
+ [:user/clients {:optional true}
+ [:maybe
+ (many-entity {} [:db/id entity-id])]]
+ [:user/role (ref->enum-schema "user-role")]]))
+
(def key->handler
(apply-middleware-to-all-handlers
{:users (helper/page-route grid-page)
:user-table (helper/table-route grid-page)
:user-edit-save (-> user-edit-save
- (wrap-schema-decode :form-schema (mc/schema
- [:map
- [:db/id entity-id]
- [:user/clients {:optional true}
- [:maybe
- (many-entity {} [:db/id entity-id])]]
- [:user/role (ref->enum-schema "user-role")]]))
+ (wrap-entity [:form-params :db/id] default-read)
+ (wrap-schema-decode :form-schema user-form-schema)
(wrap-nested-form-params)
- (wrap-form-4xx-2 user-save-error))
- :user-client-new (-> new-client
+ (wrap-form-4xx-2 (wrap-entity user-save-error [:form-params :db/id] default-read)))
+ :user-client-new (-> new-client
(wrap-schema-decode :query-schema [:map
[:index {:optional true
:default 0} [nat-int? {:default 0}]]]))
:user-edit-dialog (-> user-edit-dialog
+ (wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode
:route-schema (mc/schema [:map [:db/id entity-id]])))
:user-impersonate (-> impersonate
+ (wrap-entity [:params :db/id] default-read)
(wrap-schema-decode
:params-schema (mc/schema [:map [:db/id entity-id]])))}
(fn [h]
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index b80c08bd..6cbdfa0f 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -1,15 +1,15 @@
(ns auto-ap.ssr.utils
(:require
- [auto-ap.datomic :refer [all-schema]]
+ [auto-ap.datomic :refer [all-schema conn]]
[auto-ap.logging :as alog]
[clojure.string :as str]
[config.core :refer [env]]
+ [datomic.api :as dc]
[hiccup2.core :as hiccup]
[malli.core :as mc]
[malli.error :as me]
[malli.transform :as mt2]
- [slingshot.slingshot :refer [throw+ try+]]
- [manifold.time :as mt]))
+ [slingshot.slingshot :refer [throw+ try+]]))
(defn html-response [hiccup & {:keys [status headers oob] :or {status 200 headers {} oob []}}]
{:status status
@@ -99,7 +99,7 @@
(def entity-id (mc/schema [nat-int? {:error/message "required"} ]))
-(def temp-id (mc/schema :string))
+(def temp-id (mc/schema [:string {:min 1}]))
(def money (mc/schema [:double]))
(def percentage (mc/schema [:double {:decode/arbitrary (fn [x] (some-> x (* 0.01)))
:max 1.0
@@ -292,18 +292,18 @@
(:errors (:explain (:error e))))]
(alog/warn ::form-4xx :errors errors)
(form-handler (assoc request
- :last-form (:decoded e)
+ :form-params (:decoded e)
:field-validation-errors errors
:form-errors humanized)))
#_(html-response [:span.error-content.text-red-500 (:message &throw-context)]
:status 400))
(catch [:type :field-validation] e
(form-handler (assoc request
- :last-form (:form e)
+ :form-params (:form e)
:form-errors (:form-errors e))))
(catch [:type :form-validation] e
(form-handler (assoc request
- :last-form (:form e)
+ :form-params (:form e)
:form-validation-errors (:form-validation-errors e)
:form-errors {:errors (:form-validation-errors e)}))))))
@@ -326,3 +326,15 @@
(map (fn [k]
(str "[" (k->n k) "]"))
rest)))))
+
+
+(defn wrap-entity [handler path read]
+ (fn wrap-entity-request [request]
+ (let [entity (some->>
+ (get-in request path)
+ (#(if (string? %) (Long/parseLong %) %))
+ (dc/pull (dc/db conn) read ))]
+ (handler (if entity
+ (assoc request
+ :entity entity)
+ request)))))
From a8cce0377dce7ba5e7605d563066cfdab4d16ab6 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Tue, 24 Oct 2023 11:52:55 -0700
Subject: [PATCH 21/34] lots of progress
---
src/clj/auto_ap/square/core3.clj | 8 ++
src/clj/auto_ap/ssr/admin/accounts.clj | 57 +++++-----
src/clj/auto_ap/ssr/admin/background_jobs.clj | 32 +++---
.../auto_ap/ssr/admin/transaction_rules.clj | 104 ++++++++----------
src/clj/auto_ap/ssr/components/buttons.clj | 2 +-
src/clj/auto_ap/ssr/components/inputs.clj | 6 +-
src/clj/auto_ap/ssr/hx.clj | 12 ++
src/clj/auto_ap/ssr/users.clj | 73 ++++++------
src/clj/auto_ap/ssr/utils.clj | 31 ++++--
9 files changed, 170 insertions(+), 155 deletions(-)
diff --git a/src/clj/auto_ap/square/core3.clj b/src/clj/auto_ap/square/core3.clj
index d9c1e916..55cdf61a 100644
--- a/src/clj/auto_ap/square/core3.clj
+++ b/src/clj/auto_ap/square/core3.clj
@@ -767,6 +767,14 @@
(dc/db conn)
codes))))
+(defn get-square-client-and-location [code]
+ (let [[client] (get-square-clients code)]
+ (some->> client
+ :client/square-locations
+ (filter :square-location/client-location)
+ seq
+ (conj [client]))))
+
(defn upsert-locations
([]
(apply de/zip
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 755b5460..3e95993e 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -27,6 +27,7 @@
field-validation-error
form-validation-error
html-response
+ main-transformer
many-entity
ref->enum-schema
ref->select-options
@@ -263,10 +264,7 @@
:url (bidi/path-for ssr-routes/only-routes
:company-search)
:value (fc/field-value)
- :value-fn (some-fn :db/id identity) ;; TODO better hydration
- :content-fn (fn [value]
- (:client/name (cond->> value
- (nat-int? value) (dc/pull (dc/db conn) [:client/name]))))}))))
+ :content-fn #(pull-attr (dc/db conn) :client/name %)}))))
(fc/with-field :account-client-override/name
(com/data-grid-cell
{}
@@ -298,14 +296,14 @@
:hx-target "this"}
(com/modal
{}
- [:form#edit-form (-> {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
- (assoc (if (:db/id entity)
- :hx-put
- :hx-post)
- (str (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-edit-save))))
+ [:form (-> {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"}
+ (assoc (if (:db/id entity)
+ :hx-put
+ :hx-post)
+ (str (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-edit-save))))
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
@@ -323,7 +321,7 @@
(com/validated-field {:label "Numeric code"
:errors (fc/field-errors)}
(com/text-input {:name (fc/field-name)
- :value (fc/field-value)
+ :value (fc/field-value)
:x-model "accountCode"
:autofocus true
:class "w-32"}))
@@ -382,13 +380,13 @@
(com/data-grid {:headers [(com/data-grid-header {} "Client")
(com/data-grid-header {} "Account name")
(com/data-grid-header {})]
- :id "client-override-table"}
+ :id "client-override-table"}
(fc/cursor-map
#(client-override* %))
(com/data-grid-new-row {:colspan 3
- :index (count (fc/field-value))
- :hx-get (bidi/path-for ssr-routes/only-routes
+ :index (count (fc/field-value))
+ :hx-get (bidi/path-for ssr-routes/only-routes
:admin-account-client-override-new)}
"New override"))))
@@ -407,17 +405,7 @@
[]
(client-override* fc/*current*))))
-(defn account-dialog [{:keys [entity form-params form-errors]}]
- (html-response (dialog* {:entity entity
- :form-params (or (when (seq form-params)
- form-params)
- entity
- {})
- :form-errors form-errors})
- :headers {"hx-trigger" "modalopen"}))
-
-
-(def account-schema (mc/schema
+(def form-schema (mc/schema
[:map
[:db/id {:optional true} [:maybe entity-id]]
[:account/numeric-code {:optional true} [:maybe :int]]
@@ -434,6 +422,19 @@
[:account-client-override/client entity-id]
[:account-client-override/name [:string {:min 2}]])]]]))
+(defn account-dialog [{:keys [entity form-params form-errors]}]
+ (html-response (dialog* {:entity entity
+ :form-params (or (when (seq form-params)
+ form-params)
+ (when entity
+ (mc/decode form-schema entity main-transformer))
+ {})
+ :form-errors form-errors})
+ :headers {"hx-trigger" "modalopen"}))
+
+
+
+
(def key->handler
(apply-middleware-to-all-handlers
(->>
@@ -446,7 +447,7 @@
wrap-admin wrap-client-redirect-unauthenticated)
:admin-account-save (-> account-save
(wrap-entity [:form-params :db/id] default-read)
- (wrap-schema-decode :form-schema account-schema)
+ (wrap-schema-decode :form-schema form-schema)
(wrap-nested-form-params)
(wrap-form-4xx-2 (wrap-entity account-dialog [:form-params :db/id] default-read)))
:admin-account-edit-dialog (-> account-dialog
diff --git a/src/clj/auto_ap/ssr/admin/background_jobs.clj b/src/clj/auto_ap/ssr/admin/background_jobs.clj
index d468010f..58f4bb47 100644
--- a/src/clj/auto_ap/ssr/admin/background_jobs.clj
+++ b/src/clj/auto_ap/ssr/admin/background_jobs.clj
@@ -184,11 +184,11 @@
(defn job-start-dialog [_]
(html-response (com/modal
{:modal-class "max-w-4xl"}
- [:form#edit-form {:hx-ext "response-targets"
- :hx-post (bidi/path-for ssr-routes/only-routes :admin-job-start
- )
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
+ [:form {:hx-ext "response-targets"
+ :hx-post (bidi/path-for ssr-routes/only-routes :admin-job-start
+ )
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"}
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
@@ -199,18 +199,18 @@
(com/select {:name "name"
:class "w-64"
:options [["" ""]
- ["yodlee2" "Yodlee Import"]
- ["yodlee2-accounts" "Yodlee Account Import"]
- ["intuit" "Intuit import"]
- ["plaid" "Plaid import"]
- ["bulk-journal-import" "Bulk Journal Import"]
- ["square2-import-job" "Square2 Import"]
- ["register-invoice-import" "Register Invoice Import "]
- ["ezcater-upsert" "Upsert recent ezcater orders"]
- ["load-historical-sales" "Load Historical Square Sales"]
- ["export-backup" "Export Backup"]]
+ ["yodlee2" "Yodlee Import"]
+ ["yodlee2-accounts" "Yodlee Account Import"]
+ ["intuit" "Intuit import"]
+ ["plaid" "Plaid import"]
+ ["bulk-journal-import" "Bulk Journal Import"]
+ ["square2-import-job" "Square2 Import"]
+ ["register-invoice-import" "Register Invoice Import "]
+ ["ezcater-upsert" "Upsert recent ezcater orders"]
+ ["load-historical-sales" "Load Historical Square Sales"]
+ ["export-backup" "Export Backup"]]
:hx-get (bidi/path-for ssr-routes/only-routes
- :admin-job-subform)
+ :admin-job-subform)
:hx-target "#sub-form"
:hx-swap "innerHTML"}))
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 841c2160..383a2f18 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -29,6 +29,7 @@
field-validation-error
form-validation-error
html-response
+ main-transformer
many-entity
money
percentage
@@ -66,8 +67,9 @@
:url (bidi/path-for ssr-routes/only-routes
:vendor-search)
:id (str "vendor-search")
- :value [(:db/id (:vendor (:parsed-query-params request)))
- (:vendor/name (:vendor (:parsed-query-params request)))]}))
+ :value (:vendor (:parsed-query-params request))
+ :value-fn :db/id
+ :content-fn :vendor/name}))
(com/field {:label "Note"}
(com/text-input {:name "note"
:id "note"
@@ -330,12 +332,11 @@
:id name
:x-model x-model
:value value
- :value-fn (some-fn :db/id identity)
:content-fn (fn [value]
- (:account/name (d-accounts/clientize (cond->> value
- (nat-int? value) (dc/pull (dc/db conn) d-accounts/default-read))
+ (:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
client-id)))})])
+;; TODO something is making the accountId not change the location for only existing ones?
(defn- transaction-rule-account-row*
[transaction-rule account]
(com/data-grid-row (-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
@@ -363,8 +364,7 @@
(account-typeahead* {:value (fc/field-value)
:client-id (:db/id (:transaction-rule/client transaction-rule))
:name (fc/field-name)
- :x-model "accountId"
- }))))
+ :x-model "accountId"}))))
(fc/with-field :transaction-rule-account/location
(com/data-grid-cell
{}
@@ -396,22 +396,21 @@
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
-;; TODO dialog is no longer closeable
-;; TODO might not need #edit-form id
+;; TODO background jobs and company 1099
(defn dialog* [{:keys [entity form-params form-errors]}]
(fc/start-form form-params form-errors
(com/modal
{:modal-class "max-w-2xl"
:hx-target "this"}
- [:form#edit-form {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"
- :x-trap "true"
- :class "group/form"
- (if (:db/id entity)
- :hx-put
- :hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
+ [:form {:hx-ext "response-targets"
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :x-trap "true"
+ :class "group/form"
+ (if (:db/id entity)
+ :hx-put
+ :hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
(com/modal-card
{}
[:div.flex [:div.p-2 "Transaction Rule"]]
@@ -465,10 +464,7 @@
:url (bidi/path-for ssr-routes/only-routes :company-search)
:x-model "clientId"
: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))})]))
+ :content-fn (fn [c] (pull-attr (dc/db conn) :client/name c))})]))
(fc/with-field :transaction-rule/bank-account
(com/validated-field
@@ -536,11 +532,9 @@
(com/typeahead-2 {:name (fc/field-name)
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
- :id (str "form-vendor-search")
:class "w-96"
:value (fc/field-value)
- :value-fn (some-fn :db/id identity)
- :content-fn (some-fn :vendor/name #(pull-attr (dc/db conn) :vendor/name %))})]))
+ :content-fn #(pull-attr (dc/db conn) :vendor/name %)})]))
(fc/with-field :transaction-rule/accounts
(com/validated-field
@@ -573,11 +567,6 @@
(com/validated-save-button {:errors (:errors form-errors)} "Save rule")])])))
-;; TODO Should forms have some kind of helper to render an individual field? saving
-;; could generate the entire form and swap if there are errors
-;; but also when you tab out it could call the same function, and just
-;; pull out the single field to swap
-
(defn new-account [{{:keys [client-id index]} :query-params}]
(html-response
(fc/start-form-with-prefix
@@ -598,16 +587,14 @@
;; TODO check to see if it should be called "Shared" or "shared" for the value
;; TODO hydrate nested types more easily. make it easy to hydrate so you don't do weird sometimes pulls
-;; TODO is it possible to make it easy to get a virtual cursor in the case of adding a new row? setting up
-;; fake data doesn't feel right - maybe have a "prelude" that's dynamic
(defn location-select [{{:keys [name account-id client-id value] :as qp} :query-params}]
(html-response (location-select* {:name name
:value value
:account-location (some->> account-id
- (pull-attr (dc/db conn) :account/location))
+ (pull-attr (dc/db conn) :account/location))
:client-locations (some->> client-id
- (pull-attr (dc/db conn) :client/locations))})))
+ (pull-attr (dc/db conn) :client/locations))})))
(defn account-typeahead [{{:keys [name value client-id] :as qp} :query-params}]
(let [account (some->> value (dc/pull (dc/db conn) [:account/name :db/id
@@ -619,34 +606,37 @@
:value account
:client-id client-id}))))
+(def form-schema (mc/schema
+ [:map
+ [:db/id {:optional true} [:maybe entity-id]]
+ [:transaction-rule/client {:optional true} [:maybe entity-id]]
+ [:transaction-rule/description [:and regex
+ [:string {:min 3}]]]
+ [:transaction-rule/bank-account [:maybe entity-id]]
+ [:transaction-rule/amount-gte {:optional true} [:maybe money]]
+ [:transaction-rule/amount-lte {:optional true} [:maybe money]]
+ [:transaction-rule/dom-gte {:optional true} [:maybe :int]]
+ [:transaction-rule/dom-lte {:optional true} [:maybe :int]]
+ [:transaction-rule/vendor {:optional true} [:maybe entity-id]]
+ [:transaction-rule/transaction-approval-status (ref->enum-schema "transaction-approval-status")]
+ [:transaction-rule/accounts
+ (many-entity {:min 1}
+ [:db/id [:or entity-id temp-id]]
+ [:transaction-rule-account/account entity-id]
+ [:transaction-rule-account/location [:string {:min 1 :error/message "required"}]]
+ [:transaction-rule-account/percentage percentage])]]))
+
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
(html-response (dialog* {:entity entity
:form-params (or (when (seq form-params)
form-params)
- entity ;; TODO coerce into form params
+ (when entity
+ (mc/decode form-schema entity main-transformer)) ;; TODO coerce into form params
{})
:form-errors form-errors})
:headers {"hx-trigger" "modalopen"}))
-(def transaction-rule-schema (mc/schema
- [:map
- [:db/id {:optional true} [:maybe entity-id]]
- [:transaction-rule/client {:optional true} [:maybe entity-id]]
- [:transaction-rule/description [:and regex
- [:string {:min 3}]]]
- [:transaction-rule/bank-account [:maybe entity-id]]
- [:transaction-rule/amount-gte {:optional true} [:maybe money]]
- [:transaction-rule/amount-lte {:optional true} [:maybe money]]
- [:transaction-rule/dom-gte {:optional true} [:maybe :int]]
- [:transaction-rule/dom-lte {:optional true} [:maybe :int]]
- [:transaction-rule/vendor {:optional true} [:maybe entity-id]]
- [:transaction-rule/transaction-approval-status (ref->enum-schema "transaction-approval-status")]
- [:transaction-rule/accounts
- (many-entity {:min 1}
- [:db/id [:or entity-id temp-id]]
- [:transaction-rule-account/account entity-id]
- [:transaction-rule-account/location [:string {:min 1 :error/message "required"}]]
- [:transaction-rule-account/percentage percentage])]]))
+
(def key->handler
(apply-middleware-to-all-handlers
@@ -676,10 +666,10 @@
[:maybe entity-id]]]))
:admin-transaction-rule-save (-> transaction-rule-save
(wrap-entity [:form-params :db/id] default-read)
- (wrap-schema-decode :form-schema transaction-rule-schema)
- (wrap-nested-form-params)
- (wrap-form-4xx-2 (-> transaction-dialog
- (wrap-entity [:form-params :db/id] default-read))))
+ (wrap-schema-decode :form-schema form-schema)
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 (-> transaction-dialog
+ (wrap-entity [:form-params :db/id] default-read))))
:admin-transaction-rule-edit-dialog (-> transaction-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj
index 9df54b67..d23281d7 100644
--- a/src/clj/auto_ap/ssr/components/buttons.clj
+++ b/src/clj/auto_ap/ssr/components/buttons.clj
@@ -176,7 +176,7 @@
(defn validated-save-button- [{:keys [errors class] :as params} & children]
- (button- (-> {:color :primary :form "edit-form"
+ (button- (-> {:color :primary
:type "submit" :class (cond-> (or class "")
true (hh/add-class "w-32")
(seq errors) (hh/add-class "animate-shake"))}
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index 02251640..c42f82ed 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -75,11 +75,11 @@ c.clearChoices();
:baseUrl (if (str/includes? (:url params) "?")
(str (:url params) "&q=")
(str (:url params) "?q="))
- :value {:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}
+ :value {:value ((:value-fn params identity) (:value params)) :label ((:content-fn params identity) (:value params))}
:search ""
:active -1
- :elements (if ((:value-fn params first) (:value params))
- [{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}]
+ :elements (if ((:value-fn params identity) (:value params))
+ [{:value ((:value-fn params identity) (:value params)) :label ((:content-fn params identity) (:value params))}]
[])})
:x-modelable "value.value"
:x-model (:x-model params)
diff --git a/src/clj/auto_ap/ssr/hx.clj b/src/clj/auto_ap/ssr/hx.clj
index 0a069362..370e27b3 100644
--- a/src/clj/auto_ap/ssr/hx.clj
+++ b/src/clj/auto_ap/ssr/hx.clj
@@ -38,3 +38,15 @@
alpine-appear
alpine-disappear)
(dissoc params :data-key)))
+
+(defn bind-alpine-vals [m field->alpine-field]
+ (assoc m "x-bind:hx-vals"
+
+ (format "JSON.stringify({%s})"
+ (str/join ", "
+ (map
+ (fn [[field alpine-field]]
+ (format "\"%s\": $data.%s" field alpine-field))
+
+ field->alpine-field)))))
+
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 26f90161..3040f057 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -6,6 +6,7 @@
apply-sort-3
conn
merge-query
+ pull-attr
pull-many
query2]]
[auto-ap.query-params :as query-params]
@@ -23,6 +24,7 @@
:refer [apply-middleware-to-all-handlers
entity-id
html-response
+ main-transformer
many-entity
ref->enum-schema
ref->select-options
@@ -256,13 +258,11 @@
(def table* (partial helper/table* grid-page))
(defn impersonate [request]
- (println (:entity request))
(if (:entity request)
{:status 200
:headers {"hx-redirect" (str "/?jwt=" (jwt/sign (auth/user->jwt (:entity request) "FAKE_TOKEN")
(:jwt-secret env)
- {:alg :hs512}))
- }
+ {:alg :hs512}))}
:session {:identity (dissoc (auth/user->jwt (:entity request) "FAKE_TOKEN")
:exp)}}
{:status 404}))
@@ -279,31 +279,27 @@
:url (bidi/path-for ssr-routes/only-routes
:company-search)
:value (fc/field-value)
+ :value-fn :db/id
- :value-fn :db/id ;; TODO better hydration
- :content-fn (fn [value]
- (:client/name (dc/pull (dc/db conn) [:client/name]
- (or (:db/id value)
- value))))
+ :content-fn #(pull-attr (dc/db conn) :client/name (:db/id %))
:size :small})))
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
-;; TODO hydrate user name
(defn dialog* [{:keys [form-params form-errors entity]}]
(fc/start-form
form-params form-errors
(com/modal
{:hx-target "this"}
- [:form#edit-form {:hx-ext "response-targets"
- :hx-put (str (bidi/path-for ssr-routes/only-routes
- :user-edit-save
- :request-method :put))
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"
- :class "w-full"}
+ [:form {:hx-ext "response-targets"
+ :hx-put (str (bidi/path-for ssr-routes/only-routes
+ :user-edit-save
+ :request-method :put))
+ :hx-swap "outerHTML swap:300ms"
+ :hx-target-400 "#form-errors .error-content"
+ :class "w-full"}
[:fieldset {:class "hx-disable"}
(com/modal-card
{}
@@ -321,7 +317,7 @@
:value (some->> (fc/field-value) name)
:options (ref->select-options "user-role")})))
(fc/with-field :user/clients
- (com/validated-field {:label "Clients"}
+ (com/validated-field {:label "Clients"}
(com/data-grid {:headers [(com/data-grid-header {} "Client")
(com/data-grid-header {} )]
:id "client-table"}
@@ -336,7 +332,6 @@
(com/validated-save-button {:errors (seq form-errors)}
"Save user")])]])))
-;; TODO rename edit-form or make it generic
(defn user-edit-save [{:keys [form-params identity] :as request}]
(let [_ @(dc/transact conn [[:upsert-entity form-params]])
user (some-> form-params :db/id (#(dc/pull (dc/db conn) default-read %)))]
@@ -346,18 +341,25 @@
:headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#user-table tr[data-id=\"%d\"]" (:db/id user))})))
-(defn user-save-error [request]
- ;; TODO hydration
- ;; TODO consistency of error handling and passing, on all form examples
- (html-response (dialog* {:form-params (:form-params request)
- :entity (:entity request)
- :form-errors (:form-errors request)})))
-(defn user-edit-dialog [request]
+(def form-schema
+ (mc/schema
+ [:map
+ [:db/id entity-id]
+ [:user/clients {:optional true}
+ [:maybe
+ (many-entity {} [:db/id entity-id])]]
+ [:user/role (ref->enum-schema "user-role")]]))
+
+(defn user-dialog [{:keys [form-params entity form-errors]}]
(html-response
- (dialog* {:form-params (:entity request)
- :entity (:entity request)
- :form-errors {}})
+ (dialog* {:form-params (or (when (seq form-params)
+ form-params)
+ (when entity
+ (mc/decode form-schema entity main-transformer))
+ {})
+ :entity entity
+ :form-errors form-errors})
:headers {"hx-trigger" "modalopen"}))
@@ -367,14 +369,7 @@
:new? true} []
(client-row* fc/*current*))))
-(def user-form-schema
- (mc/schema
- [:map
- [:db/id entity-id]
- [:user/clients {:optional true}
- [:maybe
- (many-entity {} [:db/id entity-id])]]
- [:user/role (ref->enum-schema "user-role")]]))
+
(def key->handler
(apply-middleware-to-all-handlers
@@ -382,14 +377,14 @@
:user-table (helper/table-route grid-page)
:user-edit-save (-> user-edit-save
(wrap-entity [:form-params :db/id] default-read)
- (wrap-schema-decode :form-schema user-form-schema)
+ (wrap-schema-decode :form-schema form-schema)
(wrap-nested-form-params)
- (wrap-form-4xx-2 (wrap-entity user-save-error [:form-params :db/id] default-read)))
+ (wrap-form-4xx-2 (wrap-entity user-dialog [:form-params :db/id] default-read)))
:user-client-new (-> new-client
(wrap-schema-decode :query-schema [:map
[:index {:optional true
:default 0} [nat-int? {:default 0}]]]))
- :user-edit-dialog (-> user-edit-dialog
+ :user-edit-dialog (-> user-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode
:route-schema (mc/schema [:map [:db/id entity-id]])))
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 6cbdfa0f..ca664017 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -97,7 +97,11 @@
:long empty->nil
'nat-int? empty->nil}}))
-(def entity-id (mc/schema [nat-int? {:error/message "required"} ]))
+(def entity-id (mc/schema [nat-int? {:error/message "required"
+ :decode/arbitrary (fn [e]
+ (if (and (map? e) (:db/id e))
+ (:db/id e)
+ e))} ]))
(def temp-id (mc/schema [:string {:min 1}]))
(def money (mc/schema [:double]))
@@ -116,15 +120,17 @@
(def map->db-id-decoder
{:enter (fn [x]
- (into []
- (for [[k v] (sort-by (comp #(Long/parseLong %) name first) x)]
- v
- #_(assoc v :db/id (cond (and (string? k) (re-find #"^\d+$" k))
- (Long/parseLong k)
- (keyword? k)
- (name k)
- :else
- k)))))})
+ (if (sequential? x)
+ x
+ (into []
+ (for [[k v] (sort-by (comp #(Long/parseLong %) name first) x)]
+ v
+ #_(assoc v :db/id (cond (and (string? k) (re-find #"^\d+$" k))
+ (Long/parseLong k)
+ (keyword? k)
+ (name k)
+ :else
+ k))))))})
(defn many-entity [params & keys]
(mc/schema
@@ -219,7 +225,10 @@
(handler request))))
(defn ref->enum-schema [n]
- (into [:enum {:decode/string #(keyword n %)}]
+ (into [:enum {:decode/string #(if (keyword? %)
+ %
+ (keyword n %)
+ )}]
(for [{:db/keys [ident]} (all-schema)
:when (= n (namespace ident))]
ident)))
From d7edf0221cc390cc24a647a627f9c5b4de9d49ec Mon Sep 17 00:00:00 2001
From: Bryce
Date: Tue, 24 Oct 2023 12:29:48 -0700
Subject: [PATCH 22/34] revamp more
---
src/clj/auto_ap/ssr/admin/accounts.clj | 19 ++++---------------
src/clj/auto_ap/ssr/users.clj | 3 ---
2 files changed, 4 insertions(+), 18 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 3e95993e..3fd9557f 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -136,14 +136,14 @@
:parse-query-params (comp
(query-params/parse-key :code query-params/parse-long)
(helper/default-parse-query-params grid-page))
- :action-buttons (fn [request]
+ :action-buttons (fn [_]
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-new-dialog))
:hx-target "#modal-content"
:hx-swap "innerHTML"
:color :primary}
"New Account")])
- :row-buttons (fn [request entity]
+ :row-buttons (fn [_ entity]
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-edit-dialog
:db/id (:db/id entity)))
@@ -184,16 +184,15 @@
(let [entity (cond-> form-params
(= :post request-method) (assoc :db/id "new"))
_ (cond (= :post request-method)
- (when-let [extant (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))]
+ (when (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))
(field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
[:account/numeric-code]
:form form-params))
)
- ;; TODO the following would work better if the schema was hydrated automatically with needed values
_ (some->> form-params
:account/client-overrides
(group-by :account-client-override/client)
- (filter (fn [[client overrides]]
+ (filter (fn [[_ overrides]]
(> (count overrides) 1)))
(map first)
seq
@@ -235,16 +234,6 @@
:headers {"hx-trigger" "modalclose"
"hx-retarget" (format "#account-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
-;; TODO use cursor
-;; TODO index based list not dbid
-
-;; TODO lots of weird edge cases with indexes
-;; for example, what happens when you have 0, 1, 2, but then delete 1?
-;; what happens when you delete 2 but then add another one?
-;; preference is that the field parsing logic does better grouping of what
-;; goes with what, building index on the server side
-;; not needing to pass index in
-
;; TODO decide when cursors are used. other cases it's not, some are
(defn client-override* [override]
(com/data-grid-row (-> {:x-ref "p"
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 3040f057..c7f5fec4 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -369,8 +369,6 @@
:new? true} []
(client-row* fc/*current*))))
-
-
(def key->handler
(apply-middleware-to-all-handlers
{:users (helper/page-route grid-page)
@@ -396,4 +394,3 @@
(-> h
(wrap-admin)
(wrap-client-redirect-unauthenticated)))))
-
From f5fd532a31c7aadab7b6585c9dfae0b3517d6332 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Tue, 24 Oct 2023 16:59:43 -0700
Subject: [PATCH 23/34] ccount modal
---
src/clj/auto_ap/ssr/admin/accounts.clj | 85 ++++-----
.../auto_ap/ssr/admin/transaction_rules.clj | 180 +++++++++---------
src/clj/auto_ap/ssr/ui.clj | 13 +-
src/clj/auto_ap/ssr/users.clj | 11 +-
src/clj/auto_ap/ssr/utils.clj | 58 +++---
5 files changed, 167 insertions(+), 180 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 3fd9557f..6dad6db6 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -29,8 +29,10 @@
html-response
main-transformer
many-entity
+ modal-response
ref->enum-schema
ref->select-options
+ strip
temp-id
wrap-entity
wrap-form-4xx-2
@@ -44,8 +46,8 @@
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:admin-account-table)
- "hx-target" "#account-table"
- "hx-indicator" "#account-table"}
+ "hx-target" "#entity-table"
+ "hx-indicator" "#entity-table"}
[:fieldset.space-y-6
(com/field {:label "Name"}
@@ -129,7 +131,7 @@
matching-count]))
(def grid-page
- (helper/build {:id "account-table"
+ (helper/build {:id "entity-table"
:nav (com/admin-aside-nav)
:page-specific-nav filters
:fetch-page fetch-page
@@ -139,16 +141,12 @@
:action-buttons (fn [_]
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-new-dialog))
- :hx-target "#modal-content"
- :hx-swap "innerHTML"
:color :primary}
"New Account")])
:row-buttons (fn [_ entity]
[(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-account-edit-dialog
- :db/id (:db/id entity)))
- :hx-target "#modal-content"
- :hx-swap "innerHTML"}
+ :db/id (:db/id entity)))}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -181,31 +179,29 @@
(def table* (partial helper/table* grid-page))
(defn account-save [{:keys [form-params request-method] :as request}]
- (let [entity (cond-> form-params
- (= :post request-method) (assoc :db/id "new"))
- _ (cond (= :post request-method)
- (when (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))
- (field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
- [:account/numeric-code]
- :form form-params))
- )
- _ (some->> form-params
- :account/client-overrides
- (group-by :account-client-override/client)
- (filter (fn [[_ overrides]]
- (> (count overrides) 1)))
- (map first)
- seq
- (#(form-validation-error (format "Client(s) %s have more than one override."
- (str/join ", "
- (map (fn [client]
- (format "'%s'" (pull-attr (dc/db conn)
- :client/name
- (-> client)))
- ) %)))
- :form form-params))
-
- )
+ (let [entity (cond-> form-params
+ (= :post request-method) (assoc :db/id "new"))
+ _ (cond (= :post request-method)
+ (when (seq (dc/q '[:find ?x :in $ ?nc :where [?x :account/numeric-code ?nc]] (dc/db conn) (:account/numeric-code entity)))
+ (field-validation-error (format "The code %d is already in use." (:account/numeric-code entity))
+ [:account/numeric-code]
+ :form form-params)))
+ _ (some->> form-params
+ :account/client-overrides
+ (group-by :account-client-override/client)
+ (filter (fn [[_ overrides]]
+ (> (count overrides) 1)))
+ (map first)
+ seq
+ (#(form-validation-error (format "Client(s) %s have more than one override."
+ (str/join ", "
+ (map (fn [client]
+ (format "'%s'" (pull-attr (dc/db conn)
+ :client/name
+ (-> client)))
+ ) %)))
+ :form form-params)) ;; TODO shouldnt need to bubble this through. See if we can eliminate the passing of form and last-form.
+ )
{:keys [tempids]} (audit-transact [[:upsert-entity (cond-> entity
(:account/numeric-code entity) (assoc :account/code (str (:account/numeric-code entity))))]]
(:identity request))
@@ -231,8 +227,10 @@
"account_client_override_id" (:db/id o)})))
(html-response
(row* identity updated-account {:flash? true})
- :headers {"hx-trigger" "modalclose"
- "hx-retarget" (format "#account-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
+ :headers (cond-> {"hx-trigger" "modalclose"}
+ (= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
+ "hx-reswap" "afterbegin")
+ (= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-account)))))))
;; TODO decide when cursors are used. other cases it's not, some are
(defn client-override* [override]
@@ -377,14 +375,14 @@
:index (count (fc/field-value))
:hx-get (bidi/path-for ssr-routes/only-routes
:admin-account-client-override-new)}
- "New override"))))
-
- ]
+ "New override"))))]
[:div
(com/form-errors {:errors (:errors fc/*form-errors*)})
(com/validated-save-button {:errors (seq form-errors)}
"Save account")])]])]))
+;; TODO saving new row should att it to the tbody
+
(defn new-client-override [{ {:keys [index]} :query-params}]
(html-response
(fc/start-form-with-prefix
@@ -398,8 +396,8 @@
[:map
[:db/id {:optional true} [:maybe entity-id]]
[:account/numeric-code {:optional true} [:maybe :int]]
- [:account/name [:string {:min 1}]]
- [:account/location [:maybe :string]]
+ [:account/name [:string {:min 1 :decode/string strip}]]
+ [:account/location {:optional true} [:maybe [:string {:decode/string strip}]]]
[:account/type (ref->enum-schema "account-type")]
[:account/applicability (ref->enum-schema "account-applicability")] ;
[:account/invoice-allowance (ref->enum-schema "allowance")]
@@ -409,17 +407,16 @@
(many-entity {}
[:db/id [:or entity-id temp-id]]
[:account-client-override/client entity-id]
- [:account-client-override/name [:string {:min 2}]])]]]))
+ [:account-client-override/name [:string {:min 2 :decode/string strip}]])]]]))
(defn account-dialog [{:keys [entity form-params form-errors]}]
- (html-response (dialog* {:entity entity
+ (modal-response (dialog* {:entity entity
:form-params (or (when (seq form-params)
form-params)
(when entity
(mc/decode form-schema entity main-transformer))
{})
- :form-errors form-errors})
- :headers {"hx-trigger" "modalopen"}))
+ :form-errors form-errors})))
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 383a2f18..f3c1a92b 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -31,6 +31,7 @@
html-response
main-transformer
many-entity
+ modal-response
money
percentage
ref->enum-schema
@@ -44,21 +45,14 @@
[bidi.bidi :as bidi]
[clojure.string :as str]
[datomic.api :as dc]
- [iol-ion.query :refer [ident]]
[malli.core :as mc]))
-;; TODO with dependencies, I really don't like that you have to be ultra specific in what
-;; you want to include, and generating the routes and interconnection is weird too.
-;; I'm tempted to say to include a full snapshot of the form, and the indicator
-;; as to which one to generate.
-
-
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-table)
- "hx-target" "#transaction-rule-table"
- "hx-indicator" "#transaction-rule-table"}
+ "hx-target" "#entity-table"
+ "hx-indicator" "#entity-table"}
[:fieldset.space-y-6
(com/field {:label "Vendor"}
@@ -180,7 +174,7 @@
matching-count]))
(def grid-page
- (helper/build {:id "transaction-rule-table"
+ (helper/build {:id "entity-table"
:nav (com/admin-aside-nav)
:page-specific-nav filters
:fetch-page fetch-page
@@ -190,16 +184,12 @@
:action-buttons (fn [request]
[(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-new-dialog))
- :hx-target "#modal-content"
- :hx-swap "innerHTML"
:color :primary}
"New Transaction Rule")])
:row-buttons (fn [request entity]
[(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-content"
- :hx-swap "innerHTML"}
+ :db/id (:db/id entity)))}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -269,6 +259,7 @@
bank-account-id))
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
+ (clojure.pprint/pprint form-params)
(let [entity (cond-> form-params
(= :post request-method) (assoc :db/id "new")
true (assoc :transaction-rule/note (entity->note form-params)))
@@ -297,13 +288,15 @@
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
(:identity request))
- updated-account (dc/pull (dc/db conn)
+ updated-rule (dc/pull (dc/db conn)
default-read
(or (get tempids (:db/id entity)) (:db/id entity)))]
(html-response
- (row* identity updated-account {:flash? true})
- :headers {"hx-trigger" "modalclose"
- "hx-retarget" (format "#transaction-rule-table tr[data-id=\"%d\"]" (:db/id updated-account))})))
+ (row* identity updated-rule {:flash? true})
+ :headers (cond-> {"hx-trigger" "modalclose"}
+ (= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
+ "hx-reswap" "afterbegin")
+ (= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule)))))))
@@ -327,81 +320,84 @@
[{:keys [name value client-id x-model]}]
[:div.flex.flex-col
(com/typeahead-2 {:name name
- :placeholder "Search..."
- :url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
- :id name
- :x-model x-model
- :value value
- :content-fn (fn [value]
- (:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
- client-id)))})])
+ :placeholder "Search..."
+ :url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
+ :id name
+ :x-model x-model
+ :value value
+ :content-fn (fn [value]
+ (:account/name (d-accounts/clientize (dc/pull (dc/db conn) d-accounts/default-read value)
+ client-id)))})])
-;; TODO something is making the accountId not change the location for only existing ones?
(defn- transaction-rule-account-row*
[transaction-rule account]
- (com/data-grid-row (-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
- (fc/field-value (:transaction-rule-account/account account)))
- :show (boolean (not (fc/field-value (:new? account))))})
- :data-key "show"
- :x-ref "p"}
- hx/alpine-mount-then-appear)
- (let [account-name (fc/field-name (:transaction-rule-account/account account))]
- (list
-
- (fc/with-field :db/id
- (com/hidden {:name (fc/field-name)
- :value (fc/field-value)}))
- (fc/with-field :transaction-rule-account/account
- (com/data-grid-cell
- {}
- (com/validated-field
- {:errors (fc/field-errors)}
- [:div {:hx-trigger "changed"
- :hx-target "next div"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
- :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
- :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
- (account-typeahead* {:value (fc/field-value)
- :client-id (:db/id (:transaction-rule/client transaction-rule))
- :name (fc/field-name)
- :x-model "accountId"}))))
- (fc/with-field :transaction-rule-account/location
- (com/data-grid-cell
- {}
- (com/validated-field
- {:errors (fc/field-errors)
- :x-data (hx/json {:location (fc/field-value)})}
- [:div {:hx-trigger "changed"
- :hx-target "next *"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
- :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
- :x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data))"}]
- (location-select* {:name (fc/field-name)
- :account-location (:account/location (cond->> (:transaction-rule-account/account @account)
- (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
- '[:account/location])))
- :client-locations (:client/locations (:transaction-rule/client transaction-rule))
- :hx-model "location"
- :value (fc/field-value)}))))
- (fc/with-field :transaction-rule-account/percentage
- (com/data-grid-cell
- {}
- (com/validated-field
- {:errors (fc/field-errors)}
- (com/money-input {:name (fc/field-name)
- :class "w-16"
- :value (some-> (fc/field-value)
- (* 100 )
- (long ))}))))))
- (com/data-grid-cell {:class "align-top"}
- (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
+ (com/data-grid-row
+ (-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
+ (fc/field-value (:transaction-rule-account/account account)))
+ :show (boolean (not (fc/field-value (:new? account))))})
+ :data-key "show"
+ :x-ref "p"}
+ hx/alpine-mount-then-appear)
+ (let [account-name (fc/field-name (:transaction-rule-account/account account))]
+ (list
+
+ (fc/with-field :db/id
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)}))
+ (fc/with-field :transaction-rule-account/account
+ (com/data-grid-cell
+ {}
+ (com/validated-field
+ {:errors (fc/field-errors)}
+ [:div {:hx-trigger "changed"
+ :hx-target "next div"
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
+ :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+ (account-typeahead* {:value (fc/field-value)
+ :client-id (:db/id (:transaction-rule/client transaction-rule))
+ :name (fc/field-name)
+ :x-model "accountId"}))))
+ (fc/with-field :transaction-rule-account/location
+ (com/data-grid-cell
+ {}
+ (com/validated-field
+ {:errors (fc/field-errors)
+ :x-data (hx/json {:location (fc/field-value)})}
+ [:div {:hx-trigger "changed"
+ :hx-target "next *"
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
+ :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data) )"}]
+ (location-select* {:name (fc/field-name)
+ :account-location (:account/location (cond->> (:transaction-rule-account/account @account)
+ (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
+ '[:account/location])))
+ :client-locations (:client/locations (:transaction-rule/client transaction-rule))
+ :hx-model "location"
+ :value (fc/field-value)}))))
+ (fc/with-field :transaction-rule-account/percentage
+ (com/data-grid-cell
+ {}
+ (com/validated-field
+ {:errors (fc/field-errors)}
+ (println "FIELD VALUE IS" (fc/field-value) (some-> (fc/field-value)
+ (* 100 )
+ (long )))
+ (com/money-input {:name (fc/field-name)
+ :class "w-16"
+ :value (some-> (fc/field-value)
+ (* 100 )
+ (long ))}))))))
+ (com/data-grid-cell {:class "align-top"}
+ (com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
;; TODO background jobs and company 1099
(defn dialog* [{:keys [entity form-params form-errors]}]
(fc/start-form form-params form-errors
(com/modal
{:modal-class "max-w-2xl"
- :hx-target "this"}
+ :hx-target "this"}
[:form {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms"
@@ -415,7 +411,6 @@
{}
[:div.flex [:div.p-2 "Transaction Rule"]]
[:fieldset {:class "hx-disable"
- :hx-disinherit "hx-target" ;; TODO why disinherit
:x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client form-params))
(:transaction-rule/client form-params)
(:db/id (:transaction-rule/client entity)))})}
@@ -542,8 +537,7 @@
(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"}
+ (com/data-grid-header {:class "w-16"})]}
(fc/cursor-map #(transaction-rule-account-row* form-params %))
(com/data-grid-new-row {:colspan 4
:hx-get (bidi/path-for ssr-routes/only-routes
@@ -604,7 +598,8 @@
client-id client-id]
(html-response (account-typeahead* {:name name
:value account
- :client-id client-id}))))
+ :client-id client-id
+ :x-model "accountId"}))))
(def form-schema (mc/schema
[:map
@@ -627,14 +622,13 @@
[:transaction-rule-account/percentage percentage])]]))
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
- (html-response (dialog* {:entity entity
+ (modal-response (dialog* {:entity entity
:form-params (or (when (seq form-params)
form-params)
(when entity
- (mc/decode form-schema entity main-transformer)) ;; TODO coerce into form params
+ (mc/decode form-schema entity main-transformer))
{})
- :form-errors form-errors})
- :headers {"hx-trigger" "modalopen"}))
+ :form-errors form-errors})))
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index 3cccfa40..6ab04c9e 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -1,7 +1,8 @@
(ns auto-ap.ssr.ui
(:require
- [hiccup2.core :as hiccup]
- [auto-ap.ssr.hx :as hx]))
+ [auto-ap.ssr.hx :as hx]
+ [config.core :refer [env]]
+ [hiccup2.core :as hiccup]))
(defn html-page [hiccup]
{:status 200
@@ -27,8 +28,12 @@
[:script {:src "https://unpkg.com/hyperscript.org@0.9.7/dist/_hyperscript.min.js"}]
[:script {:src "https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js"}]
[:script {:src "https://cdn.plaid.com/link/v2/stable/link-initialize.js"}]
- [:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
- :crossorigin= "anonymous"}]
+ (if (= "dev" (:dd-env env))
+ [:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.js"
+ :crossorigin= "anonymous"}]
+ [:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
+ :crossorigin= "anonymous"}])
+
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
[:script {:src "/js/htmx-disable.js"}]
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async"}]]
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index c7f5fec4..0f650dd0 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -26,6 +26,7 @@
html-response
main-transformer
many-entity
+ modal-response
ref->enum-schema
ref->select-options
wrap-entity
@@ -213,9 +214,7 @@
:hx-vals (format "{\"db/id\": \"%s\"}" (:db/id entity))} "Impersonate")
(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
:user-edit-dialog
- :db/id (:db/id entity)))
- :hx-target "#modal-content"
- :hx-swap "innerHTML"}
+ :db/id (:db/id entity)))}
svg/pencil)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:admin)}
@@ -352,16 +351,14 @@
[:user/role (ref->enum-schema "user-role")]]))
(defn user-dialog [{:keys [form-params entity form-errors]}]
- (html-response
+ (modal-response
(dialog* {:form-params (or (when (seq form-params)
form-params)
(when entity
(mc/decode form-schema entity main-transformer))
{})
:entity entity
- :form-errors form-errors})
-
- :headers {"hx-trigger" "modalopen"}))
+ :form-errors form-errors})))
(defn new-client [{ {:keys [index]} :query-params}]
(html-response
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index ca664017..27685076 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -27,6 +27,16 @@
o))
oob)))})
+(defn modal-response [hiccup & {:as opts}]
+ (apply html-response
+ (into
+ [hiccup]
+ (mapcat identity
+ (-> opts
+ (assoc-in [:headers "hx-trigger"] "modalopen")
+ (assoc-in [:headers "hx-retarget"] "#modal-content")
+ (assoc-in [:headers "hx-reswap"] "innerHTML"))))))
+
(defn wrap-error-response [handler]
(fn [request]
(try
@@ -105,8 +115,11 @@
(def temp-id (mc/schema [:string {:min 1}]))
(def money (mc/schema [:double]))
-(def percentage (mc/schema [:double {:decode/arbitrary (fn [x] (some-> x (* 0.01)))
- :max 1.0
+(def percentage (mc/schema [:double {:decode/string {:enter (fn [x]
+ (if (and (string? x) (re-find #"^\d+(\.\d+)?$" x))
+ (-> x (Double/parseDouble) (* 0.01))
+ x))}
+ :max 1.0
:error/message "1-100"}]))
(def regex (mc/schema [:fn {:error/message "not a regex"}
@@ -124,13 +137,7 @@
x
(into []
(for [[k v] (sort-by (comp #(Long/parseLong %) name first) x)]
- v
- #_(assoc v :db/id (cond (and (string? k) (re-find #"^\d+$" k))
- (Long/parseLong k)
- (keyword? k)
- (name k)
- :else
- k))))))})
+ v))))})
(defn many-entity [params & keys]
(mc/schema
@@ -174,6 +181,16 @@
(mt2/transformer {:name :arbitrary})
mt2/default-value-transformer))
+(defn strip [s]
+ (cond (and (string? s) (str/blank? s))
+ nil
+
+ (string? s)
+ (str/trim s)
+
+ :else
+ s))
+
(defn wrap-schema-decode [handler & {:keys [form-schema query-schema route-schema params-schema]}]
(fn [{:keys [form-params query-params params] :as request}]
(let [request (try
@@ -207,7 +224,6 @@
main-transformer)))
(catch Exception e
(alog/warn ::validation-error :error e)
-
(throw (ex-info (->> (-> e
(ex-data )
:data
@@ -251,17 +267,6 @@
-#_(defn namespaceize-decoder [n]
- {:exit (fn [m]
- (when m
- (reduce
- (fn [m [k v]]
- (if (= k "id")
- (assoc m :db/id v)
- (assoc m (keyword n (name k)) v)))
- m
- m)))})
-
(defn wrap-form-4xx [handler]
(fn [request]
@@ -274,17 +279,6 @@
(html-response [:span.error-content.text-red-500 (:message &throw-context)]
:status 400)))))
-(defn assoc-errors-into-meta [entity errors]
- (reduce
- (fn add-error [entity {:keys [path message] :as se}]
- (if (= (count path) 1)
- (with-meta entity (assoc (meta entity) (last path) {:errors message}))
-
- (update-in entity (butlast path)
- (fn [terminal]
- (with-meta terminal (assoc (meta terminal) (last path) {:errors message}))))))
- entity
- errors))
(defn wrap-form-4xx-2 [handler form-handler]
(fn [request]
From b4ea51df84b7bdd2e6455eeebb4c80801100107c Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 06:46:31 -0700
Subject: [PATCH 24/34] preserves values.
---
.../auto_ap/ssr/admin/transaction_rules.clj | 67 ++++++++-----------
1 file changed, 28 insertions(+), 39 deletions(-)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index f3c1a92b..5f72215d 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -259,7 +259,6 @@
bank-account-id))
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
- (clojure.pprint/pprint form-params)
(let [entity (cond-> form-params
(= :post request-method) (assoc :db/id "new")
true (assoc :transaction-rule/note (entity->note form-params)))
@@ -330,10 +329,11 @@
client-id)))})])
(defn- transaction-rule-account-row*
- [transaction-rule account]
+ [account client-id client-locations]
(com/data-grid-row
(-> {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account)))
(fc/field-value (:transaction-rule-account/account account)))
+ :location (fc/field-value (:transaction-rule-account/location account))
:show (boolean (not (fc/field-value (:new? account))))})
:data-key "show"
:x-ref "p"}
@@ -351,11 +351,11 @@
{:errors (fc/field-errors)}
[:div {:hx-trigger "changed"
:hx-target "next div"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name)
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId, value: event.detail.accountId}" account-name)
:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead))
- :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
+ :x-init "$watch('clientId', cid => $dispatch('changed', $data));"}]
(account-typeahead* {:value (fc/field-value)
- :client-id (:db/id (:transaction-rule/client transaction-rule))
+ :client-id client-id
:name (fc/field-name)
:x-model "accountId"}))))
(fc/with-field :transaction-rule-account/location
@@ -366,24 +366,21 @@
:x-data (hx/json {:location (fc/field-value)})}
[:div {:hx-trigger "changed"
:hx-target "next *"
- :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) )
+ :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || '', value: event.detail.location}" (fc/field-name) )
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
:x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data) )"}]
(location-select* {:name (fc/field-name)
:account-location (:account/location (cond->> (:transaction-rule-account/account @account)
(nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn)
'[:account/location])))
- :client-locations (:client/locations (:transaction-rule/client transaction-rule))
- :hx-model "location"
+ :client-locations client-locations
+ :x-model "location"
:value (fc/field-value)}))))
(fc/with-field :transaction-rule-account/percentage
(com/data-grid-cell
{}
(com/validated-field
{:errors (fc/field-errors)}
- (println "FIELD VALUE IS" (fc/field-value) (some-> (fc/field-value)
- (* 100 )
- (long )))
(com/money-input {:name (fc/field-name)
:class "w-16"
:value (some-> (fc/field-value)
@@ -477,7 +474,7 @@
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name))
:x-init "$watch('clientId', cid => $dispatch('changed', $data))"}]
- (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client form-params))
+ (bank-account-typeahead* {:client-id (:transaction-rule/client form-params)
:name (fc/field-name)
:value (fc/field-value)})]))
@@ -534,17 +531,18 @@
(fc/with-field :transaction-rule/accounts
(com/validated-field
{:errors (fc/field-errors)}
- (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"})]}
- (fc/cursor-map #(transaction-rule-account-row* form-params %))
- (com/data-grid-new-row {:colspan 4
- :hx-get (bidi/path-for ssr-routes/only-routes
- :admin-transaction-rule-new-account)
- :index (count (fc/field-value))
- :tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
- "New account"))))
+ (let [client-locations (some->> form-params :transaction-rule/client (pull-attr (dc/db conn) :client/locations))]
+ (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"})]}
+ (fc/cursor-map #(transaction-rule-account-row* % (:transaction-rule/client form-params) client-locations))
+ (com/data-grid-new-row {:colspan 4
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-new-account)
+ :index (count (fc/field-value))
+ :tr-params (hx/bind-alpine-vals {} {:client-id "clientId"})}
+ "New account")))))
(fc/with-field :transaction-rule/transaction-approval-status
(com/validated-field {:label "Approval status"
@@ -570,13 +568,9 @@
:new? true}
[]
(transaction-rule-account-row*
- ;; TODO store a pointer to the "head " cursor for errors instead of nesting them
- ;; makes it so you don't have to do this
-
- {:transaction-rule/client (dc/pull (dc/db conn) '[:client/name :client/locations :db/id]
- client-id)}
-
- fc/*current*))))
+ fc/*current*
+ client-id
+ (some->> client-id (pull-attr (dc/db conn) :client/locations) client-id)))))
;; TODO check to see if it should be called "Shared" or "shared" for the value
@@ -591,15 +585,10 @@
(pull-attr (dc/db conn) :client/locations))})))
(defn account-typeahead [{{:keys [name value client-id] :as qp} :query-params}]
- (let [account (some->> value (dc/pull (dc/db conn) [:account/name :db/id
- {:account/client-overrides [:db/id
- :account-client-override/name
- {:account-client-override/client [:db/id :client/name]}]}]))
- client-id client-id]
- (html-response (account-typeahead* {:name name
- :value account
- :client-id client-id
- :x-model "accountId"}))))
+ (html-response (account-typeahead* {:name name
+ :value value
+ :client-id client-id
+ :x-model "accountId"})))
(def form-schema (mc/schema
[:map
From deaad7513c5ebe0323ad7885e90c16164634ad75 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 12:43:00 -0700
Subject: [PATCH 25/34] Fixes modal, but users still have to say h-full on
every element leading to the card
---
resources/public/output.css | 137 +++++++++++-------
src/clj/auto_ap/ssr/admin/accounts.clj | 8 +-
.../auto_ap/ssr/admin/transaction_rules.clj | 3 +-
src/clj/auto_ap/ssr/components/dialog.clj | 11 +-
src/clj/auto_ap/ssr/components/inputs.clj | 2 +-
src/clj/auto_ap/ssr/ui.clj | 11 +-
src/clj/auto_ap/ssr/users.clj | 4 +-
7 files changed, 106 insertions(+), 70 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 96983899..a6672f5a 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1155,6 +1155,10 @@ input:checked + .toggle-bg {
margin: 1rem;
}
+.m-12 {
+ margin: 3rem;
+}
+
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
@@ -1332,6 +1336,10 @@ input:checked + .toggle-bg {
height: 1.5rem;
}
+.h-64 {
+ height: 16rem;
+}
+
.h-8 {
height: 2rem;
}
@@ -1344,47 +1352,43 @@ input:checked + .toggle-bg {
height: 100%;
}
-.h-screen {
- height: 100vh;
-}
-
-.h-64 {
- height: 16rem;
-}
-
.h-min {
height: -moz-min-content;
height: min-content;
}
-.h-\[90vh\] {
- height: 90vh;
+.h-screen {
+ height: 100vh;
+}
+
+.h-24 {
+ height: 6rem;
}
.max-h-96 {
max-height: 24rem;
}
-.max-h-full {
- max-height: 100%;
-}
-
-.max-h-\[90vh\] {
- max-height: 90vh;
-}
-
-.max-h-\[100vh\] {
- max-height: 100vh;
-}
-
.max-h-\[80vh\] {
max-height: 80vh;
}
+.max-h-full {
+ max-height: 100%;
+}
+
+.max-h-\[50\%\] {
+ max-height: 50%;
+}
+
.w-1\/2 {
width: 50%;
}
+.w-1\/4 {
+ width: 25%;
+}
+
.w-16 {
width: 4rem;
}
@@ -1454,21 +1458,32 @@ input:checked + .toggle-bg {
width: 100vw;
}
-.w-min {
- width: -moz-min-content;
- width: min-content;
+.w-\[900px\] {
+ width: 900px;
}
-.w-8\/12 {
- width: 66.666667%;
+.w-\[1200px\] {
+ width: 1200px;
}
-.w-6\/12 {
- width: 50%;
+.w-\[2900px\] {
+ width: 2900px;
}
-.w-1\/4 {
- width: 25%;
+.min-w-\[25\%\] {
+ min-width: 25%;
+}
+
+.min-w-\[500px\] {
+ min-width: 500px;
+}
+
+.min-w-\[450px\] {
+ min-width: 450px;
+}
+
+.min-w-\[700px\] {
+ min-width: 700px;
}
.max-w-2xl {
@@ -1495,8 +1510,8 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
-.max-w-xs {
- max-width: 20rem;
+.max-w-6xl {
+ max-width: 72rem;
}
.flex-1 {
@@ -1709,18 +1724,10 @@ 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;
}
@@ -1757,6 +1764,10 @@ input:checked + .toggle-bg {
justify-content: space-between;
}
+.justify-stretch {
+ justify-content: stretch;
+}
+
.justify-items-stretch {
justify-items: stretch;
}
@@ -1857,6 +1868,10 @@ input:checked + .toggle-bg {
align-self: center;
}
+.self-stretch {
+ align-self: stretch;
+}
+
.justify-self-end {
justify-self: end;
}
@@ -2148,6 +2163,11 @@ input:checked + .toggle-bg {
background-color: rgb(255 230 230 / var(--tw-bg-opacity));
}
+.bg-red-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(255 3 3 / var(--tw-bg-opacity));
+}
+
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -2162,6 +2182,11 @@ input:checked + .toggle-bg {
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
}
+.bg-yellow-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(194 120 3 / var(--tw-bg-opacity));
+}
+
.\!bg-opacity-0 {
--tw-bg-opacity: 0 !important;
}
@@ -2202,8 +2227,8 @@ input:checked + .toggle-bg {
padding: 1rem;
}
-.p-6 {
- padding: 1.5rem;
+.p-8 {
+ padding: 2rem;
}
.px-2 {
@@ -2226,6 +2251,11 @@ input:checked + .toggle-bg {
padding-right: 1.25rem;
}
+.px-6 {
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+}
+
.py-0 {
padding-top: 0px;
padding-bottom: 0px;
@@ -2266,11 +2296,6 @@ input:checked + .toggle-bg {
padding-bottom: 1.25rem;
}
-.px-6 {
- padding-left: 1.5rem;
- padding-right: 1.5rem;
-}
-
.pb-2 {
padding-bottom: 0.5rem;
}
@@ -3614,12 +3639,12 @@ input:checked + .toggle-bg {
display: block;
}
- .sm\:max-h-\[90vh\] {
- max-height: 90vh;
+ .sm\:items-center {
+ align-items: center;
}
- .sm\:max-w-2xl {
- max-width: 42rem;
+ .sm\:justify-center {
+ justify-content: center;
}
.sm\:rounded-lg {
@@ -3666,6 +3691,10 @@ input:checked + .toggle-bg {
align-items: center;
}
+ .md\:justify-center {
+ justify-content: center;
+ }
+
.md\:space-x-3 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
@@ -3677,6 +3706,10 @@ input:checked + .toggle-bg {
margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(0px * var(--tw-space-y-reverse));
}
+
+ .md\:p-12 {
+ padding: 3rem;
+ }
}
@media (min-width: 1024px) {
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 6dad6db6..5c913a68 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -280,18 +280,20 @@
(fc/start-form form-params form-errors
[:div {:x-data (hx/json {"accountName" (or (:account/name form-params) (:account/numeric-code entity))
"accountCode" (or (:account/numeric-code form-params) (:account/numeric-code entity) )})
- :hx-target "this"}
+ :hx-target "this"
+ :class "w-full h-full"}
(com/modal
{}
[:form (-> {:hx-ext "response-targets"
:hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
+ :hx-target-400 "#form-errors .error-content"
+ :class "h-full"}
(assoc (if (:db/id entity)
:hx-put
:hx-post)
(str (bidi/path-for ssr-routes/only-routes
:admin-transaction-rule-edit-save))))
- [:fieldset {:class "hx-disable"}
+ [:fieldset {:class "hx-disable h-full"}
(com/modal-card
{}
[:div.flex [:div.p-2 "Account"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 5f72215d..3d0deb2d 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -400,7 +400,7 @@
:hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content"
:x-trap "true"
- :class "group/form"
+ :class "group/form w-full h-full"
(if (:db/id entity)
:hx-put
:hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
@@ -574,7 +574,6 @@
;; TODO check to see if it should be called "Shared" or "shared" for the value
-;; TODO hydrate nested types more easily. make it easy to hydrate so you don't do weird sometimes pulls
(defn location-select [{{:keys [name account-id client-id value] :as qp} :query-params}]
(html-response (location-select* {:name name
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index 3ee49af6..0a5f7474 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -5,19 +5,16 @@
(defn modal- [params & children]
[:div (-> params
- (update :class #(-> %
- (or "max-w-4xl w-1/4 overflow-visible")
- (hh/add-class "h-min")))
-
- (assoc "@click.outside" "open=false"))
+ (assoc "@click.outside" "open=false")
+ (update :class (fnil hh/add-class "") "w-full h-full"))
children])
(defn modal-card- [params header content footer]
[:div#modal-card (update params
:class (fn [c] (-> c
- (or "w-full")
+ (or "w-full p-4 h-full")
)))
- [:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col max-h-[80vh]"}
+ [:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col h-full"}
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
[:div {:class "px-6 space-y-6 overflow-y-scroll w-full shrink"}
#_[:div.bg-green-300.w-full.h-64
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index c42f82ed..61db8e31 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -109,7 +109,7 @@ c.clearChoices();
[:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
- [:ul.dropdown-contents {:class "absolute bg-gray-50 dark:bg-gray-600 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-50 mt-1"
"@keydown.escape" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
"x-transition:enter-start" "!opacity-0 !mt-0"
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index 6ab04c9e..cc7ad535 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -72,7 +72,7 @@ input[type=number] {
"@modalopen.document" "open=true"
"@modalclose.document" "open=false"}
- [:div {:class "bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40"
+ [:div {:class "bg-gray-900 bg-opacity-50 dark:bg-opacity-80 fixed inset-0 z-40 md:p-12"
"x-show" "open"
":aria-hidden" "!open"
"x-transition:enter" "duration-300"
@@ -86,7 +86,8 @@ input[type=number] {
;; div that is forced to the maximum allowed size. inside that will be a div that just centers
;; the elements, allowing it to grow as necessar. Then make the modal on the inside of this
;; div just use flexbox to make the inside part be the part that scrolls
- [:div#modal-content {:class (str "inset-0 max-h-[80vh] sm:m-12 flex justify-center items-center shrink h-full")
+ [:div {;;:class (str "sm:m-12 flex justify-center items-center bg-green-500 items-stretch inset-0")
+ :class "flex h-full w-full justify-stretch md:justify-center items-stretch md:items-center "
"x-trap.inert.noscroll" "open"
"x-trap.inert" "open"
"x-show" "open"
@@ -95,4 +96,8 @@ input[type=number] {
"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"}]]]]]))
+ "x-transition:leave-end" "!opacity-0 !translate-y-32"}
+ [:div.flex.items-center.justify-center.max-w-6xl {:class "min-w-[700px] max-h-full "}
+ [:div#modal-content.flex.flex-col.self-stretch {:class "min-w-[700px] md:p-12"} ;;.overflow-scroll
+ ]
+ ]]]]]]))
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 0f650dd0..7861f1d2 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -298,8 +298,8 @@
:request-method :put))
:hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content"
- :class "w-full"}
- [:fieldset {:class "hx-disable"}
+ :class "w-full h-full"}
+ [:fieldset {:class "hx-disable h-full"}
(com/modal-card
{}
[:div.flex [:div.p-2 "User"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:user/name entity)]]
From 3f369360639bad982dbb36ccedb7e5bc98a0080c Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 13:30:40 -0700
Subject: [PATCH 26/34] popper makes it work better.
---
src/clj/auto_ap/ssr/components/inputs.clj | 21 +++++++++++++--------
src/clj/auto_ap/ssr/ui.clj | 3 +++
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index 61db8e31..c0f187f1 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -80,18 +80,22 @@ c.clearChoices();
:active -1
:elements (if ((:value-fn params identity) (:value params))
[{:value ((:value-fn params identity) (:value params)) :label ((:content-fn params identity) (:value params))}]
- [])})
+ [])
+ :popper nil})
:x-modelable "value.value"
:x-model (:x-model params)
- :class "relative"}
+ :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed'})"
+ }
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
- "@click.prevent" "open = !open;"
- "@keydown.enter.prevent.stop" "open = !open;"
- "@keydown.down.prevent.stop" "open = true;"
- "@keydown.backspace" "value = {value: '', label: '' }"
+ "@click.prevent" "open = !open; popper.update()"
+ "@keydown.enter.prevent.stop" "open = !open; popper.update()"
+ "@keydown.down.prevent.stop" "open = true; popper.update()"
+ "@keydown.backspace" "value = {value: '', label: '' }"
:tabindex 0
- :x-init (:x-init params)}
+ :x-init (:x-init params)
+ :x-ref "input"
+ }
[:input (-> params
(dissoc :class)
(dissoc :value-fn)
@@ -109,7 +113,8 @@ c.clearChoices();
[:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
- [:ul.dropdown-contents {:class "absolute bg-gray-50 dark:bg-gray-600 rounded-lg shadow-lg py-1 w-max z-50 mt-1"
+ [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-lg py-1 w-max z-50"
+ "x-ref" "dropdown"
"@keydown.escape" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
"x-transition:enter-start" "!opacity-0 !mt-0"
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index cc7ad535..f9eb0bec 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -61,9 +61,12 @@ input[type=number] {
-moz-appearance:textfield; /* Firefox */
} "]
+
[:body {:hx-ext "disable-submit"}
contents
[:script {:src "/js/flowbite.min.js"}]
+
+ [:div#tooltip.bg-red-500.p-12 {:role "tooltip"}]
[: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"
From 635bf3c26721c4ba630ecee337ec749a67172aa4 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 13:52:46 -0700
Subject: [PATCH 27/34] uses popper for dropdown.
---
resources/input.css | 23 ++++
resources/public/output.css | 132 ++++++----------------
src/clj/auto_ap/ssr/components/inputs.clj | 21 ++--
src/clj/auto_ap/ssr/ui.clj | 7 +-
4 files changed, 75 insertions(+), 108 deletions(-)
diff --git a/resources/input.css b/resources/input.css
index 921b1ff9..9e3a576e 100644
--- a/resources/input.css
+++ b/resources/input.css
@@ -165,3 +165,26 @@
.choices[data-type*="select-one"] .choices__button {
right:auto !important;
}
+
+.arrow,
+.arrow::before {
+ position: absolute;
+ width: 24px;
+ height: 24px;
+ background: inherit;
+}
+
+.arrow {
+ visibility: hidden;
+}
+
+
+.arrow::before {
+ visibility: visible;
+ content: '';
+ transform: rotate(45deg);
+}
+
+.arrow {
+ bottom: -4px;
+}
diff --git a/resources/public/output.css b/resources/public/output.css
index a6672f5a..571f55cd 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1155,10 +1155,6 @@ input:checked + .toggle-bg {
margin: 1rem;
}
-.m-12 {
- margin: 3rem;
-}
-
.mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
@@ -1352,43 +1348,22 @@ input:checked + .toggle-bg {
height: 100%;
}
-.h-min {
- height: -moz-min-content;
- height: min-content;
-}
-
.h-screen {
height: 100vh;
}
-.h-24 {
- height: 6rem;
-}
-
.max-h-96 {
max-height: 24rem;
}
-.max-h-\[80vh\] {
- max-height: 80vh;
-}
-
.max-h-full {
max-height: 100%;
}
-.max-h-\[50\%\] {
- max-height: 50%;
-}
-
.w-1\/2 {
width: 50%;
}
-.w-1\/4 {
- width: 25%;
-}
-
.w-16 {
width: 4rem;
}
@@ -1458,30 +1433,6 @@ input:checked + .toggle-bg {
width: 100vw;
}
-.w-\[900px\] {
- width: 900px;
-}
-
-.w-\[1200px\] {
- width: 1200px;
-}
-
-.w-\[2900px\] {
- width: 2900px;
-}
-
-.min-w-\[25\%\] {
- min-width: 25%;
-}
-
-.min-w-\[500px\] {
- min-width: 500px;
-}
-
-.min-w-\[450px\] {
- min-width: 450px;
-}
-
.min-w-\[700px\] {
min-width: 700px;
}
@@ -1494,6 +1445,10 @@ input:checked + .toggle-bg {
max-width: 56rem;
}
+.max-w-6xl {
+ max-width: 72rem;
+}
+
.max-w-lg {
max-width: 32rem;
}
@@ -1510,10 +1465,6 @@ input:checked + .toggle-bg {
max-width: 1024px;
}
-.max-w-6xl {
- max-width: 72rem;
-}
-
.flex-1 {
flex: 1 1 0%;
}
@@ -1538,10 +1489,6 @@ input:checked + .toggle-bg {
flex-grow: 1;
}
-.grow {
- flex-grow: 1;
-}
-
.basis-1\/4 {
flex-basis: 25%;
}
@@ -1884,10 +1831,6 @@ input:checked + .toggle-bg {
overflow: hidden;
}
-.overflow-visible {
- overflow: visible;
-}
-
.overflow-scroll {
overflow: scroll;
}
@@ -1950,6 +1893,11 @@ input:checked + .toggle-bg {
border-top-right-radius: 0.5rem;
}
+.rounded-b-lg {
+ border-bottom-right-radius: 0.5rem;
+ border-bottom-left-radius: 0.5rem;
+}
+
.border {
border-width: 1px;
}
@@ -2163,11 +2111,6 @@ input:checked + .toggle-bg {
background-color: rgb(255 230 230 / var(--tw-bg-opacity));
}
-.bg-red-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 3 3 / var(--tw-bg-opacity));
-}
-
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -2182,11 +2125,6 @@ input:checked + .toggle-bg {
background-color: rgb(253 246 178 / var(--tw-bg-opacity));
}
-.bg-yellow-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(194 120 3 / var(--tw-bg-opacity));
-}
-
.\!bg-opacity-0 {
--tw-bg-opacity: 0 !important;
}
@@ -2207,10 +2145,6 @@ input:checked + .toggle-bg {
padding: 0.25rem;
}
-.p-12 {
- padding: 3rem;
-}
-
.p-2 {
padding: 0.5rem;
}
@@ -2227,10 +2161,6 @@ input:checked + .toggle-bg {
padding: 1rem;
}
-.p-8 {
- padding: 2rem;
-}
-
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
@@ -2563,6 +2493,12 @@ input:checked + .toggle-bg {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}
+.shadow-2xl {
+ --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
+ --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
+}
+
.outline {
outline-style: solid;
}
@@ -3010,6 +2946,28 @@ input:checked + .toggle-bg {
right:auto !important;
}
+.arrow,
+.arrow::before {
+ position: absolute;
+ width: 24px;
+ height: 24px;
+ background: inherit;
+}
+
+.arrow {
+ visibility: hidden;
+}
+
+.arrow::before {
+ visibility: visible;
+ content: '';
+ transform: rotate(45deg);
+}
+
+.arrow {
+ bottom: -4px;
+}
+
.hover\:scale-105:hover {
--tw-scale-x: 1.05;
--tw-scale-y: 1.05;
@@ -3631,22 +3589,10 @@ input:checked + .toggle-bg {
}
@media (min-width: 640px) {
- .sm\:m-12 {
- margin: 3rem;
- }
-
.sm\:block {
display: block;
}
- .sm\:items-center {
- align-items: center;
- }
-
- .sm\:justify-center {
- justify-content: center;
- }
-
.sm\:rounded-lg {
border-radius: 0.5rem;
}
@@ -3655,10 +3601,6 @@ input:checked + .toggle-bg {
padding: 1.5rem;
}
- .sm\:p-12 {
- padding: 3rem;
- }
-
.sm\:py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index c0f187f1..aeab5789 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -84,7 +84,7 @@ c.clearChoices();
:popper nil})
:x-modelable "value.value"
:x-model (:x-model params)
- :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed'})"
+ :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [0, 20]}}})"
}
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
@@ -113,7 +113,7 @@ c.clearChoices();
[:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
- [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-lg py-1 w-max z-50"
+ [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50"
"x-ref" "dropdown"
"@keydown.escape" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
@@ -124,15 +124,20 @@ c.clearChoices();
"x-transition:leave-end" "!opacity-0 !mt-0"
"x-show " "open"
"x-trap" "open"
- "@click.outside" "open=false; console.log('is this ihid')"}
- [:input {:type "text" :class (hh/add-class (or (:class params) "") default-input-classes)
+ "@click.outside" "open=false;"}
+
+ [:input {:type "text"
+ :class (-> (:class params)
+ (or "")
+ (hh/add-class default-input-classes)
+ (hh/replace-wildcard ["rounded" "border"] "border-bottom bg-gray-100 rounded-t-lg w-full"))
"x-model" "search"
"placeholder" (:placeholder params)
"@keydown.down.prevent" "active ++; active = active >= elements.length - 1 ? elements.length - 1 : active"
"@keydown.up.prevent" "active --; active = active < 0 ? 0 : active"
- "@keydown.enter.prevent" "open = false; value = elements.length > 0 ? $data.elements[active] : {'value': '', label: ''}; console.log('are we here')"
+ "@keydown.enter.prevent" "open = false; value = elements.length > 0 ? $data.elements[active] : {'value': '', label: ''};"
"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
+ [:div.dropdown-options {:class "rounded-b-lg overflow-hidden"}
[: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-300 [&.active]:dark:bg-primary-700 text-gray-800 dark:text-gray-100"
:href "#"
@@ -143,9 +148,11 @@ c.clearChoices();
"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-800 dark:text-gray-100 text-xs "}
- "No results found"]]]]])
+ "No results found"]]]
+ ]])
+;; TODO fix search modal
(defn use-size [size]
(if (= :small size)
(str " " "text-xs p-2")
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index f9eb0bec..68e01e9a 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -66,7 +66,6 @@ input[type=number] {
contents
[:script {:src "/js/flowbite.min.js"}]
- [:div#tooltip.bg-red-500.p-12 {:role "tooltip"}]
[: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"
@@ -85,11 +84,7 @@ input[type=number] {
"x-transition:leave-start" "!bg-opacity-50"
"x-transition:leave-end" "!bg-opacity-0"}
- ;; TODO to get this right i think what needs to happen is to just set this up as having a single
- ;; div that is forced to the maximum allowed size. inside that will be a div that just centers
- ;; the elements, allowing it to grow as necessar. Then make the modal on the inside of this
- ;; div just use flexbox to make the inside part be the part that scrolls
- [:div {;;:class (str "sm:m-12 flex justify-center items-center bg-green-500 items-stretch inset-0")
+ [:div {
:class "flex h-full w-full justify-stretch md:justify-center items-stretch md:items-center "
"x-trap.inert.noscroll" "open"
"x-trap.inert" "open"
From a2d834794f13ee47e1c57801b9d88672afc2008a Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 13:55:31 -0700
Subject: [PATCH 28/34] ring.
---
resources/public/output.css | 18 ++++++++++++++++++
src/clj/auto_ap/ssr/components/inputs.clj | 2 +-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 571f55cd..a032d320 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -2513,6 +2513,24 @@ input:checked + .toggle-bg {
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
}
+.ring-4 {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
+}
+
+.ring-2 {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
+}
+
+.ring-1 {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
+}
+
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index aeab5789..aba64d7b 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -113,7 +113,7 @@ c.clearChoices();
[:div {:class "w-3 h-3 m-1 inline ml-1 justify-self-end text-gray-500 self-center"}
svg/drop-down]]]
- [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50"
+ [:ul.dropdown-contents {:class "bg-gray-100 dark:bg-gray-600 rounded-lg shadow-2xl w-max z-50 ring-1"
"x-ref" "dropdown"
"@keydown.escape" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
From 506d2ac78202c383e8a6b4952bebb3c100f82881 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 15:35:33 -0700
Subject: [PATCH 29/34] Makes background jobs work again
---
resources/public/output.css | 3757 +----------------
src/clj/auto_ap/ssr/admin/background_jobs.clj | 189 +-
.../auto_ap/ssr/admin/transaction_rules.clj | 5 +-
src/clj/auto_ap/ssr/components/dialog.clj | 9 +-
src/clj/auto_ap/ssr/components/inputs.clj | 10 +-
src/clj/auto_ap/ssr/components/navbar.clj | 5 +-
src/clj/auto_ap/ssr/components/page.clj | 1 +
src/clj/auto_ap/ssr/search.clj | 8 +-
src/clj/auto_ap/ssr/transaction/insights.clj | 10 +-
src/clj/auto_ap/ssr/utils.clj | 4 +-
10 files changed, 138 insertions(+), 3860 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index a032d320..60da88b9 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1,3756 +1 @@
-/*
-! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com
-*/
-
-/*
-1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
-2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
-*/
-
-*,
-::before,
-::after {
- box-sizing: border-box;
- /* 1 */
- border-width: 0;
- /* 2 */
- border-style: solid;
- /* 2 */
- border-color: #E5E7EB;
- /* 2 */
-}
-
-::before,
-::after {
- --tw-content: '';
-}
-
-/*
-1. Use a consistent sensible line-height in all browsers.
-2. Prevent adjustments of font size after orientation changes in iOS.
-3. Use a more readable tab size.
-4. Use the user's configured `sans` font-family by default.
-5. Use the user's configured `sans` font-feature-settings by default.
-6. Use the user's configured `sans` font-variation-settings by default.
-*/
-
-html {
- line-height: 1.5;
- /* 1 */
- -webkit-text-size-adjust: 100%;
- /* 2 */
- -moz-tab-size: 4;
- /* 3 */
- -o-tab-size: 4;
- tab-size: 4;
- /* 3 */
- font-family: Calibri, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
- /* 4 */
- font-feature-settings: normal;
- /* 5 */
- font-variation-settings: normal;
- /* 6 */
-}
-
-/*
-1. Remove the margin in all browsers.
-2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
-*/
-
-body {
- margin: 0;
- /* 1 */
- line-height: inherit;
- /* 2 */
-}
-
-/*
-1. Add the correct height in Firefox.
-2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
-3. Ensure horizontal rules are visible by default.
-*/
-
-hr {
- height: 0;
- /* 1 */
- color: inherit;
- /* 2 */
- border-top-width: 1px;
- /* 3 */
-}
-
-/*
-Add the correct text decoration in Chrome, Edge, and Safari.
-*/
-
-abbr:where([title]) {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
-}
-
-/*
-Remove the default font size and weight for headings.
-*/
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- font-size: inherit;
- font-weight: inherit;
-}
-
-/*
-Reset links to optimize for opt-in styling instead of opt-out.
-*/
-
-a {
- color: inherit;
- text-decoration: inherit;
-}
-
-/*
-Add the correct font weight in Edge and Safari.
-*/
-
-b,
-strong {
- font-weight: bolder;
-}
-
-/*
-1. Use the user's configured `mono` font family by default.
-2. Correct the odd `em` font sizing in all browsers.
-*/
-
-code,
-kbd,
-samp,
-pre {
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
- /* 1 */
- font-size: 1em;
- /* 2 */
-}
-
-/*
-Add the correct font size in all browsers.
-*/
-
-small {
- font-size: 80%;
-}
-
-/*
-Prevent `sub` and `sup` elements from affecting the line height in all browsers.
-*/
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-/*
-1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
-2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
-3. Remove gaps between table borders by default.
-*/
-
-table {
- text-indent: 0;
- /* 1 */
- border-color: inherit;
- /* 2 */
- border-collapse: collapse;
- /* 3 */
-}
-
-/*
-1. Change the font styles in all browsers.
-2. Remove the margin in Firefox and Safari.
-3. Remove default padding in all browsers.
-*/
-
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: inherit;
- /* 1 */
- font-size: 100%;
- /* 1 */
- font-weight: inherit;
- /* 1 */
- line-height: inherit;
- /* 1 */
- color: inherit;
- /* 1 */
- margin: 0;
- /* 2 */
- padding: 0;
- /* 3 */
-}
-
-/*
-Remove the inheritance of text transform in Edge and Firefox.
-*/
-
-button,
-select {
- text-transform: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Remove default button styles.
-*/
-
-button,
-[type='button'],
-[type='reset'],
-[type='submit'] {
- -webkit-appearance: button;
- /* 1 */
- background-color: transparent;
- /* 2 */
- background-image: none;
- /* 2 */
-}
-
-/*
-Use the modern Firefox focus style for all focusable elements.
-*/
-
-:-moz-focusring {
- outline: auto;
-}
-
-/*
-Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
-*/
-
-:-moz-ui-invalid {
- box-shadow: none;
-}
-
-/*
-Add the correct vertical alignment in Chrome and Firefox.
-*/
-
-progress {
- vertical-align: baseline;
-}
-
-/*
-Correct the cursor style of increment and decrement buttons in Safari.
-*/
-
-::-webkit-inner-spin-button,
-::-webkit-outer-spin-button {
- height: auto;
-}
-
-/*
-1. Correct the odd appearance in Chrome and Safari.
-2. Correct the outline style in Safari.
-*/
-
-[type='search'] {
- -webkit-appearance: textfield;
- /* 1 */
- outline-offset: -2px;
- /* 2 */
-}
-
-/*
-Remove the inner padding in Chrome and Safari on macOS.
-*/
-
-::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-/*
-1. Correct the inability to style clickable types in iOS and Safari.
-2. Change font properties to `inherit` in Safari.
-*/
-
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- /* 1 */
- font: inherit;
- /* 2 */
-}
-
-/*
-Add the correct display in Chrome and Safari.
-*/
-
-summary {
- display: list-item;
-}
-
-/*
-Removes the default spacing and border for appropriate elements.
-*/
-
-blockquote,
-dl,
-dd,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-hr,
-figure,
-p,
-pre {
- margin: 0;
-}
-
-fieldset {
- margin: 0;
- padding: 0;
-}
-
-legend {
- padding: 0;
-}
-
-ol,
-ul,
-menu {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-/*
-Prevent resizing textareas horizontally by default.
-*/
-
-textarea {
- resize: vertical;
-}
-
-/*
-1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
-2. Set the default placeholder color to the user's configured gray 400 color.
-*/
-
-input::-moz-placeholder, textarea::-moz-placeholder {
- opacity: 1;
- /* 1 */
- color: #9CA3AF;
- /* 2 */
-}
-
-input::placeholder,
-textarea::placeholder {
- opacity: 1;
- /* 1 */
- color: #9CA3AF;
- /* 2 */
-}
-
-/*
-Set the default cursor for buttons.
-*/
-
-button,
-[role="button"] {
- cursor: pointer;
-}
-
-/*
-Make sure disabled buttons don't get the pointer cursor.
-*/
-
-:disabled {
- cursor: default;
-}
-
-/*
-1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
-2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
- This can trigger a poorly considered lint error in some tools but is included by design.
-*/
-
-img,
-svg,
-video,
-canvas,
-audio,
-iframe,
-embed,
-object {
- display: block;
- /* 1 */
- vertical-align: middle;
- /* 2 */
-}
-
-/*
-Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
-*/
-
-img,
-video {
- max-width: 100%;
- height: auto;
-}
-
-/* Make elements with the HTML hidden attribute stay hidden by default */
-
-[hidden] {
- display: none;
-}
-
-[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: #fff;
- border-color: #6B7280;
- border-width: 1px;
- border-radius: 0px;
- padding-top: 0.5rem;
- padding-right: 0.75rem;
- padding-bottom: 0.5rem;
- padding-left: 0.75rem;
- font-size: 1rem;
- line-height: 1.5rem;
- --tw-shadow: 0 0 #0000;
-}
-
-[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #007dbb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- border-color: #007dbb;
-}
-
-input::-moz-placeholder, textarea::-moz-placeholder {
- color: #6B7280;
- opacity: 1;
-}
-
-input::placeholder,textarea::placeholder {
- color: #6B7280;
- opacity: 1;
-}
-
-::-webkit-datetime-edit-fields-wrapper {
- padding: 0;
-}
-
-::-webkit-date-and-time-value {
- min-height: 1.5em;
-}
-
-select:not([size]) {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
- background-position: right 0.5rem center;
- background-repeat: no-repeat;
- background-size: 1.5em 1.5em;
- padding-right: 2.5rem;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
-}
-
-[multiple] {
- background-image: initial;
- background-position: initial;
- background-repeat: unset;
- background-size: initial;
- padding-right: 0.75rem;
- -webkit-print-color-adjust: unset;
- print-color-adjust: unset;
-}
-
-[type='checkbox'],[type='radio'] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- padding: 0;
- -webkit-print-color-adjust: exact;
- print-color-adjust: exact;
- display: inline-block;
- vertical-align: middle;
- background-origin: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- flex-shrink: 0;
- height: 1rem;
- width: 1rem;
- color: #007dbb;
- background-color: #fff;
- border-color: #6B7280;
- border-width: 1px;
- --tw-shadow: 0 0 #0000;
-}
-
-[type='checkbox'] {
- border-radius: 0px;
-}
-
-[type='radio'] {
- border-radius: 100%;
-}
-
-[type='checkbox']:focus,[type='radio']:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
- --tw-ring-offset-width: 2px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #007dbb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
-}
-
-[type='checkbox']:checked,[type='radio']:checked,.dark [type='checkbox']:checked,.dark [type='radio']:checked {
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type='checkbox']:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
-}
-
-[type='radio']:checked {
- background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
-}
-
-[type='checkbox']:indeterminate {
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
- border-color: transparent;
- background-color: currentColor;
- background-size: 100% 100%;
- background-position: center;
- background-repeat: no-repeat;
-}
-
-[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
- border-color: transparent;
- background-color: currentColor;
-}
-
-[type='file'] {
- background: unset;
- border-color: inherit;
- border-width: 0;
- border-radius: 0;
- padding: 0;
- font-size: unset;
- line-height: inherit;
-}
-
-[type='file']:focus {
- outline: 1px auto inherit;
-}
-
-input[type=file]::file-selector-button {
- color: white;
- background: #1F2937;
- border: 0;
- font-weight: 500;
- font-size: 0.875rem;
- cursor: pointer;
- padding-top: 0.625rem;
- padding-bottom: 0.625rem;
- padding-left: 2rem;
- padding-right: 1rem;
- -webkit-margin-start: -1rem;
- margin-inline-start: -1rem;
- -webkit-margin-end: 1rem;
- margin-inline-end: 1rem;
-}
-
-input[type=file]::file-selector-button:hover {
- background: #374151;
-}
-
-.dark input[type=file]::file-selector-button {
- color: white;
- background: #4B5563;
-}
-
-.dark input[type=file]::file-selector-button:hover {
- background: #6B7280;
-}
-
-input[type="range"]::-webkit-slider-thumb {
- height: 1.25rem;
- width: 1.25rem;
- background: #007dbb;
- border-radius: 9999px;
- border: 0;
- appearance: none;
- -moz-appearance: none;
- -webkit-appearance: none;
- cursor: pointer;
-}
-
-input[type="range"]:disabled::-webkit-slider-thumb {
- background: #9CA3AF;
-}
-
-.dark input[type="range"]:disabled::-webkit-slider-thumb {
- background: #6B7280;
-}
-
-input[type="range"]:focus::-webkit-slider-thumb {
- outline: 2px solid transparent;
- outline-offset: 2px;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
- --tw-ring-opacity: 1px;
- --tw-ring-color: rgb(164 202 254 / var(--tw-ring-opacity));
-}
-
-input[type="range"]::-moz-range-thumb {
- height: 1.25rem;
- width: 1.25rem;
- background: #007dbb;
- border-radius: 9999px;
- border: 0;
- appearance: none;
- -moz-appearance: none;
- -webkit-appearance: none;
- cursor: pointer;
-}
-
-input[type="range"]:disabled::-moz-range-thumb {
- background: #9CA3AF;
-}
-
-.dark input[type="range"]:disabled::-moz-range-thumb {
- background: #6B7280;
-}
-
-input[type="range"]::-moz-range-progress {
- background: #009cea;
-}
-
-input[type="range"]::-ms-fill-lower {
- background: #009cea;
-}
-
-.toggle-bg:after {
- content: "";
- position: absolute;
- top: 0.125rem;
- left: 0.125rem;
- background: white;
- border-color: #D1D5DB;
- border-width: 1px;
- border-radius: 9999px;
- height: 1.25rem;
- width: 1.25rem;
- transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;
- transition-duration: .15s;
- box-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
-}
-
-input:checked + .toggle-bg:after {
- transform: translateX(100%);;
- border-color: white;
-}
-
-input:checked + .toggle-bg {
- background: #007dbb;
- border-color: #007dbb;
-}
-
-.tooltip-arrow,.tooltip-arrow:before {
- position: absolute;
- width: 8px;
- height: 8px;
- background: inherit;
-}
-
-.tooltip-arrow {
- visibility: hidden;
-}
-
-.tooltip-arrow:before {
- content: "";
- visibility: visible;
- transform: rotate(45deg);
-}
-
-[data-tooltip-style^='light'] + .tooltip > .tooltip-arrow:before {
- border-style: solid;
- border-color: #e5e7eb;
-}
-
-[data-tooltip-style^='light'] + .tooltip[data-popper-placement^='top'] > .tooltip-arrow:before {
- border-bottom-width: 1px;
- border-right-width: 1px;
-}
-
-[data-tooltip-style^='light'] + .tooltip[data-popper-placement^='right'] > .tooltip-arrow:before {
- border-bottom-width: 1px;
- border-left-width: 1px;
-}
-
-[data-tooltip-style^='light'] + .tooltip[data-popper-placement^='bottom'] > .tooltip-arrow:before {
- border-top-width: 1px;
- border-left-width: 1px;
-}
-
-[data-tooltip-style^='light'] + .tooltip[data-popper-placement^='left'] > .tooltip-arrow:before {
- border-top-width: 1px;
- border-right-width: 1px;
-}
-
-.tooltip[data-popper-placement^='top'] > .tooltip-arrow {
- bottom: -4px;
-}
-
-.tooltip[data-popper-placement^='bottom'] > .tooltip-arrow {
- top: -4px;
-}
-
-.tooltip[data-popper-placement^='left'] > .tooltip-arrow {
- right: -4px;
-}
-
-.tooltip[data-popper-placement^='right'] > .tooltip-arrow {
- left: -4px;
-}
-
-.tooltip.invisible > .tooltip-arrow:before {
- visibility: hidden;
-}
-
-[data-popper-arrow],[data-popper-arrow]:before {
- position: absolute;
- width: 8px;
- height: 8px;
- background: inherit;
-}
-
-[data-popper-arrow] {
- visibility: hidden;
-}
-
-[data-popper-arrow]:before {
- content: "";
- visibility: visible;
- transform: rotate(45deg);
-}
-
-[data-popper-arrow]:after {
- content: "";
- visibility: visible;
- transform: rotate(45deg);
- position: absolute;
- width: 9px;
- height: 9px;
- background: inherit;
-}
-
-[role="tooltip"] > [data-popper-arrow]:before {
- border-style: solid;
- border-color: #e5e7eb;
-}
-
-.dark [role="tooltip"] > [data-popper-arrow]:before {
- border-style: solid;
- border-color: #4b5563;
-}
-
-[role="tooltip"] > [data-popper-arrow]:after {
- border-style: solid;
- border-color: #e5e7eb;
-}
-
-.dark [role="tooltip"] > [data-popper-arrow]:after {
- border-style: solid;
- border-color: #4b5563;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='top'] > [data-popper-arrow]:before {
- border-bottom-width: 1px;
- border-right-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='top'] > [data-popper-arrow]:after {
- border-bottom-width: 1px;
- border-right-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='right'] > [data-popper-arrow]:before {
- border-bottom-width: 1px;
- border-left-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='right'] > [data-popper-arrow]:after {
- border-bottom-width: 1px;
- border-left-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='bottom'] > [data-popper-arrow]:before {
- border-top-width: 1px;
- border-left-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='bottom'] > [data-popper-arrow]:after {
- border-top-width: 1px;
- border-left-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='left'] > [data-popper-arrow]:before {
- border-top-width: 1px;
- border-right-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='left'] > [data-popper-arrow]:after {
- border-top-width: 1px;
- border-right-width: 1px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='top'] > [data-popper-arrow] {
- bottom: -5px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='bottom'] > [data-popper-arrow] {
- top: -5px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='left'] > [data-popper-arrow] {
- right: -5px;
-}
-
-[data-popover][role="tooltip"][data-popper-placement^='right'] > [data-popper-arrow] {
- left: -5px;
-}
-
-[role="tooltip"].invisible > [data-popper-arrow]:before {
- visibility: hidden;
-}
-
-[role="tooltip"].invisible > [data-popper-arrow]:after {
- visibility: hidden;
-}
-
-*, ::before, ::after {
- --tw-border-spacing-x: 0;
- --tw-border-spacing-y: 0;
- --tw-translate-x: 0;
- --tw-translate-y: 0;
- --tw-rotate: 0;
- --tw-skew-x: 0;
- --tw-skew-y: 0;
- --tw-scale-x: 1;
- --tw-scale-y: 1;
- --tw-pan-x: ;
- --tw-pan-y: ;
- --tw-pinch-zoom: ;
- --tw-scroll-snap-strictness: proximity;
- --tw-gradient-from-position: ;
- --tw-gradient-via-position: ;
- --tw-gradient-to-position: ;
- --tw-ordinal: ;
- --tw-slashed-zero: ;
- --tw-numeric-figure: ;
- --tw-numeric-spacing: ;
- --tw-numeric-fraction: ;
- --tw-ring-inset: ;
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: rgb(0 156 234 / 0.5);
- --tw-ring-offset-shadow: 0 0 #0000;
- --tw-ring-shadow: 0 0 #0000;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- --tw-blur: ;
- --tw-brightness: ;
- --tw-contrast: ;
- --tw-grayscale: ;
- --tw-hue-rotate: ;
- --tw-invert: ;
- --tw-saturate: ;
- --tw-sepia: ;
- --tw-drop-shadow: ;
- --tw-backdrop-blur: ;
- --tw-backdrop-brightness: ;
- --tw-backdrop-contrast: ;
- --tw-backdrop-grayscale: ;
- --tw-backdrop-hue-rotate: ;
- --tw-backdrop-invert: ;
- --tw-backdrop-opacity: ;
- --tw-backdrop-saturate: ;
- --tw-backdrop-sepia: ;
-}
-
-::backdrop {
- --tw-border-spacing-x: 0;
- --tw-border-spacing-y: 0;
- --tw-translate-x: 0;
- --tw-translate-y: 0;
- --tw-rotate: 0;
- --tw-skew-x: 0;
- --tw-skew-y: 0;
- --tw-scale-x: 1;
- --tw-scale-y: 1;
- --tw-pan-x: ;
- --tw-pan-y: ;
- --tw-pinch-zoom: ;
- --tw-scroll-snap-strictness: proximity;
- --tw-gradient-from-position: ;
- --tw-gradient-via-position: ;
- --tw-gradient-to-position: ;
- --tw-ordinal: ;
- --tw-slashed-zero: ;
- --tw-numeric-figure: ;
- --tw-numeric-spacing: ;
- --tw-numeric-fraction: ;
- --tw-ring-inset: ;
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: rgb(0 156 234 / 0.5);
- --tw-ring-offset-shadow: 0 0 #0000;
- --tw-ring-shadow: 0 0 #0000;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-colored: 0 0 #0000;
- --tw-blur: ;
- --tw-brightness: ;
- --tw-contrast: ;
- --tw-grayscale: ;
- --tw-hue-rotate: ;
- --tw-invert: ;
- --tw-saturate: ;
- --tw-sepia: ;
- --tw-drop-shadow: ;
- --tw-backdrop-blur: ;
- --tw-backdrop-brightness: ;
- --tw-backdrop-contrast: ;
- --tw-backdrop-grayscale: ;
- --tw-backdrop-hue-rotate: ;
- --tw-backdrop-invert: ;
- --tw-backdrop-opacity: ;
- --tw-backdrop-saturate: ;
- --tw-backdrop-sepia: ;
-}
-
-.container {
- width: 100%;
-}
-
-@media (min-width: 640px) {
- .container {
- max-width: 640px;
- }
-}
-
-@media (min-width: 768px) {
- .container {
- max-width: 768px;
- }
-}
-
-@media (min-width: 1024px) {
- .container {
- max-width: 1024px;
- }
-}
-
-@media (min-width: 1280px) {
- .container {
- max-width: 1280px;
- }
-}
-
-@media (min-width: 1536px) {
- .container {
- max-width: 1536px;
- }
-}
-
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
- border-width: 0;
-}
-
-.pointer-events-none {
- pointer-events: none;
-}
-
-.visible {
- visibility: visible;
-}
-
-.invisible {
- visibility: hidden;
-}
-
-.collapse {
- visibility: collapse;
-}
-
-.static {
- position: static;
-}
-
-.fixed {
- position: fixed;
-}
-
-.absolute {
- position: absolute;
-}
-
-.relative {
- position: relative;
-}
-
-.sticky {
- position: sticky;
-}
-
-.inset-0 {
- inset: 0px;
-}
-
-.inset-y-0 {
- top: 0px;
- bottom: 0px;
-}
-
-.-right-2 {
- right: -0.5rem;
-}
-
-.-top-2 {
- top: -0.5rem;
-}
-
-.bottom-0 {
- bottom: 0px;
-}
-
-.bottom-\[60px\] {
- bottom: 60px;
-}
-
-.left-0 {
- left: 0px;
-}
-
-.left-1\/2 {
- left: 50%;
-}
-
-.right-0 {
- right: 0px;
-}
-
-.right-2 {
- right: 0.5rem;
-}
-
-.top-0 {
- top: 0px;
-}
-
-.top-2 {
- top: 0.5rem;
-}
-
-.top-2\/4 {
- top: 50%;
-}
-
-.top-5 {
- top: 1.25rem;
-}
-
-.z-10 {
- z-index: 10;
-}
-
-.z-20 {
- z-index: 20;
-}
-
-.z-30 {
- z-index: 30;
-}
-
-.z-40 {
- z-index: 40;
-}
-
-.z-50 {
- z-index: 50;
-}
-
-.z-\[99\] {
- z-index: 99;
-}
-
-.col-span-1 {
- grid-column: span 1 / span 1;
-}
-
-.col-span-2 {
- grid-column: span 2 / span 2;
-}
-
-.col-span-3 {
- grid-column: span 3 / span 3;
-}
-
-.col-span-6 {
- grid-column: span 6 / span 6;
-}
-
-.col-start-1 {
- grid-column-start: 1;
-}
-
-.m-1 {
- margin: 0.25rem;
-}
-
-.m-4 {
- margin: 1rem;
-}
-
-.mx-2 {
- margin-left: 0.5rem;
- margin-right: 0.5rem;
-}
-
-.mx-4 {
- margin-left: 1rem;
- margin-right: 1rem;
-}
-
-.mx-auto {
- margin-left: auto;
- margin-right: auto;
-}
-
-.my-0 {
- margin-top: 0px;
- margin-bottom: 0px;
-}
-
-.my-4 {
- margin-top: 1rem;
- margin-bottom: 1rem;
-}
-
-.\!mt-0 {
- margin-top: 0px !important;
-}
-
-.\!mt-1 {
- margin-top: 0.25rem !important;
-}
-
-.-mb-1 {
- margin-bottom: -0.25rem;
-}
-
-.mb-1 {
- margin-bottom: 0.25rem;
-}
-
-.mb-2 {
- margin-bottom: 0.5rem;
-}
-
-.mb-3 {
- margin-bottom: 0.75rem;
-}
-
-.mb-4 {
- margin-bottom: 1rem;
-}
-
-.ml-1 {
- margin-left: 0.25rem;
-}
-
-.ml-2 {
- margin-left: 0.5rem;
-}
-
-.ml-3 {
- margin-left: 0.75rem;
-}
-
-.ml-auto {
- margin-left: auto;
-}
-
-.mr-1 {
- margin-right: 0.25rem;
-}
-
-.mr-10 {
- margin-right: 2.5rem;
-}
-
-.mr-16 {
- margin-right: 4rem;
-}
-
-.mr-2 {
- margin-right: 0.5rem;
-}
-
-.mr-3 {
- margin-right: 0.75rem;
-}
-
-.mt-0 {
- margin-top: 0px;
-}
-
-.mt-0\.5 {
- margin-top: 0.125rem;
-}
-
-.mt-1 {
- margin-top: 0.25rem;
-}
-
-.mt-2 {
- margin-top: 0.5rem;
-}
-
-.mt-4 {
- margin-top: 1rem;
-}
-
-.mt-5 {
- margin-top: 1.25rem;
-}
-
-.block {
- display: block;
-}
-
-.inline-block {
- display: inline-block;
-}
-
-.inline {
- display: inline;
-}
-
-.flex {
- display: flex;
-}
-
-.inline-flex {
- display: inline-flex;
-}
-
-.table {
- display: table;
-}
-
-.grid {
- display: grid;
-}
-
-.contents {
- display: contents;
-}
-
-.hidden {
- display: none;
-}
-
-.h-10 {
- height: 2.5rem;
-}
-
-.h-3 {
- height: 0.75rem;
-}
-
-.h-3\.5 {
- height: 0.875rem;
-}
-
-.h-4 {
- height: 1rem;
-}
-
-.h-48 {
- height: 12rem;
-}
-
-.h-5 {
- height: 1.25rem;
-}
-
-.h-6 {
- height: 1.5rem;
-}
-
-.h-64 {
- height: 16rem;
-}
-
-.h-8 {
- height: 2rem;
-}
-
-.h-96 {
- height: 24rem;
-}
-
-.h-full {
- height: 100%;
-}
-
-.h-screen {
- height: 100vh;
-}
-
-.max-h-96 {
- max-height: 24rem;
-}
-
-.max-h-full {
- max-height: 100%;
-}
-
-.w-1\/2 {
- width: 50%;
-}
-
-.w-16 {
- width: 4rem;
-}
-
-.w-24 {
- width: 6rem;
-}
-
-.w-3 {
- width: 0.75rem;
-}
-
-.w-3\.5 {
- width: 0.875rem;
-}
-
-.w-32 {
- width: 8rem;
-}
-
-.w-36 {
- width: 9rem;
-}
-
-.w-4 {
- width: 1rem;
-}
-
-.w-48 {
- width: 12rem;
-}
-
-.w-5 {
- width: 1.25rem;
-}
-
-.w-6 {
- width: 1.5rem;
-}
-
-.w-64 {
- width: 16rem;
-}
-
-.w-8 {
- width: 2rem;
-}
-
-.w-96 {
- width: 24rem;
-}
-
-.w-auto {
- width: auto;
-}
-
-.w-full {
- width: 100%;
-}
-
-.w-max {
- width: -moz-max-content;
- width: max-content;
-}
-
-.w-screen {
- width: 100vw;
-}
-
-.min-w-\[700px\] {
- min-width: 700px;
-}
-
-.max-w-2xl {
- max-width: 42rem;
-}
-
-.max-w-4xl {
- max-width: 56rem;
-}
-
-.max-w-6xl {
- max-width: 72rem;
-}
-
-.max-w-lg {
- max-width: 32rem;
-}
-
-.max-w-md {
- max-width: 28rem;
-}
-
-.max-w-screen-2xl {
- max-width: 1536px;
-}
-
-.max-w-screen-lg {
- max-width: 1024px;
-}
-
-.flex-1 {
- flex: 1 1 0%;
-}
-
-.flex-shrink {
- flex-shrink: 1;
-}
-
-.flex-shrink-0 {
- flex-shrink: 0;
-}
-
-.shrink {
- flex-shrink: 1;
-}
-
-.shrink-0 {
- flex-shrink: 0;
-}
-
-.flex-grow {
- flex-grow: 1;
-}
-
-.basis-1\/4 {
- flex-basis: 25%;
-}
-
-.\!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-x-1\/2 {
- --tw-translate-x: -50%;
- 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-x-full {
- --tw-translate-x: -100%;
- 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-1\/2 {
- --tw-translate-y: -50%;
- 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-full {
- --tw-translate-y: -100%;
- 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-x-0 {
- --tw-translate-x: 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-x-full {
- --tw-translate-x: 100%;
- 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-full {
- --tw-translate-y: 100%;
- 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));
-}
-
-.transform {
- 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));
-}
-
-.transform-none {
- transform: none;
-}
-
-@keyframes pulse {
- 50% {
- opacity: .5;
- }
-}
-
-.animate-pulse {
- animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
-}
-
-@keyframes shake {
- 0% {
- transform: translateX(0px);
- }
-
- 12.5% {
- transform: translateX(-5px);
- }
-
- 25% {
- transform: translateX(0px);
- }
-
- 37.5% {
- transform: translateX(5px);
- }
-
- 50% {
- transform: translateX(0px);
- }
-
- 62.5% {
- transform: translateX(-5px);
- }
-
- 75% {
- transform: translateX(5px);
- }
-
- 87.5% {
- transform: translateX(5px);
- }
-
- 100% {
- transform: translateX(0px);
- }
-}
-
-.animate-shake {
- animation: shake 0.5s ease-out 1;
-}
-
-@keyframes spin {
- to {
- transform: rotate(360deg);
- }
-}
-
-.animate-spin {
- animation: spin 1s linear infinite;
-}
-
-.cursor-default {
- cursor: default;
-}
-
-.cursor-not-allowed {
- cursor: not-allowed;
-}
-
-.cursor-pointer {
- cursor: pointer;
-}
-
-.resize {
- resize: both;
-}
-
-.list-none {
- list-style-type: none;
-}
-
-.appearance-none {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
-}
-
-.grid-cols-3 {
- grid-template-columns: repeat(3, minmax(0, 1fr));
-}
-
-.grid-cols-4 {
- grid-template-columns: repeat(4, minmax(0, 1fr));
-}
-
-.grid-cols-6 {
- grid-template-columns: repeat(6, minmax(0, 1fr));
-}
-
-.grid-cols-7 {
- grid-template-columns: repeat(7, minmax(0, 1fr));
-}
-
-.flex-row {
- flex-direction: row;
-}
-
-.flex-row-reverse {
- flex-direction: row-reverse;
-}
-
-.flex-col {
- flex-direction: column;
-}
-
-.flex-wrap {
- flex-wrap: wrap;
-}
-
-.place-items-center {
- place-items: center;
-}
-
-.items-start {
- align-items: flex-start;
-}
-
-.items-end {
- align-items: flex-end;
-}
-
-.items-center {
- align-items: center;
-}
-
-.items-baseline {
- align-items: baseline;
-}
-
-.items-stretch {
- align-items: stretch;
-}
-
-.justify-start {
- justify-content: flex-start;
-}
-
-.justify-end {
- justify-content: flex-end;
-}
-
-.justify-center {
- justify-content: center;
-}
-
-.justify-between {
- justify-content: space-between;
-}
-
-.justify-stretch {
- justify-content: stretch;
-}
-
-.justify-items-stretch {
- justify-items: stretch;
-}
-
-.gap-1 {
- gap: 0.25rem;
-}
-
-.gap-2 {
- gap: 0.5rem;
-}
-
-.gap-4 {
- gap: 1rem;
-}
-
-.gap-8 {
- gap: 2rem;
-}
-
-.gap-x-4 {
- -moz-column-gap: 1rem;
- column-gap: 1rem;
-}
-
-.-space-x-px > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(-1px * var(--tw-space-x-reverse));
- margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse)));
-}
-
-.space-x-1 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(0.25rem * var(--tw-space-x-reverse));
- margin-left: calc(0.25rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
-.space-x-2 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(0.5rem * var(--tw-space-x-reverse));
- margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
-.space-x-4 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(1rem * var(--tw-space-x-reverse));
- margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
-}
-
-.space-y-1 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));
-}
-
-.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
-}
-
-.space-y-2 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
-}
-
-.space-y-3 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
-}
-
-.space-y-4 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(1rem * var(--tw-space-y-reverse));
-}
-
-.space-y-6 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
-}
-
-.divide-y > :not([hidden]) ~ :not([hidden]) {
- --tw-divide-y-reverse: 0;
- border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
- border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
-}
-
-.divide-gray-100 > :not([hidden]) ~ :not([hidden]) {
- --tw-divide-opacity: 1;
- border-color: rgb(243 244 246 / var(--tw-divide-opacity));
-}
-
-.self-center {
- align-self: center;
-}
-
-.self-stretch {
- align-self: stretch;
-}
-
-.justify-self-end {
- justify-self: end;
-}
-
-.overflow-auto {
- overflow: auto;
-}
-
-.overflow-hidden {
- overflow: hidden;
-}
-
-.overflow-scroll {
- overflow: scroll;
-}
-
-.overflow-x-auto {
- overflow-x: auto;
-}
-
-.overflow-y-auto {
- overflow-y: auto;
-}
-
-.overflow-y-scroll {
- overflow-y: scroll;
-}
-
-.truncate {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.whitespace-nowrap {
- white-space: nowrap;
-}
-
-.rounded {
- border-radius: 0.25rem;
-}
-
-.rounded-full {
- border-radius: 9999px;
-}
-
-.rounded-lg {
- border-radius: 0.5rem;
-}
-
-.rounded-md {
- border-radius: 0.375rem;
-}
-
-.rounded-l-lg {
- border-top-left-radius: 0.5rem;
- border-bottom-left-radius: 0.5rem;
-}
-
-.rounded-r-lg {
- border-top-right-radius: 0.5rem;
- border-bottom-right-radius: 0.5rem;
-}
-
-.rounded-t {
- border-top-left-radius: 0.25rem;
- border-top-right-radius: 0.25rem;
-}
-
-.rounded-t-lg {
- border-top-left-radius: 0.5rem;
- border-top-right-radius: 0.5rem;
-}
-
-.rounded-b-lg {
- border-bottom-right-radius: 0.5rem;
- border-bottom-left-radius: 0.5rem;
-}
-
-.border {
- border-width: 1px;
-}
-
-.border-0 {
- border-width: 0px;
-}
-
-.border-2 {
- border-width: 2px;
-}
-
-.border-b {
- border-bottom-width: 1px;
-}
-
-.border-r {
- border-right-width: 1px;
-}
-
-.border-t {
- border-top-width: 1px;
-}
-
-.border-dashed {
- border-style: dashed;
-}
-
-.border-blue-300 {
- --tw-border-opacity: 1;
- border-color: rgb(102 196 242 / var(--tw-border-opacity));
-}
-
-.border-blue-600 {
- --tw-border-opacity: 1;
- border-color: rgb(0 125 187 / var(--tw-border-opacity));
-}
-
-.border-blue-700 {
- --tw-border-opacity: 1;
- border-color: rgb(0 94 140 / var(--tw-border-opacity));
-}
-
-.border-gray-100 {
- --tw-border-opacity: 1;
- border-color: rgb(243 244 246 / var(--tw-border-opacity));
-}
-
-.border-gray-200 {
- --tw-border-opacity: 1;
- border-color: rgb(229 231 235 / var(--tw-border-opacity));
-}
-
-.border-gray-300 {
- --tw-border-opacity: 1;
- border-color: rgb(209 213 219 / var(--tw-border-opacity));
-}
-
-.border-primary-300 {
- --tw-border-opacity: 1;
- border-color: rgb(175 211 130 / var(--tw-border-opacity));
-}
-
-.border-red-300 {
- --tw-border-opacity: 1;
- border-color: rgb(255 104 104 / var(--tw-border-opacity));
-}
-
-.border-white {
- --tw-border-opacity: 1;
- border-color: rgb(255 255 255 / var(--tw-border-opacity));
-}
-
-.bg-blue-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(204 235 251 / var(--tw-bg-opacity));
-}
-
-.bg-blue-200 {
- --tw-bg-opacity: 1;
- background-color: rgb(153 215 247 / var(--tw-bg-opacity));
-}
-
-.bg-blue-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(102 196 242 / var(--tw-bg-opacity));
-}
-
-.bg-blue-400 {
- --tw-bg-opacity: 1;
- background-color: rgb(51 176 238 / var(--tw-bg-opacity));
-}
-
-.bg-blue-50 {
- --tw-bg-opacity: 1;
- background-color: rgb(230 245 253 / var(--tw-bg-opacity));
-}
-
-.bg-blue-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(0 156 234 / var(--tw-bg-opacity));
-}
-
-.bg-blue-600 {
- --tw-bg-opacity: 1;
- background-color: rgb(0 125 187 / var(--tw-bg-opacity));
-}
-
-.bg-blue-700 {
- --tw-bg-opacity: 1;
- background-color: rgb(0 94 140 / var(--tw-bg-opacity));
-}
-
-.bg-blue-800 {
- --tw-bg-opacity: 1;
- background-color: rgb(0 62 94 / var(--tw-bg-opacity));
-}
-
-.bg-gray-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(243 244 246 / var(--tw-bg-opacity));
-}
-
-.bg-gray-200 {
- --tw-bg-opacity: 1;
- background-color: rgb(229 231 235 / var(--tw-bg-opacity));
-}
-
-.bg-gray-400 {
- --tw-bg-opacity: 1;
- background-color: rgb(156 163 175 / var(--tw-bg-opacity));
-}
-
-.bg-gray-50 {
- --tw-bg-opacity: 1;
- background-color: rgb(249 250 251 / var(--tw-bg-opacity));
-}
-
-.bg-gray-800 {
- --tw-bg-opacity: 1;
- background-color: rgb(31 41 55 / var(--tw-bg-opacity));
-}
-
-.bg-gray-900 {
- --tw-bg-opacity: 1;
- background-color: rgb(17 24 39 / var(--tw-bg-opacity));
-}
-
-.bg-green-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(228 240 213 / var(--tw-bg-opacity));
-}
-
-.bg-green-200 {
- --tw-bg-opacity: 1;
- background-color: rgb(201 225 171 / var(--tw-bg-opacity));
-}
-
-.bg-green-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity));
-}
-
-.bg-green-400 {
- --tw-bg-opacity: 1;
- background-color: rgb(148 196 88 / var(--tw-bg-opacity));
-}
-
-.bg-green-500 {
- --tw-bg-opacity: 1;
- background-color: rgb(121 181 46 / var(--tw-bg-opacity));
-}
-
-.bg-green-600 {
- --tw-bg-opacity: 1;
- background-color: rgb(97 145 37 / var(--tw-bg-opacity));
-}
-
-.bg-green-700 {
- --tw-bg-opacity: 1;
- background-color: rgb(73 109 28 / var(--tw-bg-opacity));
-}
-
-.bg-green-800 {
- --tw-bg-opacity: 1;
- background-color: rgb(48 72 18 / var(--tw-bg-opacity));
-}
-
-.bg-primary-50 {
- --tw-bg-opacity: 1;
- background-color: rgb(242 248 234 / var(--tw-bg-opacity));
-}
-
-.bg-red-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 205 205 / var(--tw-bg-opacity));
-}
-
-.bg-red-200 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 154 154 / var(--tw-bg-opacity));
-}
-
-.bg-red-300 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 104 104 / var(--tw-bg-opacity));
-}
-
-.bg-red-50 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 230 230 / var(--tw-bg-opacity));
-}
-
-.bg-white {
- --tw-bg-opacity: 1;
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
-}
-
-.bg-white\/50 {
- background-color: rgb(255 255 255 / 0.5);
-}
-
-.bg-yellow-100 {
- --tw-bg-opacity: 1;
- background-color: rgb(253 246 178 / var(--tw-bg-opacity));
-}
-
-.\!bg-opacity-0 {
- --tw-bg-opacity: 0 !important;
-}
-
-.\!bg-opacity-100 {
- --tw-bg-opacity: 1 !important;
-}
-
-.\!bg-opacity-50 {
- --tw-bg-opacity: 0.5 !important;
-}
-
-.bg-opacity-50 {
- --tw-bg-opacity: 0.5;
-}
-
-.p-1 {
- padding: 0.25rem;
-}
-
-.p-2 {
- padding: 0.5rem;
-}
-
-.p-2\.5 {
- padding: 0.625rem;
-}
-
-.p-3 {
- padding: 0.75rem;
-}
-
-.p-4 {
- padding: 1rem;
-}
-
-.px-2 {
- padding-left: 0.5rem;
- padding-right: 0.5rem;
-}
-
-.px-3 {
- padding-left: 0.75rem;
- padding-right: 0.75rem;
-}
-
-.px-4 {
- padding-left: 1rem;
- padding-right: 1rem;
-}
-
-.px-5 {
- padding-left: 1.25rem;
- padding-right: 1.25rem;
-}
-
-.px-6 {
- padding-left: 1.5rem;
- padding-right: 1.5rem;
-}
-
-.py-0 {
- padding-top: 0px;
- padding-bottom: 0px;
-}
-
-.py-0\.5 {
- padding-top: 0.125rem;
- padding-bottom: 0.125rem;
-}
-
-.py-1 {
- padding-top: 0.25rem;
- padding-bottom: 0.25rem;
-}
-
-.py-2 {
- padding-top: 0.5rem;
- padding-bottom: 0.5rem;
-}
-
-.py-2\.5 {
- padding-top: 0.625rem;
- padding-bottom: 0.625rem;
-}
-
-.py-3 {
- padding-top: 0.75rem;
- padding-bottom: 0.75rem;
-}
-
-.py-4 {
- padding-top: 1rem;
- padding-bottom: 1rem;
-}
-
-.py-5 {
- padding-top: 1.25rem;
- padding-bottom: 1.25rem;
-}
-
-.pb-2 {
- padding-bottom: 0.5rem;
-}
-
-.pb-3 {
- padding-bottom: 0.75rem;
-}
-
-.pl-10 {
- padding-left: 2.5rem;
-}
-
-.pl-11 {
- padding-left: 2.75rem;
-}
-
-.pl-2 {
- padding-left: 0.5rem;
-}
-
-.pl-3 {
- padding-left: 0.75rem;
-}
-
-.pr-2 {
- padding-right: 0.5rem;
-}
-
-.pr-2\.5 {
- padding-right: 0.625rem;
-}
-
-.pt-16 {
- padding-top: 4rem;
-}
-
-.pt-2 {
- padding-top: 0.5rem;
-}
-
-.pt-5 {
- padding-top: 1.25rem;
-}
-
-.pt-8 {
- padding-top: 2rem;
-}
-
-.text-left {
- text-align: left;
-}
-
-.text-center {
- text-align: center;
-}
-
-.text-right {
- text-align: right;
-}
-
-.align-baseline {
- vertical-align: baseline;
-}
-
-.align-top {
- vertical-align: top;
-}
-
-.text-2xl {
- font-size: 1.5rem;
- line-height: 2rem;
-}
-
-.text-base {
- font-size: 1rem;
- line-height: 1.5rem;
-}
-
-.text-lg {
- font-size: 1.125rem;
- line-height: 1.75rem;
-}
-
-.text-sm {
- font-size: 0.875rem;
- line-height: 1.25rem;
-}
-
-.text-xl {
- font-size: 1.25rem;
- line-height: 1.75rem;
-}
-
-.text-xs {
- font-size: 0.75rem;
- line-height: 1rem;
-}
-
-.font-bold {
- font-weight: 700;
-}
-
-.font-medium {
- font-weight: 500;
-}
-
-.font-normal {
- font-weight: 400;
-}
-
-.font-semibold {
- font-weight: 600;
-}
-
-.uppercase {
- text-transform: uppercase;
-}
-
-.italic {
- font-style: italic;
-}
-
-.leading-6 {
- line-height: 1.5rem;
-}
-
-.leading-9 {
- line-height: 2.25rem;
-}
-
-.leading-none {
- line-height: 1;
-}
-
-.leading-tight {
- line-height: 1.25;
-}
-
-.text-black {
- --tw-text-opacity: 1;
- color: rgb(0 0 0 / var(--tw-text-opacity));
-}
-
-.text-blue-400 {
- --tw-text-opacity: 1;
- color: rgb(51 176 238 / var(--tw-text-opacity));
-}
-
-.text-blue-600 {
- --tw-text-opacity: 1;
- color: rgb(0 125 187 / var(--tw-text-opacity));
-}
-
-.text-blue-800 {
- --tw-text-opacity: 1;
- color: rgb(0 62 94 / var(--tw-text-opacity));
-}
-
-.text-gray-400 {
- --tw-text-opacity: 1;
- color: rgb(156 163 175 / var(--tw-text-opacity));
-}
-
-.text-gray-500 {
- --tw-text-opacity: 1;
- color: rgb(107 114 128 / var(--tw-text-opacity));
-}
-
-.text-gray-600 {
- --tw-text-opacity: 1;
- color: rgb(75 85 99 / var(--tw-text-opacity));
-}
-
-.text-gray-700 {
- --tw-text-opacity: 1;
- color: rgb(55 65 81 / var(--tw-text-opacity));
-}
-
-.text-gray-800 {
- --tw-text-opacity: 1;
- color: rgb(31 41 55 / var(--tw-text-opacity));
-}
-
-.text-gray-900 {
- --tw-text-opacity: 1;
- color: rgb(17 24 39 / var(--tw-text-opacity));
-}
-
-.text-green-800 {
- --tw-text-opacity: 1;
- color: rgb(48 72 18 / var(--tw-text-opacity));
-}
-
-.text-primary-600 {
- --tw-text-opacity: 1;
- color: rgb(97 145 37 / var(--tw-text-opacity));
-}
-
-.text-red-500 {
- --tw-text-opacity: 1;
- color: rgb(255 3 3 / var(--tw-text-opacity));
-}
-
-.text-red-600 {
- --tw-text-opacity: 1;
- color: rgb(204 2 2 / var(--tw-text-opacity));
-}
-
-.text-red-800 {
- --tw-text-opacity: 1;
- color: rgb(102 1 1 / var(--tw-text-opacity));
-}
-
-.text-white {
- --tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
-}
-
-.text-yellow-800 {
- --tw-text-opacity: 1;
- color: rgb(114 59 19 / var(--tw-text-opacity));
-}
-
-.underline {
- text-decoration-line: underline;
-}
-
-.\!opacity-0 {
- opacity: 0 !important;
-}
-
-.\!opacity-100 {
- opacity: 1 !important;
-}
-
-.opacity-0 {
- opacity: 0;
-}
-
-.opacity-100 {
- opacity: 1;
-}
-
-.shadow {
- --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.shadow-lg {
- --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.shadow-md {
- --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
- --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.shadow-sm {
- --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
- --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.shadow-2xl {
- --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
- --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
-}
-
-.outline {
- outline-style: solid;
-}
-
-.outline-0 {
- outline-width: 0px;
-}
-
-.ring {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.ring-4 {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.ring-2 {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.ring-1 {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.blur {
- --tw-blur: blur(8px);
- filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
-}
-
-.filter {
- filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
-}
-
-.transition {
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
- transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 150ms;
-}
-
-.transition-all {
- transition-property: all;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 150ms;
-}
-
-.transition-opacity {
- transition-property: opacity;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 150ms;
-}
-
-.transition-transform {
- transition-property: transform;
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- transition-duration: 150ms;
-}
-
-.duration-100 {
- transition-duration: 100ms;
-}
-
-.duration-200 {
- transition-duration: 200ms;
-}
-
-.duration-300 {
- transition-duration: 300ms;
-}
-
-.duration-500 {
- transition-duration: 500ms;
-}
-
-.duration-75 {
- transition-duration: 75ms;
-}
-
-.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] {
- transition-timing-function: cubic-bezier(.3,2.3,.6,1);
-}
-
-.ease-in-out {
- transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-.ease-out {
- transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
-}
-
-.htmx-added .fade-in {
- opacity: 0.0 !important;
-}
-
-.htmx-added.fade-in {
- opacity: 0.0 !important;
-}
-
-.fade-in {
- opacity: 1.0;
-}
-
-.htmx-settling .fade-in-settle {
- opacity: 0.0 !important;
-}
-
-.htmx-settling.fade-in-settle {
- opacity: 0.0 !important;
-}
-
-.fade-in-settle {
- opacity: 1.0;
-}
-
-.htmx-settling .slide-up-settle {
- --tw-translate-y: 1.25rem !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;
-}
-
-.htmx-settling.slide-up-settle {
- --tw-translate-y: 1.25rem !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;
-}
-
-.slide-up-settle {
- --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));
-}
-
-.htmx-added .slide-up {
- --tw-translate-y: 1.25rem !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;
-}
-
-.hidden .slide-up {
- --tw-translate-y: 1.25rem !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;
-}
-
-.slide-up {
- --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));
-}
-
-.live-added {
- animation: pulse-green 300ms 2;
- animation-direction: alternate;
- animation-timing-function: ease-in-out;
-}
-
-.dark .live-added {
- animation: pulse-dark-green 300ms 2 !important;
- animation-direction: alternate;
- animation-timing-function: ease-in-out;
-}
-
-/*
-.live-added {
- @apply bg-white;
-}
-*/
-
-@keyframes pulse-green {
- 0% {
- --tw-bg-opacity: 1;
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
- }
-
- 100% {
- --tw-bg-opacity: 1;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity));
- }
-
- :is(.dark 100%) {
- --tw-bg-opacity: 1;
- background-color: rgb(153 2 2 / var(--tw-bg-opacity));
- }
-}
-
-@keyframes pulse-dark-green {
- :is(.dark 0%) {
- --tw-bg-opacity: 1;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity));
- }
-
- 100% {
- --tw-bg-opacity: 1;
- background-color: rgb(73 109 28 / var(--tw-bg-opacity));
- }
-}
-
-.htmx-request .htmx-indicator, .htmx-request.htmx-indicator {
- display: inherit !important;
-}
-
-.htmx-indicator {
- display: none;
-}
-
-.htmx-request .htmx-indicator-hidden {
- display: none !important;
-}
-
-.htmx-indicator-hidden {
- display: inherit;
-}
-
-.htmx-swapping .fade-out {
- opacity: 0.0 !important;
-}
-
-.fade-out {
- opacity: 1.0;
-}
-
-.min-h-content {
- min-height: calc(100vh - 4em);
-}
-
-.choices {
- margin-bottom: 0px !important;
- border-width: 0px !important;
-}
-
-.choices__list--multiple {
-}
-
-.choices__inner {
- display: block !important;
- width: 100% !important;
- border-radius: 0.5rem !important;
- border-width: 1px !important;
- --tw-border-opacity: 1 !important;
- border-color: rgb(209 213 219 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(249 250 251 / var(--tw-bg-opacity)) !important;
- padding: 0.25rem !important;
- font-size: 0.875rem !important;
- line-height: 1.25rem !important;
- --tw-text-opacity: 1 !important;
- color: rgb(17 24 39 / var(--tw-text-opacity)) !important;
-}
-
-.choices__inner:focus {
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-.group.has-error .choices__inner {
- --tw-border-opacity: 1 !important;
- border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(255 230 230 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(51 1 1 / var(--tw-text-opacity)) !important;
-}
-
-.group.has-error .choices__inner::-moz-placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(153 2 2 / var(--tw-placeholder-opacity)) !important;
-}
-
-.group.has-error .choices__inner::placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(153 2 2 / var(--tw-placeholder-opacity)) !important;
-}
-
-.group.has-error .choices__inner:focus {
- --tw-border-opacity: 1 !important;
- border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(255 3 3 / var(--tw-ring-opacity)) !important;
-}
-
-:is(.dark .choices__inner) {
- --tw-border-opacity: 1 !important;
- border-color: rgb(75 85 99 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(255 255 255 / var(--tw-text-opacity)) !important;
-}
-
-:is(.dark .choices__inner)::-moz-placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(156 163 175 / var(--tw-placeholder-opacity)) !important;
-}
-
-:is(.dark .choices__inner)::placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(156 163 175 / var(--tw-placeholder-opacity)) !important;
-}
-
-:is(.dark .choices__inner:focus) {
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-.group.has-error :is(.dark .choices__inner) {
- --tw-border-opacity: 1 !important;
- border-color: rgb(255 3 3 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(255 3 3 / var(--tw-text-opacity)) !important;
-}
-
-.group.has-error :is(.dark .choices__inner)::-moz-placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(255 3 3 / var(--tw-placeholder-opacity)) !important;
-}
-
-.group.has-error :is(.dark .choices__inner)::placeholder {
- --tw-placeholder-opacity: 1 !important;
- color: rgb(255 3 3 / var(--tw-placeholder-opacity)) !important;
-}
-
-.choices:focus-within .choices__inner {
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-:is(.dark .choices:focus-within .choices__inner) {
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-.choices:focus-within .choices__inner {
- outline: 2px solid transparent !important;
- outline-offset: 2px;
- --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-color: #007dbb;
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- border-color: #007dbb;
-}
-
-.choices__inner .choices__input {
- margin: 0px !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(249 250 251 / var(--tw-bg-opacity)) !important;
-}
-
-:is(.dark .choices__inner .choices__input) {
- --tw-bg-opacity: 1 !important;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(255 255 255 / var(--tw-text-opacity)) !important;
-}
-
-.choices__inner .choices__item {
- white-space: nowrap !important;
- border-radius: 0.25rem !important;
- --tw-border-opacity: 1 !important;
- border-color: rgb(156 163 175 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity)) !important;
- padding-left: 0.5rem !important;
- padding-right: 0.5rem !important;
- padding-top: 0.125rem !important;
- padding-bottom: 0.125rem !important;
- font-size: 0.75rem !important;
- line-height: 1rem !important;
- font-weight: 500 !important;
- --tw-text-opacity: 1 !important;
- color: rgb(48 72 18 / var(--tw-text-opacity)) !important;
-}
-
-:is(.dark .choices__inner .choices__item) {
- --tw-bg-opacity: 1 !important;
- background-color: rgb(24 36 9 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(175 211 130 / var(--tw-text-opacity)) !important;
-}
-
-.choices__list--dropdown {
- border-radius: 0.5rem !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(255 255 255 / var(--tw-bg-opacity)) !important;
- --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) !important;
- --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color) !important;
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
-}
-
-:is(.dark .choices__list--dropdown) {
- --tw-bg-opacity: 1 !important;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity)) !important;
-}
-
-.choices__list--dropdown .choices__item--selectable.is-highlighted {
- --tw-bg-opacity: 1 !important;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(48 72 18 / var(--tw-text-opacity)) !important;
-}
-
-:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted) {
- --tw-bg-opacity: 1 !important;
- background-color: rgb(24 36 9 / var(--tw-bg-opacity)) !important;
- --tw-text-opacity: 1 !important;
- color: rgb(175 211 130 / var(--tw-text-opacity)) !important;
-}
-
-.choices[data-type*="select-multiple"] .choices__button {
- --tw-border-opacity: 1 !important;
- border-color: rgb(107 114 128 / var(--tw-border-opacity)) !important;
-}
-
-.choices[data-type*="select-multiple"] .choices__button:focus {
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-.choices__inner .choices__item:focus-within {
- border-color: rgb(107 114 128 / var(--tw-border-opacity)) !important;
- --tw-border-opacity: 1 !important;
- border-color: rgb(0 156 234 / var(--tw-border-opacity)) !important;
- --tw-bg-opacity: 1 !important;
- background-color: rgb(121 181 46 / var(--tw-bg-opacity)) !important;
- --tw-ring-opacity: 1 !important;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)) !important;
-}
-
-.choices__list--single .choices__item {
- display: flex !important;
- width: auto !important;
-}
-
-.choices__list--single {
- width: auto !important;
-}
-
-.choices__list--single button {
- position: relative !important;
- margin: 0px !important;
- display: block !important;
- height: auto !important;
-}
-
-.choices[data-type*="select-one"] .choices__button {
- right:auto !important;
-}
-
-.arrow,
-.arrow::before {
- position: absolute;
- width: 24px;
- height: 24px;
- background: inherit;
-}
-
-.arrow {
- visibility: hidden;
-}
-
-.arrow::before {
- visibility: visible;
- content: '';
- transform: rotate(45deg);
-}
-
-.arrow {
- bottom: -4px;
-}
-
-.hover\:scale-105:hover {
- --tw-scale-x: 1.05;
- --tw-scale-y: 1.05;
- 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));
-}
-
-.hover\:scale-110:hover {
- --tw-scale-x: 1.1;
- --tw-scale-y: 1.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));
-}
-
-.hover\:border-gray-300:hover {
- --tw-border-opacity: 1;
- border-color: rgb(209 213 219 / var(--tw-border-opacity));
-}
-
-.hover\:bg-blue-300:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(102 196 242 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-blue-600:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(0 125 187 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-blue-800:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(0 62 94 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-gray-100:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(243 244 246 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-gray-200:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(229 231 235 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-green-100:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(228 240 213 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-green-300:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-green-600:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(97 145 37 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-green-700:hover {
- --tw-bg-opacity: 1;
- 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));
-}
-
-.hover\:bg-red-300:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(255 104 104 / var(--tw-bg-opacity));
-}
-
-.hover\:bg-white:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(255 255 255 / var(--tw-bg-opacity));
-}
-
-.hover\:text-blue-600:hover {
- --tw-text-opacity: 1;
- color: rgb(0 125 187 / var(--tw-text-opacity));
-}
-
-.hover\:text-gray-600:hover {
- --tw-text-opacity: 1;
- color: rgb(75 85 99 / var(--tw-text-opacity));
-}
-
-.hover\:text-gray-700:hover {
- --tw-text-opacity: 1;
- color: rgb(55 65 81 / var(--tw-text-opacity));
-}
-
-.hover\:text-gray-800:hover {
- --tw-text-opacity: 1;
- color: rgb(31 41 55 / var(--tw-text-opacity));
-}
-
-.hover\:text-gray-900:hover {
- --tw-text-opacity: 1;
- color: rgb(17 24 39 / var(--tw-text-opacity));
-}
-
-.hover\:text-primary-700:hover {
- --tw-text-opacity: 1;
- color: rgb(73 109 28 / var(--tw-text-opacity));
-}
-
-.hover\:underline:hover {
- text-decoration-line: underline;
-}
-
-.focus\:z-10:focus {
- z-index: 10;
-}
-
-.focus\:border-blue-500:focus {
- --tw-border-opacity: 1;
- border-color: rgb(0 156 234 / var(--tw-border-opacity));
-}
-
-.focus\:border-primary-500:focus {
- --tw-border-opacity: 1;
- border-color: rgb(121 181 46 / var(--tw-border-opacity));
-}
-
-.focus\:bg-neutral-100:focus {
- --tw-bg-opacity: 1;
- background-color: rgb(245 245 245 / var(--tw-bg-opacity));
-}
-
-.focus\:text-green-700:focus {
- --tw-text-opacity: 1;
- color: rgb(73 109 28 / var(--tw-text-opacity));
-}
-
-.focus\:outline-none:focus {
- outline: 2px solid transparent;
- outline-offset: 2px;
-}
-
-.focus\:ring-2:focus {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.focus\:ring-4:focus {
- --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
- --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
- box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
-}
-
-.focus\:ring-blue-200:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(153 215 247 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-blue-300:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(102 196 242 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-blue-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-gray-200:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(229 231 235 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-gray-300:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(209 213 219 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-green-200:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(201 225 171 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-green-300:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(175 211 130 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-green-700:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(73 109 28 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-primary-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(121 181 46 / var(--tw-ring-opacity));
-}
-
-.focus\:ring-red-200:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(255 154 154 / var(--tw-ring-opacity));
-}
-
-.group:hover .group-hover\:scale-110 {
- --tw-scale-x: 1.1;
- --tw-scale-y: 1.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));
-}
-
-.group:hover .group-hover\:text-blue-500 {
- --tw-text-opacity: 1;
- color: rgb(0 156 234 / var(--tw-text-opacity));
-}
-
-.group:hover .group-hover\:text-gray-900 {
- --tw-text-opacity: 1;
- color: rgb(17 24 39 / var(--tw-text-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:border-red-500 {
- --tw-border-opacity: 1;
- border-color: rgb(255 3 3 / var(--tw-border-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:bg-red-50 {
- --tw-bg-opacity: 1;
- background-color: rgb(255 230 230 / var(--tw-bg-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:text-red-900 {
- --tw-text-opacity: 1;
- color: rgb(51 1 1 / var(--tw-text-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(153 2 2 / var(--tw-placeholder-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(153 2 2 / var(--tw-placeholder-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus {
- --tw-border-opacity: 1;
- border-color: rgb(255 3 3 / var(--tw-border-opacity));
-}
-
-.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(255 3 3 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:block) {
- display: block;
-}
-
-:is(.dark .dark\:hidden) {
- display: none;
-}
-
-:is(.dark .dark\:divide-gray-600) > :not([hidden]) ~ :not([hidden]) {
- --tw-divide-opacity: 1;
- border-color: rgb(75 85 99 / var(--tw-divide-opacity));
-}
-
-:is(.dark .dark\:border-blue-500) {
- --tw-border-opacity: 1;
- border-color: rgb(0 156 234 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:border-gray-500) {
- --tw-border-opacity: 1;
- border-color: rgb(107 114 128 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:border-gray-600) {
- --tw-border-opacity: 1;
- border-color: rgb(75 85 99 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:border-gray-700) {
- --tw-border-opacity: 1;
- border-color: rgb(55 65 81 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:border-gray-900) {
- --tw-border-opacity: 1;
- border-color: rgb(17 24 39 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:border-transparent) {
- border-color: transparent;
-}
-
-:is(.dark .dark\:bg-blue-600) {
- --tw-bg-opacity: 1;
- background-color: rgb(0 125 187 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-blue-700) {
- --tw-bg-opacity: 1;
- background-color: rgb(0 94 140 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-blue-900) {
- --tw-bg-opacity: 1;
- background-color: rgb(0 31 47 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-gray-600) {
- --tw-bg-opacity: 1;
- background-color: rgb(75 85 99 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-gray-700) {
- --tw-bg-opacity: 1;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-gray-800) {
- --tw-bg-opacity: 1;
- background-color: rgb(31 41 55 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-gray-800\/50) {
- background-color: rgb(31 41 55 / 0.5);
-}
-
-:is(.dark .dark\:bg-gray-900) {
- --tw-bg-opacity: 1;
- background-color: rgb(17 24 39 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-green-600) {
- --tw-bg-opacity: 1;
- background-color: rgb(97 145 37 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-green-700) {
- --tw-bg-opacity: 1;
- background-color: rgb(73 109 28 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-green-900) {
- --tw-bg-opacity: 1;
- background-color: rgb(24 36 9 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-red-700) {
- --tw-bg-opacity: 1;
- background-color: rgb(153 2 2 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-red-900) {
- --tw-bg-opacity: 1;
- background-color: rgb(51 1 1 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-yellow-900) {
- --tw-bg-opacity: 1;
- background-color: rgb(99 49 18 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:bg-opacity-80) {
- --tw-bg-opacity: 0.8;
-}
-
-:is(.dark .dark\:text-blue-200) {
- --tw-text-opacity: 1;
- color: rgb(153 215 247 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-blue-300) {
- --tw-text-opacity: 1;
- color: rgb(102 196 242 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-blue-400) {
- --tw-text-opacity: 1;
- color: rgb(51 176 238 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-blue-500) {
- --tw-text-opacity: 1;
- color: rgb(0 156 234 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-100) {
- --tw-text-opacity: 1;
- color: rgb(243 244 246 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-200) {
- --tw-text-opacity: 1;
- color: rgb(229 231 235 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-300) {
- --tw-text-opacity: 1;
- color: rgb(209 213 219 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-400) {
- --tw-text-opacity: 1;
- color: rgb(156 163 175 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-50) {
- --tw-text-opacity: 1;
- color: rgb(249 250 251 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-gray-500) {
- --tw-text-opacity: 1;
- color: rgb(107 114 128 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-green-300) {
- --tw-text-opacity: 1;
- color: rgb(175 211 130 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-red-300) {
- --tw-text-opacity: 1;
- color: rgb(255 104 104 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-red-400) {
- --tw-text-opacity: 1;
- color: rgb(255 53 53 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-red-500) {
- --tw-text-opacity: 1;
- color: rgb(255 3 3 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-white) {
- --tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:text-yellow-300) {
- --tw-text-opacity: 1;
- color: rgb(250 202 21 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(156 163 175 / var(--tw-placeholder-opacity));
-}
-
-:is(.dark .dark\:placeholder-gray-400)::placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(156 163 175 / var(--tw-placeholder-opacity));
-}
-
-:is(.dark .dark\:ring-offset-gray-700) {
- --tw-ring-offset-color: #374151;
-}
-
-:is(.dark .dark\:ring-offset-gray-800) {
- --tw-ring-offset-color: #1F2937;
-}
-
-:is(.dark .dark\:hover\:bg-blue-600:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(0 125 187 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-blue-700:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(0 94 140 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-gray-600:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(75 85 99 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-gray-700:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-gray-800:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(31 41 55 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-green-600:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(97 145 37 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-green-700:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(73 109 28 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:bg-red-600:hover) {
- --tw-bg-opacity: 1;
- background-color: rgb(204 2 2 / var(--tw-bg-opacity));
-}
-
-:is(.dark .dark\:hover\:text-blue-500:hover) {
- --tw-text-opacity: 1;
- color: rgb(0 156 234 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:hover\:text-gray-100:hover) {
- --tw-text-opacity: 1;
- color: rgb(243 244 246 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:hover\:text-gray-300:hover) {
- --tw-text-opacity: 1;
- color: rgb(209 213 219 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:hover\:text-white:hover) {
- --tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:focus\:border-blue-500:focus) {
- --tw-border-opacity: 1;
- border-color: rgb(0 156 234 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:focus\:border-primary-500:focus) {
- --tw-border-opacity: 1;
- border-color: rgb(121 181 46 / var(--tw-border-opacity));
-}
-
-:is(.dark .dark\:focus\:text-white:focus) {
- --tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-blue-500:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-blue-600:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(0 125 187 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-blue-800:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(0 62 94 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-gray-600:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-green-500:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(121 181 46 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-green-800:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(48 72 18 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-primary-500:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(121 181 46 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-primary-600:focus) {
- --tw-ring-opacity: 1;
- --tw-ring-color: rgb(97 145 37 / var(--tw-ring-opacity));
-}
-
-:is(.dark .dark\:focus\:ring-offset-gray-700:focus) {
- --tw-ring-offset-color: #374151;
-}
-
-:is(.dark .group:hover .dark\:group-hover\:text-white) {
- --tw-text-opacity: 1;
- color: rgb(255 255 255 / var(--tw-text-opacity));
-}
-
-.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500) {
- --tw-border-opacity: 1;
- border-color: rgb(255 3 3 / var(--tw-border-opacity));
-}
-
-.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700) {
- --tw-bg-opacity: 1;
- background-color: rgb(55 65 81 / var(--tw-bg-opacity));
-}
-
-.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500) {
- --tw-text-opacity: 1;
- color: rgb(255 3 3 / var(--tw-text-opacity));
-}
-
-.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(255 3 3 / var(--tw-placeholder-opacity));
-}
-
-.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder {
- --tw-placeholder-opacity: 1;
- color: rgb(255 3 3 / var(--tw-placeholder-opacity));
-}
-
-@media (min-width: 640px) {
- .sm\:block {
- display: block;
- }
-
- .sm\:rounded-lg {
- border-radius: 0.5rem;
- }
-
- .sm\:p-6 {
- padding: 1.5rem;
- }
-
- .sm\:py-5 {
- padding-top: 1.25rem;
- padding-bottom: 1.25rem;
- }
-
- .sm\:text-sm {
- font-size: 0.875rem;
- line-height: 1.25rem;
- }
-}
-
-@media (min-width: 768px) {
- .md\:ml-2 {
- margin-left: 0.5rem;
- }
-
- .md\:mr-24 {
- margin-right: 6rem;
- }
-
- .md\:table-cell {
- display: table-cell;
- }
-
- .md\:flex-row {
- flex-direction: row;
- }
-
- .md\:items-center {
- align-items: center;
- }
-
- .md\:justify-center {
- justify-content: center;
- }
-
- .md\:space-x-3 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(0.75rem * var(--tw-space-x-reverse));
- margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
- }
-
- .md\:space-y-0 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0px * var(--tw-space-y-reverse));
- }
-
- .md\:p-12 {
- padding: 3rem;
- }
-}
-
-@media (min-width: 1024px) {
- .lg\:block {
- display: block;
- }
-
- .lg\:flex {
- display: flex;
- }
-
- .lg\:table-cell {
- display: table-cell;
- }
-
- .lg\:hidden {
- display: none;
- }
-
- .lg\:w-96 {
- width: 24rem;
- }
-
- .lg\:translate-x-0 {
- --tw-translate-x: 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));
- }
-
- .lg\:flex-row {
- flex-direction: row;
- }
-
- .lg\:items-center {
- align-items: center;
- }
-
- .lg\:justify-end {
- justify-content: flex-end;
- }
-
- .lg\:justify-between {
- justify-content: space-between;
- }
-
- .lg\:space-x-4 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-x-reverse: 0;
- margin-right: calc(1rem * var(--tw-space-x-reverse));
- margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
- }
-
- .lg\:space-y-0 > :not([hidden]) ~ :not([hidden]) {
- --tw-space-y-reverse: 0;
- margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
- margin-bottom: calc(0px * var(--tw-space-y-reverse));
- }
-
- .lg\:px-5 {
- padding-left: 1.25rem;
- padding-right: 1.25rem;
- }
-
- .lg\:pl-3 {
- padding-left: 0.75rem;
- }
-
- .lg\:pl-64 {
- padding-left: 16rem;
- }
-}
-
-.\[\&\.active\]\:bg-primary-300.active {
- --tw-bg-opacity: 1;
- background-color: rgb(175 211 130 / var(--tw-bg-opacity));
-}
-
-.\[\&\.active\]\:bg-primary-500.active {
- --tw-bg-opacity: 1;
- background-color: rgb(121 181 46 / 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));
-}
+/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.rotate-180,.translate-y-full{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}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x: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))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
diff --git a/src/clj/auto_ap/ssr/admin/background_jobs.clj b/src/clj/auto_ap/ssr/admin/background_jobs.clj
index 58f4bb47..ec1ecdfc 100644
--- a/src/clj/auto_ap/ssr/admin/background_jobs.clj
+++ b/src/clj/auto_ap/ssr/admin/background_jobs.clj
@@ -2,24 +2,28 @@
(:require
[amazonica.aws.ecs :as ecs]
[auto-ap.logging :as alog]
+ [clojure.string :as str]
[auto-ap.routes.utils
:refer [wrap-admin wrap-client-redirect-unauthenticated]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
+ [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
[auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.utils
:refer [apply-middleware-to-all-handlers
+ entity-id
+ form-validation-error
html-response
- validation-error
- wrap-form-4xx
+ modal-response
+ wrap-form-4xx-2
wrap-schema-decode]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as coerce]
[clj-time.core :as time]
- [clojure.string :as str]
- [config.core :refer [env]])
+ [malli.core :as mc]
+ [auto-ap.ssr.hx :as hx])
(:import
(com.amazonaws.services.ecs.model AssignPublicIp)))
@@ -57,8 +61,8 @@
false))
(defn ecs-task->job [task]
-
- {:status (condp = (:last-status task)
+ {:arn (:task-arn task)
+ :status (condp = (:last-status task)
"RUNNING" :running
"PENDING" :pending
"PROVISIONING" :pending
@@ -78,13 +82,11 @@
(def grid-page
(helper/build {:id "job-table"
+ :id-fn :arn
:nav (com/admin-aside-nav)
:fetch-page fetch-page
:action-buttons (fn [request]
- [(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes
- :admin-job-start-dialog))
- :hx-target "#modal-holder"
- :hx-swap "outerHTML"
+ [(com/button {:hx-get (str (bidi/path-for ssr-routes/only-routes :admin-job-start-dialog))
:color :primary}
"Run job")])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
@@ -151,86 +153,119 @@
(str "_" (:dd-env env)))
(dissoc form-params :name))]
{:message (str "task " (str new-job) " started.")})
- (validation-error "This job is already running")))
+ (form-validation-error "This job is already running"
+ :form form-params)))
-(defn subform [{{:strs [name]} :query-params }]
- (html-response (cond (= "bulk-journal-import" name)
- [:div (com/field {:label "Url"}
- [:div.flex.place-items-center.gap-2
- [:pre.text-xs.mr-1 "s3://data.prod.app.integreatconsult.com/bulk-import/"]
- (com/text-input {:placeholder "ledger-data.csv"
- :name "ledger-url"} )])]
- (= "register-invoice-import" name)
- [:div (com/field {:label "Url"}
+(defn subform* [{:keys [name]}]
+ (into [:div {:class "fade-in-settle transition"}]
+ (cond (= "bulk-journal-import" name)
+ [(fc/with-field :ledger-url
+ (com/validated-field {:label "Url"
+ :errors (fc/field-errors)}
+ [:div.flex.place-items-center.gap-2
+ [:pre.text-xs.mr-1 "s3://data.prod.app.integreatconsult.com/bulk-import/"]
+ (com/text-input {:placeholder "ledger-data.csv"
+ :name (fc/field-name)
+ :value (fc/field-value)} )]))]
+ (= "register-invoice-import" name)
+ [
+ (fc/with-field :invoice-url
+ (com/validated-field {:label "Url"
+ :errors (fc/field-errors)}
[:div.flex.place-items-center.gap-2
[:pre.text-xs.mr-1 "s3://data.prod.app.integreatconsult.com/bulk-import/"]
(com/text-input {:placeholder "invoice-data.csv"
- :name "invoice-url"} )])]
- (= "load-historical-sales" name)
- [:div
- (com/field {:label "Client"}
- (com/typeahead {:name "client"
- :placeholder "Search..."
- :url (bidi/path-for ssr-routes/only-routes
- :company-search)
- :id (str "client-search")}))
- (com/field {:label "Days to load"}
- (com/text-input {:placeholder "60"
- :name "days"} ))]
- :else [:div]))
+ :name (fc/field-name)
+ :value (fc/field-value)} )]))]
+ (= "load-historical-sales" name)
+ [
+ (fc/with-field :client
+ (com/validated-field {:label "Client"
+ :errors (fc/field-errors)}
+ (com/typeahead-2 {:name (fc/field-name)
+ :value (fc/field-value)
+ :placeholder "Search..."
+ :url (bidi/path-for ssr-routes/only-routes
+ :company-search)})))
+ (fc/with-field :days
+ (com/validated-field {:label "Days to load"
+ :errors (fc/field-errors)}
+ (com/text-input {:placeholder "60"
+ :name (fc/field-name)
+ :value (fc/field-value)} )))]
+ :else nil))
+
)
-(defn job-start-dialog [_]
- (html-response (com/modal
- {:modal-class "max-w-4xl"}
- [:form {:hx-ext "response-targets"
- :hx-post (bidi/path-for ssr-routes/only-routes :admin-job-start
- )
- :hx-swap "outerHTML swap:300ms"
- :hx-target-400 "#form-errors .error-content"}
- [:fieldset {:class "hx-disable"}
- (com/modal-card
- {}
- [:div.flex [:div.p-2 "New job"] ]
- [:div.space-y-6
+(defn subform [{{:keys [name]} :query-params }]
+ (html-response
+ (fc/start-form {} nil
+ (subform* {:name name}))))
- (com/field {:label "Job"}
- (com/select {:name "name"
- :class "w-64"
- :options [["" ""]
- ["yodlee2" "Yodlee Import"]
- ["yodlee2-accounts" "Yodlee Account Import"]
- ["intuit" "Intuit import"]
- ["plaid" "Plaid import"]
- ["bulk-journal-import" "Bulk Journal Import"]
- ["square2-import-job" "Square2 Import"]
- ["register-invoice-import" "Register Invoice Import "]
- ["ezcater-upsert" "Upsert recent ezcater orders"]
- ["load-historical-sales" "Load Historical Square Sales"]
- ["export-backup" "Export Backup"]]
- :hx-get (bidi/path-for ssr-routes/only-routes
- :admin-job-subform)
- :hx-target "#sub-form"
- :hx-swap "innerHTML"}))
+(defn job-start-dialog [{:keys [form-errors form-params] :as request}]
+ (fc/start-form (or form-params {}) form-errors
+ (modal-response
+ (com/modal ;; TODO we need a cleaner way to have forms that wrap the whole. In this cas
+ {}
+ [:form {:hx-post (bidi/path-for ssr-routes/only-routes :admin-job-start)
+ :class "h-full w-full"
+ "x-on:htmx:response-error" "unexpectedError=true"
+ "x-on:htmx:before-request" "unexpectedError=false"
+ :x-data (hx/json {:unexpectedError false})}
+ [:fieldset {:class "hx-disable h-full w-full"}
+ (com/modal-card {}
+ [:div.m-2 "New job"]
+ [:div.space-y-6
- [:div#sub-form]
- [:div#form-errors [:span.error-content]]
- (com/button {:color :primary :form "edit-form" :type "submit"}
- "Run")]
- [:div])]])))
+ (fc/with-field :name
+ (com/validated-field {:label "Job"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :value (fc/field-value)
+ :class "w-64"
+ :options [["" ""]
+ ["yodlee2" "Yodlee Import"]
+ ["yodlee2-accounts" "Yodlee Account Import"]
+ ["intuit" "Intuit import"]
+ ["plaid" "Plaid import"]
+ ["bulk-journal-import" "Bulk Journal Import"]
+ ["square2-import-job" "Square2 Import"]
+ ["register-invoice-import" "Register Invoice Import "]
+ ["ezcater-upsert" "Upsert recent ezcater orders"]
+ ["load-historical-sales" "Load Historical Square Sales"]
+ ["export-backup" "Export Backup"]]
+ :hx-get (bidi/path-for ssr-routes/only-routes
+ :admin-job-subform)
+ :hx-target "#sub-form"
+ :hx-swap "innerHTML"})))
+
+ [:div#sub-form (subform* {:name (fc/with-field :name (fc/field-value))}) ]]
+ [:div
+ [:div#5xx-error.bg-red-100.mb-2.p-1 {:x-show "unexpectedError"}
+ "An unexpected error has occured."]
+ (com/form-errors {:errors (:errors fc/*form-errors*)})
+ (com/validated-save-button {:errors form-errors} "Run job")])]]))))
+
+(def form-schema (mc/schema [:map
+ [:name [:string {:min 1}]]
+ [:ledger-url {:optional true} [:string {:min 1}]]
+ [:invoice-url {:optional true} [:string {:min 1}]]
+ [:client {:optional true} entity-id]
+ [:days {:optional true} [:int {:min 1 :max 120}]]
+ ]))
(def key->handler
(apply-middleware-to-all-handlers
(->>
- {:admin-jobs (helper/page-route grid-page)
- :admin-job-table (helper/table-route grid-page)
- :admin-job-subform (-> subform (wrap-schema-decode :query-schema [:map [:name :string]]))
- :admin-job-start (-> job-start
- (wrap-schema-decode :form-schema [:map [:name :string]])
- (wrap-nested-form-params)
- (wrap-form-4xx))
- :admin-job-start-dialog job-start-dialog})
+ {:admin-jobs (helper/page-route grid-page)
+ :admin-job-table (helper/table-route grid-page)
+ :admin-job-subform (-> subform (wrap-schema-decode :query-schema [:map [:name {:optional true} [:maybe :string]]]))
+ :admin-job-start (-> job-start
+ (wrap-schema-decode :form-schema form-schema)
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 job-start-dialog))
+ :admin-job-start-dialog job-start-dialog})
(fn [h]
(-> h
(wrap-admin)
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 3d0deb2d..87e02b7f 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -397,10 +397,9 @@
:hx-target "this"}
[:form {:hx-ext "response-targets"
- :hx-swap "outerHTML swap:300ms"
:hx-target-400 "#form-errors .error-content"
:x-trap "true"
- :class "group/form w-full h-full"
+ :class "w-full h-full"
(if (:db/id entity)
:hx-put
:hx-post) (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-edit-save))}
@@ -556,7 +555,7 @@
]]
[:div
(com/form-errors {:errors (:errors fc/*form-errors*)})
- (com/validated-save-button {:errors (:errors form-errors)} "Save rule")])])))
+ (com/validated-save-button {:errors form-errors} "Save rule")])])))
(defn new-account [{{:keys [client-id index]} :query-params}]
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index 0a5f7474..e6fc4e47 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -1,7 +1,6 @@
(ns auto-ap.ssr.components.dialog
- (:require [hiccup2.core :as hiccup]
- [auto-ap.ssr.hx :as hx]
- [auto-ap.ssr.hiccup-helper :as hh]))
+ (:require
+ [auto-ap.ssr.hiccup-helper :as hh]))
(defn modal- [params & children]
[:div (-> params
@@ -12,7 +11,8 @@
(defn modal-card- [params header content footer]
[:div#modal-card (update params
:class (fn [c] (-> c
- (or "w-full p-4 h-full")
+ (or "")
+ (hh/add-class "w-full p-4 h-full")
)))
[:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col h-full"}
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
@@ -22,4 +22,3 @@
content]
(when footer [:div {:class "p-4 shrink-0"} 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 aba64d7b..acc46704 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -84,7 +84,7 @@ c.clearChoices();
:popper nil})
:x-modelable "value.value"
:x-model (:x-model params)
- :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [0, 20]}}})"
+ :x-init "popper = Popper.createPopper($refs.input, $refs.dropdown, {placement: 'bottom-start', strategy: 'fixed', modifiers: {name: 'offset', options: {offset: [0, 10]}}})"
}
[:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes)
(hh/add-class "cursor-pointer"))
@@ -117,11 +117,11 @@ c.clearChoices();
"x-ref" "dropdown"
"@keydown.escape" "open = false; value = {value: '', label: '' }"
"x-transition:enter" "ease-[cubic-bezier(.3,2.3,.6,1)] duration-200"
- "x-transition:enter-start" "!opacity-0 !mt-0"
- "x-transition:enter-end" "!opacity-1 !mt-1"
+ "x-transition:enter-start" "!opacity-0"
+ "x-transition:enter-end" "!opacity-1"
"x-transition:leave" "ease-out duration-200"
- "x-transition:leave-start" "!opacity-1 !mt-1"
- "x-transition:leave-end" "!opacity-0 !mt-0"
+ "x-transition:leave-start" "!opacity-1"
+ "x-transition:leave-end" "!opacity-0"
"x-show " "open"
"x-trap" "open"
"@click.outside" "open=false;"}
diff --git a/src/clj/auto_ap/ssr/components/navbar.clj b/src/clj/auto_ap/ssr/components/navbar.clj
index e08d9c73..0c66b351 100644
--- a/src/clj/auto_ap/ssr/components/navbar.clj
+++ b/src/clj/auto_ap/ssr/components/navbar.clj
@@ -24,10 +24,7 @@
(when (is-admin? identity)
[:button.mt-1.lg:w-96.relative.hidden.lg:block {:class "bg-gray-50 hover:bg-gray-200 dark:hover:bg-gray-700 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 w-full pl-10 py-4 pr-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 gap-4 "
- :hx-get (bidi/path-for ssr-routes/only-routes
- :search)
- :hx-target "#modal-holder"
- :hx-swap "outerHTML"}
+ :hx-get (bidi/path-for ssr-routes/only-routes :search)}
[:div {:class "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none text-gray-500"}
[:div.w-4.h-4 svg/search]
[:span.ml-2 "Search"]]])
diff --git a/src/clj/auto_ap/ssr/components/page.clj b/src/clj/auto_ap/ssr/components/page.clj
index 7afa7c3a..dc7840ec 100644
--- a/src/clj/auto_ap/ssr/components/page.clj
+++ b/src/clj/auto_ap/ssr/components/page.clj
@@ -49,4 +49,5 @@
(into
[:div.p-4]
children)]]
+
])
diff --git a/src/clj/auto_ap/ssr/search.clj b/src/clj/auto_ap/ssr/search.clj
index 45cbee37..045e68cf 100644
--- a/src/clj/auto_ap/ssr/search.clj
+++ b/src/clj/auto_ap/ssr/search.clj
@@ -2,7 +2,7 @@
(:require
[auto-ap.graphql.utils :refer [can-see-client?]]
[auto-ap.solr :as solr]
- [auto-ap.ssr.utils :refer [html-response]]
+ [auto-ap.ssr.utils :refer [html-response modal-response]]
[auto-ap.time :as atime]
[clojure.string :as str]
[com.brunobonacci.mulog :as mu]
@@ -130,11 +130,11 @@
:form (:form-params request))
(if-let [q (get (:form-params request) "q")]
(html-response (search-results* q (:identity request)))
- (html-response
+ (modal-response
(com/modal {}
- (com/modal-card {}
+ (com/modal-card {:class "w-full h-full"}
[:div.p-2 "Search"]
- [:div#search.overflow-auto.space-y-6.p-2.h-96
+ [:div#search.overflow-auto.space-y-6.p-2.w-full
(com/text-input {:id "search-input"
:type "search"
diff --git a/src/clj/auto_ap/ssr/transaction/insights.clj b/src/clj/auto_ap/ssr/transaction/insights.clj
index 78eb6ef9..dc1920da 100644
--- a/src/clj/auto_ap/ssr/transaction/insights.clj
+++ b/src/clj/auto_ap/ssr/transaction/insights.clj
@@ -1,21 +1,21 @@
(ns auto-ap.ssr.transaction.insights
(:require
[auto-ap.client-routes :as client-routes]
- [auto-ap.datomic :refer [conn pull-attr visible-clients]]
+ [auto-ap.datomic :refer [conn visible-clients]]
[auto-ap.rule-matching :refer [spread-cents]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.svg :as svg]
[auto-ap.ssr.ui :refer [base-page]]
- [auto-ap.ssr.utils :refer [html-response]]
+ [auto-ap.ssr.utils :refer [html-response modal-response]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[cemerick.url :as url]
[clj-http.client :as http]
[clj-time.coerce :as coerce]
[datomic.api :as dc]
- [iol-ion.tx :refer [random-tempid]]
- [hiccup2.core :as hiccup]))
+ [hiccup2.core :as hiccup]
+ [iol-ion.tx :refer [random-tempid]]))
(def pull-expr [:transaction/description-original
:db/id
@@ -238,7 +238,7 @@
pull-expr
(Long/parseLong transaction-id))
similar (pinecone-similarity-list transaction-id)]
- (html-response
+ (modal-response
(com/modal {}
(com/modal-card {:style {:width "900px"}}
[:div.flex [:div.p-2 "Similar Transactions"]]
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 27685076..1e17b887 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -322,7 +322,9 @@
(defn path->name2 [k & rest]
(let [k->n (fn [k]
(if (keyword? k)
- (str (namespace k) "/" (name k))
+ (str (when (namespace k)
+ (str (namespace k) "/"))
+ (name k))
k))]
(str (k->n k)
(str/join ""
From 351864da1bf8ee3cadb8341d289a7008a15fac01 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Wed, 25 Oct 2023 15:47:27 -0700
Subject: [PATCH 30/34] transaction insights dialog.
---
resources/public/output.css | 2 +-
src/clj/auto_ap/ssr/transaction/insights.clj | 76 +++++++++++---------
2 files changed, 42 insertions(+), 36 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 60da88b9..1b73f9c7 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1 +1 @@
-/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.rotate-180,.translate-y-full{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}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x: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))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
+/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.rotate-180,.translate-y-full{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}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x: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))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
diff --git a/src/clj/auto_ap/ssr/transaction/insights.clj b/src/clj/auto_ap/ssr/transaction/insights.clj
index dc1920da..3515306f 100644
--- a/src/clj/auto_ap/ssr/transaction/insights.clj
+++ b/src/clj/auto_ap/ssr/transaction/insights.clj
@@ -55,7 +55,7 @@
[(>= ?d ?starting)]]
:args [(dc/db conn)
- (iol-ion.query/recent-date 120)
+ (iol-ion.query/recent-date 300)
(map :db/id clients)
pull-expr]})
@@ -234,43 +234,49 @@
:hide-actions? true
"_" (hiccup/raw "init transition opacity to 0 over 500ms then remove me")))))
(defn explain [{:keys [identity session] {:keys [transaction-id]} :route-params}]
- (let [r (dc/pull (dc/db conn)
+ (let [r (dc/pull (dc/db conn)
pull-expr
(Long/parseLong transaction-id))
- similar (pinecone-similarity-list transaction-id)]
+ similar (pinecone-similarity-list transaction-id)]
(modal-response
- (com/modal {}
- (com/modal-card {:style {:width "900px"}}
- [:div.flex [:div.p-2 "Similar Transactions"]]
- [:table.w-full
- [:thead
- [:tr
- [:td "Date"]
- [:td "Description"]
- [:td "Amount"]
- [:td "Vendor"]
- [:td "Account"]
- [:td "Score"]]]
- [:tbody
- [:tr
- [:th.text-left (some-> r :transaction/date coerce/to-date-time (atime/unparse-local atime/normal-date))]
- [:th.text-left (-> r :transaction/description-original)]
- [:th.text-left (if (> (-> r :transaction/amount) 0.0)
- [:div.tag.is-success.is-light (str "$" (Math/round (:transaction/amount r)))]
- [:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))])]
- [:th]
- [:th]
- [:th.text-left]]
- (take 10
- (for [{:keys [amount date description vendor-name numeric-code score]} similar]
- [:tr
- [:td (subs date 0 10)]
- [:td description]
- [:td (some->> amount double (format "$%.2f"))]
- [:td vendor-name]
- [:td numeric-code]
- [:td (format "%.1f%%" (* 100 (double score)))]]))]]
- [:div])))))
+ (com/modal {}
+ (com/modal-card {:style {:width "900px"}}
+ [:div.flex [:div.p-2 "Similar Transactions"]]
+ (com/data-grid {:headers [(com/data-grid-header {:name "Date"
+ :key "date"})
+ (com/data-grid-header {:name "Description"
+ :key "description"})
+ (com/data-grid-header {:name "Amount"
+ :key "amount"})
+ (com/data-grid-header {:name "Vendor"
+ :key "vendor"})
+ (com/data-grid-header {:name "Account"
+ :key "account"})
+ (com/data-grid-header {:name "Score"
+ :key "score"})]}
+
+ (com/data-grid-row {:class "bg-primary-200"}
+ (com/data-grid-cell {:class "text-left font-bold"} (some-> r :transaction/date coerce/to-date-time (atime/unparse-local atime/normal-date)))
+ (com/data-grid-cell {:class "text-left font-bold"} (-> r :transaction/description-original) )
+ (com/data-grid-cell {:class "font-bold"} (if (> (-> r :transaction/amount) 0.0)
+ [:div.tag.is-success.is-light (str "$" (Math/round (:transaction/amount r)))]
+ [:div.tag.is-danger.is-light (str "$" (Math/round (:transaction/amount r)))]))
+ (com/data-grid-cell {})
+ (com/data-grid-cell {})
+ (com/data-grid-cell {}))
+
+ (com/data-grid-row {}
+ (take 10
+ (for [{:keys [amount date description vendor-name numeric-code score]} similar]
+ (com/data-grid-row
+ {}
+ (com/data-grid-cell {:class "text-left"} (subs date 0 10))
+ (com/data-grid-cell {:class "text-left"} description )
+ (com/data-grid-cell {} (some->> amount double (format "$%.2f")))
+ (com/data-grid-cell {} vendor-name)
+ (com/data-grid-cell {} numeric-code)
+ (com/data-grid-cell {} (format "%.1f%%" (* 100 (double score)))))))))
+ [:div])))))
(defn transaction-rows* [{:keys [clients identity after]}]
(let [recommendations (transaction-recommendations identity clients :after after)]
From 8c3d792b28a2468fd29456f51cc8cb50c8a718b1 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Thu, 26 Oct 2023 11:04:44 -0700
Subject: [PATCH 31/34] company 1099 works
---
resources/public/output.css | 2 +-
src/clj/auto_ap/ssr/company/company_1099.clj | 330 ++++++++++++-------
src/clj/auto_ap/ssr/components/aside.clj | 174 +++-------
src/clj/auto_ap/ssr/components/navbar.clj | 3 +-
src/clj/auto_ap/ssr/components/page.clj | 20 +-
src/clj/auto_ap/ssr/core.clj | 5 +-
src/clj/auto_ap/ssr/form_cursor.clj | 9 +
src/clj/auto_ap/ssr/utils.clj | 17 +-
8 files changed, 279 insertions(+), 281 deletions(-)
diff --git a/resources/public/output.css b/resources/public/output.css
index 1b73f9c7..6bb05656 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1 +1 @@
-/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.rotate-180,.translate-y-full{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}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x: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))}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
+/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.w-72{width:18rem}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.-translate-x-0,.translate-y-full{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-x-0{--tw-translate-x:-0px}.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))}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(255 3 3/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x:0px}.lg\:-translate-x-full,.lg\:translate-x-0{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))}.lg\:-translate-x-full{--tw-translate-x:-100%}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
diff --git a/src/clj/auto_ap/ssr/company/company_1099.clj b/src/clj/auto_ap/ssr/company/company_1099.clj
index f994d169..fdbb27bb 100644
--- a/src/clj/auto_ap/ssr/company/company_1099.clj
+++ b/src/clj/auto_ap/ssr/company/company_1099.clj
@@ -1,17 +1,32 @@
(ns auto-ap.ssr.company.company-1099
(:require
- [auto-ap.datomic :refer [apply-pagination-raw conn remove-nils]]
- [auto-ap.graphql.utils
- :refer [assert-can-see-client extract-client-ids is-admin?]]
+ [auto-ap.datomic :refer [apply-pagination-raw conn]]
+ [auto-ap.graphql.utils :refer [assert-can-see-client]]
+ [auto-ap.routes.utils
+ :refer [wrap-client-redirect-unauthenticated wrap-secure]]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
+ [auto-ap.ssr.form-cursor :as fc]
[auto-ap.ssr.grid-page-helper :as helper]
+ [auto-ap.ssr.nested-form-params :refer [wrap-nested-form-params]]
[auto-ap.ssr.svg :as svg]
- [auto-ap.ssr.utils :refer [form-data->map html-response path->name]]
+ [auto-ap.ssr.utils
+ :refer [apply-middleware-to-all-handlers
+ entity-id
+ html-response
+ main-transformer
+ modal-response
+ ref->enum-schema
+ ref->select-options
+ strip
+ wrap-entity
+ wrap-form-4xx-2
+ wrap-schema-decode]]
[bidi.bidi :as bidi]
- [cemerick.url :as url]
[clojure.string :as str]
- [datomic.api :as dc]))
+ [datomic.api :as dc]
+ [hiccup.util :refer [url]]
+ [malli.core :as mc]))
(def vendor-read '[:db/id
:vendor/name
@@ -74,7 +89,7 @@
(def grid-page
(helper/build
- {:id "vendor-table"
+ {:id "entity-table"
:nav (com/company-aside-nav)
:id-fn (comp :db/id second)
:fetch-page fetch-page
@@ -89,14 +104,10 @@
:entity-name "Vendors"
:route :company-1099-vendor-table
:row-buttons (fn [request e]
- [(com/icon-button {:hx-get (str (bidi/path-for ssr-routes/only-routes
+ [(com/icon-button {:hx-get (url (bidi/path-for ssr-routes/only-routes
:company-1099-vendor-dialog
:vendor-id (:db/id (second e)))
- "?"
- (url/map->query {:client-id (:db/id (first e))}))
- :hx-ext "debug"
- :hx-target "#modal-holder"
- :hx-swap "outerHTML"}
+ {:client-id (:db/id (first e))})}
svg/pencil)])
:headers [{:key "Client"
:name "Client"
@@ -161,117 +172,200 @@
(def table* (partial helper/table* grid-page))
(def row* (partial helper/row* grid-page))
-(defn vendor-save [{:keys [form-params identity route-params query-params] :as request}]
- (let [client-id (Long/parseLong (get query-params "client-id"))
- vendor-id (Long/parseLong (:vendor-id route-params))]
- (assert-can-see-client identity client-id)
- @(dc/transact conn [(remove-nils
- (-> (form-data->map form-params)
- (assoc :db/id (Long/parseLong (:vendor-id route-params)))
- (update :vendor/legal-entity-1099-type #(some->> % not-empty (keyword "legal-entity-1099-type")))
- (update :vendor/legal-entity-tin-type #(some->> % not-empty (keyword "legal-entity-tin-type")))))])
- (html-response
+(defn vendor-save [{:keys [form-params identity route-params query-params request-method] :as request
+ {:keys [vendor-id]} :route-params
+ {:keys [client-id]} :query-params}]
- (row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
- (dc/pull (dc/db conn) vendor-read vendor-id)
- (sum-for-client-vendor client-id vendor-id)
- ] {:flash? true})
- :headers {"hx-trigger" "closeModal"})))
+ (assert-can-see-client identity client-id)
+ @(dc/transact conn [[:upsert-entity (assoc form-params :db/id (:vendor-id route-params))]])
+ (html-response
-(defn vendor-dialog [request]
- (let [vendor (dc/pull (dc/db conn) '[* {:vendor/legal-entity-1099-type [:db/ident]
- :vendor/legal-entity-tin-type [:db/ident]}] (Long/parseLong (:vendor-id (:params request))))] ;; TODO perms
- (html-response
+ (row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
+ (dc/pull (dc/db conn) vendor-read vendor-id)
+ (sum-for-client-vendor client-id vendor-id)
+ ] {:flash? true})
+ :headers {"hx-trigger" "modalclose"
+ "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" vendor-id)}))
+
+(def default-vendor-read '[* {[:vendor/legal-entity-1099-type :xform iol-ion.query/ident] [:db/ident]
+ [:vendor/legal-entity-tin-type :xform iol-ion.query/ident] [:db/ident]}])
+
+
+(def form-schema (mc/schema [:map
+ [:vendor/address {:default {} }
+ [:maybe
+ [:map
+ [:db/id {:optional true} [:maybe entity-id]]
+ [:address/street1 {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:address/street2 {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:address/city {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:address/state {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:address/zip {:optional true} [:maybe [:re { :error/message "invalid zip"
+ :decode/string strip} #"^(\d{5}|)$"]]]]]]
+ [:vendor/legal-entity-name {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:vendor/legal-entity-first-name {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:vendor/legal-entity-middle-name {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:vendor/legal-entity-last-name {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:vendor/legal-entity-tin {:optional true} [:maybe [:string {:decode/string strip}]]]
+ [:vendor/legal-entity-tin-type {:optional true} [:maybe (ref->enum-schema "legal-entity-tin-type")]]
+ [:vendor/legal-entity-1099-type {:optional true} [:maybe (ref->enum-schema "legal-entity-1099-type")]]]))
+
+(defn vendor-dialog [{{:keys [client-id]} :query-params {:keys [vendor-id]} :route-params :keys [entity form-params form-errors]}]
+ (fc/start-form (or (when (seq form-params)
+ form-params)
+ (when entity
+ (mc/decode form-schema entity main-transformer))
+ {})
+ form-errors
+ (modal-response
(com/modal
{}
- [:form {:hx-post (str (bidi/path-for ssr-routes/only-routes
- :company-1099-vendor-save
- :request-method :post
- :vendor-id (Long/parseLong (:vendor-id (:params request))))
- "?"
- (url/map->query {:client-id (:client-id (:params request))}))
- :hx-target (format "#vendor-table tr[data-id=\"%d\"]" (:db/id vendor))
- :hx-swap "outerHTML swap:300ms"}
- [:fieldset {:class "hx-disable"}
+ [:form {:hx-post (url (bidi/path-for ssr-routes/only-routes
+ :company-1099-vendor-save
+ :request-method :post
+ :vendor-id vendor-id)
+ {:client-id client-id})
+ :class "w-full h-full max-w-2xl"
+ :hx-swap "outerHTML swap:300ms"}
+
+ [:fieldset {:class "hx-disable w-full h-full"}
(com/modal-card
{}
- [:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name vendor)]]
- [:div.space-y-6
- [:div.grid.grid-cols-6.gap-4
-
- [:h4.text-xl.border-b.col-span-6 "Address"]
- [:div.col-span-6
- (com/field {:label "Street 1"}
- (com/text-input {:name (path->name [:vendor/address :address/street1])
- :value (-> vendor :vendor/address :address/street1)
- :placeholder "1700 Pennsylvania Ave"
- :autofocus true}))]
- [:div.col-span-6
- (com/field {:label "Street 2"}
- (com/text-input {:name (path->name [:vendor/address :address/street2])
- :value (-> vendor :vendor/address :address/street2)
- :placeholder "Suite 200"}))]
- [:div.col-span-3
- (com/field {:label "City"}
- (com/text-input {:name (path->name [:vendor/address :address/city])
- :value (-> vendor :vendor/address :address/city)
- :placeholder "Cupertino"}))]
- [:div.col-span-1
- (com/field {:label "State"}
- (com/text-input {:name (path->name [:vendor/address :address/state])
- :value (-> vendor :vendor/address :address/state)
- :placeholder "CA"}))]
- [:div.col-span-2
- (com/field {:label "Zip"}
- (com/text-input {:name (path->name [:vendor/address :address/zip])
- :value (-> vendor :vendor/address :address/zip)
- :placeholder "98102"}))]
- [:h4.text-xl.border-b.col-span-6 "Legal Entity"]
- [:div.col-span-6
- (com/field {:label "Legal Entity Name"}
- (com/text-input {:name (path->name [:vendor/legal-entity-name])
- :value (-> vendor :vendor/legal-entity-name)
- :placeholder "Good Restaurant LLC"}))]
- [:div.col-span-6.text-center " - OR -"]
- [:div.col-span-2
- (com/field {:label "First Name"}
- (com/text-input {:name (path->name [:vendor/legal-entity-first-name])
- :value (-> vendor :vendor/legal-entity-first-name)
- :placeholder "John"}))]
- [:div.col-span-2
- (com/field {:label "Middle Name"}
- (com/text-input {:name (path->name [:vendor/legal-entity-middle-name])
- :value (-> vendor :vendor/legal-entity-middle-name)
- :placeholder "C."}))]
- [:div.col-span-2
- (com/field {:label "Last Name"}
- (com/text-input {:name (path->name [:vendor/legal-entity-last-name])
- :value (-> vendor :vendor/legal-entity-last-name)
- :placeholder "Riley"}))]
- [:div.col-span-2
- (com/field {:label "TIN"}
- (com/text-input {:name (path->name [:vendor/legal-entity-tin])
- :value (-> vendor :vendor/legal-entity-tin)
- :placeholder "John"}))]
- [:div.col-span-2
- (com/field {:label "TIN Type"}
- (com/select {:name (path->name [:vendor/legal-entity-tin-type])
- :allow-blank? true
- :value (some-> vendor :vendor/legal-entity-tin-type :db/ident name)
- :options [["ein" "EIN"]
- ["ssn" "SSN"]]}))]
- [:div.col-span-2
- (com/field {:label "1099 Type"}
- (com/select {:name (path->name [:vendor/legal-entity-1099-type])
- :allow-blank? true
- :value (some-> vendor :vendor/legal-entity-1099-type :db/ident name)
- :options [["none" "None"]
- ["misc" "Misc"]
- ["landlord" "Landlord"]]}))]
- [:div.col-span-6
- (com/button {:color :primary}
- "Save")]]]
- [:div])]]))))
+ [:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name entity)]]
+ [:div.grid.grid-cols-6.gap-x-4.gap-y-2
+
+ (fc/with-field :vendor/address ;; TODO support default
+ (list [:h4.text-xl.border-b.col-span-6 "Address"]
+ [:div.col-span-6
+ (fc/with-field :db/id
+ (com/hidden {:name (fc/field-name)
+ :value (fc/field-value)}))
+
+ (fc/with-field :address/street1
+ (com/validated-field {:label "Street 1"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "1700 Pennsylvania Ave"
+ :autofocus true})))]
+ [:div.col-span-6
+ (fc/with-field :address/street2
+ (com/validated-field {:label "Street 2"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "Suite 200"})))]
+ [:div.col-span-3
+ (fc/with-field :address/city
+ (com/validated-field {:label "City"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "Cupertino"})))]
+ [:div.col-span-1
+ (fc/with-field :address/state
+ (com/validated-field {:label "State"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "CA"})))]
+ [:div.col-span-2
+ (fc/with-field :address/zip
+ (com/validated-field {:label "Zip"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "98102"})))]))
+
+ [:h4.text-xl.border-b.col-span-6 "Legal Entity"]
+ [:div.col-span-6
+ (fc/with-field :vendor/legal-entity-name
+ (com/validated-field {:label "Legal Entity Name"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :class "w-full"
+ :value (fc/field-value)
+ :placeholder "Good Restaurant LLC"})))]
+ [:div.col-span-6.text-center " - OR -"]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-first-name
+ (com/validated-field {:label "First Name"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :value (fc/field-value)
+ :placeholder "John"})))]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-middle-name
+ (com/validated-field {:label "Middle Name"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :value (fc/field-value)
+ :placeholder "C."})))]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-last-name
+ (com/validated-field {:label "Last Name"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :value (fc/field-value)
+ :placeholder "Riley"})))]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-tin
+ (com/validated-field {:label "TIN"
+ :errors (fc/field-errors)}
+ (com/text-input {:name (fc/field-name)
+ :value (fc/field-value)
+ :placeholder "John"})))]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-tin-type
+ (com/validated-field {:label "TIN Type"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :allow-blank? true
+ :value (some-> (fc/field-value) name)
+ :options [["ein" "EIN"]
+ ["ssn" "SSN"]]})))]
+ [:div.col-span-2
+ (fc/with-field :vendor/legal-entity-1099-type
+ (com/validated-field {:label "1099 Type"
+ :errors (fc/field-errors)}
+ (com/select {:name (fc/field-name)
+ :allow-blank? true
+ :value (some-> (fc/field-value) name) ;; TODO use ref stuff
+ :options (ref->select-options "legal-entity-1099-type")})))]]
+ [:div
+ (com/form-errors {:errors (:errors fc/*form-errors*)})
+ (com/validated-save-button {:errors form-errors} "Save rule")])]]))))
(def vendor-table (helper/table-route grid-page))
(def page (helper/page-route grid-page))
+
+(def key->handler
+ (apply-middleware-to-all-handlers
+ (->>
+ {
+ :company-1099 page
+ :company-1099-vendor-table vendor-table
+ :company-1099-vendor-dialog (-> vendor-dialog
+ (wrap-entity [:route-params :vendor-id] default-vendor-read)
+ (wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
+ :query-schema [:map [:client-id entity-id]]))
+ :company-1099-vendor-save (-> vendor-save
+ (wrap-entity [:form-params :db/id] default-vendor-read)
+ (wrap-schema-decode :form-schema form-schema
+ :route-schema [:map [:vendor-id entity-id]]
+ :query-schema [:map [:client-id entity-id]])
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 (-> vendor-dialog
+ (wrap-entity [:form-params :db/id] default-vendor-read)
+ (wrap-entity [:route-params :vendor-id] default-vendor-read)
+ (wrap-schema-decode :route-schema [:map [:vendor-id entity-id]]
+ :query-schema [:map [:client-id entity-id]]))))})
+ (fn [h]
+ (-> h
+ (wrap-secure)
+ (wrap-client-redirect-unauthenticated)))))
diff --git a/src/clj/auto_ap/ssr/components/aside.clj b/src/clj/auto_ap/ssr/components/aside.clj
index 4410027e..7cad9ff8 100644
--- a/src/clj/auto_ap/ssr/components/aside.clj
+++ b/src/clj/auto_ap/ssr/components/aside.clj
@@ -3,7 +3,9 @@
[hiccup2.core :as hiccup]
[bidi.bidi :as bidi]
[auto-ap.ssr-routes :as ssr-routes]
- [auto-ap.client-routes :as client-routes]))
+ [auto-ap.client-routes :as client-routes]
+ [auto-ap.ssr.hx :as hx]
+ [auto-ap.ssr.hiccup-helper :as hh]))
(defn menu-button- [params & children]
[:div
@@ -13,140 +15,47 @@
(update :class str " cursor-pointer flex items-center p-2 w-full text-xs text-gray-600 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")
(assoc :hx-indicator "find .htmx-indicator")
(assoc :hx-boost "true")
- (assoc :hx-select "#app-contents")
- (assoc :hx-target "#app-contents")
- (assoc :hx-swap "outerHTML"))
+ (assoc :hx-select "#app")
+ (assoc :hx-target "#app")
+ (assoc :hx-swap "innerHTML"))
(when (:icon params)
[:span {:class "flex-shrink-0 w-6 h-6 text-gray-400 transition duration-75 group-hover:text-blue-500 dark:text-gray-400 group-hover:scale-110 dark:group-hover:text-white mr-3"}
(:icon params)])
(into [:span {:class "flex-1 text-left whitespace-nowrap text-gray-600 dark:text-white"}] children)
- (when (:data-collapse-toggle params)
+ (when (get params "@click")
[:svg {:aria-hidden "true", :class "w-6 h-6", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
[:path {:fill-rule "evenodd", :d "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", :clip-rule "evenodd"}]])
[:div.htmx-indicator.flex.items-center
(svg/spinner-primary {:class "inline w-4 h-4 text-white"})]]])
(defn sub-menu- [params & children]
- [:ul {:id (:id params) :class "hidden py-2 space-y-1.5"}
+ [:ul (update params
+ :class (fnil hh/add-class "")"py-2 space-y-1.5")
(for [c children]
[:li
(update-in c [1 1 :class ] str " flex items-center p-2 pl-11 w-full text-base font-normal text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700")])])
(defn left-aside- [{:keys [nav page-specific]} & children]
- [:aside {:id "left-nav", :class "fixed top-0 left-0 pt-16 z-20 w-64 h-screen transition-transform -translate-x-full lg:translate-x-0", :aria-labelledby "left-nav" :aria-hidden "true"
- "_" (hiccup/raw "init call initSidebarToggle()")}
+ [:aside {:id "left-nav",
+ :class "fixed top-0 left-0 pt-16 z-20 w-64 h-screen transition-transform -translate-x-full lg:translate-x-0",
+ "x-transition:enter" "transition duration-500"
+ "x-transition:enter-start" "lg:-translate-x-full"
+ "x-transition:enter-end" " lg:translate-x-0"
+ "x-transition:leave" "transition duration-500"
+ "x-transition:leave-start" "lg:translate-x-0"
+ "x-transition:leave-end" " lg:-translate-x-full"
+
+ :aria-labelledby "left-nav"
+ :x-show "leftNavShow"
+ ":aria-hidden" "leftNavShow ? 'false' : 'true'"}
[:div {:class "overflow-y-auto py-5 px-3 h-full bg-gray-50 border-r border-gray-200 dark:bg-gray-800 dark:border-gray-700"}
nav
- [:ul {:class "pt-5 mt-5 space-y-2 border-t border-gray-200 dark:border-gray-700"}
- #_[:li
- [:a {:href "#", :class "flex items-center p-2 text-base font-normal text-gray-900 rounded-lg transition duration-75 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white group"}
- [:svg {:aria-hidden "true", :class "flex-shrink-0 w-6 h-6 text-gray-400 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
- [:path {:d "M9 2a1 1 0 000 2h2a1 1 0 100-2H9z"}]
- [:path {:fill-rule "evenodd", :d "M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z", :clip-rule "evenodd"}]]
- [:span {:class "ml-3"} "Docs"]]]
- #_[:li
- [:a {:href "#", :class "flex items-center p-2 text-base font-normal text-gray-900 rounded-lg transition duration-75 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white group"}
- [:svg {:aria-hidden "true", :class "flex-shrink-0 w-6 h-6 text-gray-400 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
- [:path {:d "M7 3a1 1 0 000 2h6a1 1 0 100-2H7zM4 7a1 1 0 011-1h10a1 1 0 110 2H5a1 1 0 01-1-1zM2 11a2 2 0 012-2h12a2 2 0 012 2v4a2 2 0 01-2 2H4a2 2 0 01-2-2v-4z"}]]
- [:span {:class "ml-3"} "Components"]]]
- #_[:li
- [:a {:href "#", :class "flex items-center p-2 text-base font-normal text-gray-900 rounded-lg transition duration-75 hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white group"}
- [:svg {:aria-hidden "true", :class "flex-shrink-0 w-6 h-6 text-gray-400 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
- [:path {:fill-rule "evenodd", :d "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-2 0c0 .993-.241 1.929-.668 2.754l-1.524-1.525a3.997 3.997 0 00.078-2.183l1.562-1.562C15.802 8.249 16 9.1 16 10zm-5.165 3.913l1.58 1.58A5.98 5.98 0 0110 16a5.976 5.976 0 01-2.516-.552l1.562-1.562a4.006 4.006 0 001.789.027zm-4.677-2.796a4.002 4.002 0 01-.041-2.08l-.08.08-1.53-1.533A5.98 5.98 0 004 10c0 .954.223 1.856.619 2.657l1.54-1.54zm1.088-6.45A5.974 5.974 0 0110 4c.954 0 1.856.223 2.657.619l-1.54 1.54a4.002 4.002 0 00-2.346.033L7.246 4.668zM12 10a2 2 0 11-4 0 2 2 0 014 0z", :clip-rule "evenodd"}]]
- [:span {:class "ml-3"} "Help"]]]]
- page-specific]
- #_[:div {:class "hidden absolute bottom-0 left-0 justify-center p-4 space-x-4 w-full lg:flex bg-white dark:bg-gray-800 z-20 border-r border-gray-200 dark:border-gray-700"}
- [:a {:href "#", :class "inline-flex justify-center p-2 text-gray-500 rounded cursor-pointer dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-600"}
- [:svg {:aria-hidden "true", :class "w-6 h-6", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
- [:path {:d "M5 4a1 1 0 00-2 0v7.268a2 2 0 000 3.464V16a1 1 0 102 0v-1.268a2 2 0 000-3.464V4zM11 4a1 1 0 10-2 0v1.268a2 2 0 000 3.464V16a1 1 0 102 0V8.732a2 2 0 000-3.464V4zM16 3a1 1 0 011 1v7.268a2 2 0 010 3.464V16a1 1 0 11-2 0v-1.268a2 2 0 010-3.464V4a1 1 0 011-1z"}]]]
- [:a {:href "#", :data-tooltip-target "tooltip-settings", :class "inline-flex justify-center p-2 text-gray-500 rounded cursor-pointer dark:text-gray-400 dark:hover:text-white hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600"}
- [:svg {:aria-hidden "true", :class "w-6 h-6", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
- [:path {:fill-rule "evenodd", :d "M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z", :clip-rule "evenodd"}]]]
- [:div {:id "tooltip-settings", :role "tooltip", :class "inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip"} "Settings page"]
- [:button {:type "button", :data-dropdown-toggle "language-dropdown", :class "inline-flex justify-center p-2 text-gray-500 rounded cursor-pointer dark:hover:text-white dark:text-gray-400 hover:text-gray-900 hover:bg-gray-100 dark:hover:bg-gray-600"}
- [:svg {:aria-hidden "true", :class "h-5 w-5 rounded-full mt-0.5", :xmlns "http://www.w3.org/2000/svg", :xmlns:xlink "http://www.w3.org/1999/xlink", :viewbox "0 0 3900 3900"}
- [:path {:fill "#b22234", :d "M0 0h7410v3900H0z"}]
- [:path {:d "M0 450h7410m0 600H0m0 600h7410m0 600H0m0 600h7410m0 600H0", :stroke "#fff", :stroke-width "300"}]
- [:path {:fill "#3c3b6e", :d "M0 0h2964v2100H0z"}]
- [:g {:fill "#fff"}
- [:g {:id "d"}
- [:g {:id "c"}
- [:g {:id "e"}
- [:g {:id "b"}
- [:path {:id "a", :d "M247 90l70.534 217.082-184.66-134.164h228.253L176.466 307.082z"}]
- [:use {:xlink:href "#a", :y "420"}]
- [:use {:xlink:href "#a", :y "840"}]
- [:use {:xlink:href "#a", :y "1260"}]]
- [:use {:xlink:href "#a", :y "1680"}]]
- [:use {:xlink:href "#b", :x "247", :y "210"}]]
- [:use {:xlink:href "#c", :x "494"}]]
- [:use {:xlink:href "#d", :x "988"}]
- [:use {:xlink:href "#c", :x "1976"}]
- [:use {:xlink:href "#e", :x "2470"}]]]]
- [:div {:class "hidden z-50 my-4 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700", :id "language-dropdown"}
- [:ul {:class "py-1", :role "none"}
- [:li
- [:a {:href "#", :class "block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600", :role "menuitem"}
- [:div {:class "inline-flex items-center"}
- [:svg {:aria-hidden "true", :class "h-3.5 w-3.5 rounded-full mr-2", :xmlns "http://www.w3.org/2000/svg", :id "flag-icon-css-us", :viewbox "0 0 512 512"}
- [:g {:fill-rule "evenodd"}
- [:g {:stroke-width "1pt"}
- [:path {:fill "#bd3d44", :d "M0 0h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0z", :transform "scale(3.9385)"}]
- [:path {:fill "#fff", :d "M0 10h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0zm0 20h247v10H0z", :transform "scale(3.9385)"}]]
- [:path {:fill "#192f5d", :d "M0 0h98.8v70H0z", :transform "scale(3.9385)"}]
- [:path {:fill "#fff", :d "M8.2 3l1 2.8H12L9.7 7.5l.9 2.7-2.4-1.7L6 10.2l.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8H45l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7L74 8.5l-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9L92 7.5l1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm-74.1 7l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7H65zm16.4 0l1 2.8H86l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm-74 7l.8 2.8h3l-2.4 1.7.9 2.7-2.4-1.7L6 24.2l.9-2.7-2.4-1.7h3zm16.4 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8H45l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9L92 21.5l1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm-74.1 7l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7H65zm16.4 0l1 2.8H86l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm-74 7l.8 2.8h3l-2.4 1.7.9 2.7-2.4-1.7L6 38.2l.9-2.7-2.4-1.7h3zm16.4 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8H45l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9L92 35.5l1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm-74.1 7l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7H65zm16.4 0l1 2.8H86l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm-74 7l.8 2.8h3l-2.4 1.7.9 2.7-2.4-1.7L6 52.2l.9-2.7-2.4-1.7h3zm16.4 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8H45l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9L92 49.5l1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm-74.1 7l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7H65zm16.4 0l1 2.8H86l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm-74 7l.8 2.8h3l-2.4 1.7.9 2.7-2.4-1.7L6 66.2l.9-2.7-2.4-1.7h3zm16.4 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8H45l-2.4 1.7 1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9zm16.4 0l1 2.8h2.8l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h3zm16.5 0l.9 2.8h2.9l-2.3 1.7.9 2.7-2.4-1.7-2.3 1.7.9-2.7-2.4-1.7h2.9zm16.5 0l.9 2.8h2.9L92 63.5l1 2.7-2.4-1.7-2.4 1.7 1-2.7-2.4-1.7h2.9z", :transform "scale(3.9385)"}]]] " \n English (US)"]]]
- [:li
- [:a {:href "#", :class "block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:text-white dark:hover:bg-gray-600", :role "menuitem"}
- [:div {:class "inline-flex items-center"}
- [:svg {:aria-hidden "true", :class "h-3.5 w-3.5 rounded-full mr-2", :xmlns "http://www.w3.org/2000/svg", :id "flag-icon-css-de", :viewbox "0 0 512 512"}
- [:path {:fill "#ffce00", :d "M0 341.3h512V512H0z"}]
- [:path {:d "M0 0h512v170.7H0z"}]
- [:path {:fill "#d00", :d "M0 170.7h512v170.6H0z"}]]]]]
- [:li
- [:a {:href "#", :class "block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:text-white dark:hover:bg-gray-600", :role "menuitem"}
- [:div {:class "inline-flex items-center"}
- [:svg {:aria-hidden "true", :class "h-3.5 w-3.5 rounded-full mr-2", :xmlns "http://www.w3.org/2000/svg", :id "flag-icon-css-it", :viewbox "0 0 512 512"}
- [:g {:fill-rule "evenodd", :stroke-width "1pt"}
- [:path {:fill "#fff", :d "M0 0h512v512H0z"}]
- [:path {:fill "#009246", :d "M0 0h170.7v512H0z"}]
- [:path {:fill "#ce2b37", :d "M341.3 0H512v512H341.3z"}]]]]]]
- [:li
- [:a {:href "#", :class "block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:text-white dark:text-gray-300 dark:hover:bg-gray-600", :role "menuitem"}
- [:div {:class "inline-flex items-center"}
- [:svg {:aria-hidden "true", :class "h-3.5 w-3.5 rounded-full mr-2", :xmlns "http://www.w3.org/2000/svg", :xmlns:xlink "http://www.w3.org/1999/xlink", :id "flag-icon-css-cn", :viewbox "0 0 512 512"}
- [:defs
- [:path {:id "a", :fill "#ffde00", :d "M1-.3L-.7.8 0-1 .6.8-1-.3z"}]]
- [:path {:fill "#de2910", :d "M0 0h512v512H0z"}]
- [:use {:width "30", :height "20", :transform "matrix(76.8 0 0 76.8 128 128)", :xlink:href "#a"}]
- [:use {:width "30", :height "20", :transform "rotate(-121 142.6 -47) scale(25.5827)", :xlink:href "#a"}]
- [:use {:width "30", :height "20", :transform "rotate(-98.1 198 -82) scale(25.6)", :xlink:href "#a"}]
- [:use {:width "30", :height "20", :transform "rotate(-74 272.4 -114) scale(25.6137)", :xlink:href "#a"}]
- [:use {:width "30", :height "20", :transform "matrix(16 -19.968 19.968 16 256 230.4)", :xlink:href "#a"}]] "中文 (繁體)"]]]]]]
- [:script {:lang "text/javascript"}
- (hiccup/raw "
- function initSidebarToggle() {
- var $targetEl = document.getElementById('left-nav');
-
- var $triggerEl = document.getElementById('left-nav-toggle');
-
- var options = {
- onCollapse: () => {
- document.getElementById('main-content').classList.remove('lg:pl-64')
- },
- onExpand: () => {
- document.getElementById('main-content').classList.add('lg:pl-64')
- },
- onToggle: () => {
- }
- };
-
- var collapse = new Collapse($targetEl, $triggerEl, options);
- }
-")]])
+
+ page-specific]])
(defn main-aside-nav- []
[:ul {:class "space-y-1"}
@@ -155,12 +64,11 @@
(menu-button- {:icon svg/pie
:href "/"}
"Dashboard")]
- [:li
- (menu-button- {:aria-controls "dropdown-invoices",
- :data-collapse-toggle "dropdown-invoices"
+ [:li {:x-data (hx/json {:open false})}
+ (menu-button- {"@click" "open = !open"
:icon svg/accounting-invoice-mail}
"Invoices")
- (sub-menu- {:id "dropdown-invoices"}
+ (sub-menu- {:x-show "open"}
(menu-button- {:href (bidi/path-for client-routes/routes
:invoices)}
"All")
@@ -173,12 +81,11 @@
(menu-button- {:href (bidi/path-for client-routes/routes
:voided-invoices)}
"Voided"))]
- [:li
- (menu-button- {:aria-controls "dropdown-sales",
- :data-collapse-toggle "dropdown-sales"
- :icon svg/receipt-register-1}
+ [:li {:x-data (hx/json {:open false})}
+ (menu-button- {:icon svg/receipt-register-1
+ "@click" "open = !open"}
"Sales")
- (sub-menu- {:id "dropdown-sales"}
+ (sub-menu- {:x-show "open"}
(menu-button- {:href (str (bidi/path-for ssr-routes/only-routes
:pos-sales)
"?date-range=week")} "Sales")
@@ -197,12 +104,11 @@
"?date-range=week")} "Cash drawer shifts")
#_(menu-button- {:href "Sales"} "Cash Shifts")
#_(menu-button- {:href "Sales"} "Tenders"))]
- [:li
- (menu-button- {:aria-controls "dropdown-payments"
- :data-collapse-toggle "dropdown-payments"
+ [:li {:x-data (hx/json {:open false})}
+ (menu-button- {"@click" "open = !open"
:icon svg/payments}
"Payments")
- (sub-menu- {:id "dropdown-payments"}
+ (sub-menu- {:x-show "open"}
(menu-button- {:href (bidi/path-for client-routes/routes
:payments)} "All")
(menu-button- {:href (bidi/path-for client-routes/routes
@@ -212,13 +118,12 @@
(menu-button- {:href (bidi/path-for client-routes/routes
:payments)} "Voided"))]
- [:li
- (menu-button- {:aria-controls "dropdown-transactions"
- :data-collapse-toggle "dropdown-transactions"
+ [:li {:x-data (hx/json {:open false})}
+ (menu-button- {"@click" "open = !open"
:icon svg/bank}
"Transactions")
- (sub-menu- {:id "dropdown-transactions"}
+ (sub-menu- {:x-show "open"}
(menu-button- {:href (bidi/path-for client-routes/routes
:transactions)} "All")
(menu-button- {:href (bidi/path-for client-routes/routes
@@ -229,12 +134,11 @@
:approved-transactions)} "Approved")
(menu-button- {:href (bidi/path-for ssr-routes/only-routes
:transaction-insights)} "Insights"))]
- [:li
- (menu-button- {:aria-controls "dropdown-ledger"
- :data-collapse-toggle "dropdown-ledger"
+ [:li {:x-data (hx/json {:open false})}
+ (menu-button- {"@click" "open = !open"
:icon svg/receipt}
"Ledger")
- (sub-menu- {:id "dropdown-ledger"}
+ (sub-menu- {:x-show "open"}
(menu-button- {:href (bidi/path-for client-routes/routes
:ledger)} "Register")
(menu-button- {:href (bidi/path-for client-routes/routes
diff --git a/src/clj/auto_ap/ssr/components/navbar.clj b/src/clj/auto_ap/ssr/components/navbar.clj
index 0c66b351..3759e741 100644
--- a/src/clj/auto_ap/ssr/components/navbar.clj
+++ b/src/clj/auto_ap/ssr/components/navbar.clj
@@ -13,7 +13,8 @@
[:div {:class "px-3 py-3 lg:px-5 lg:pl-3"}
[:div {:class "flex items-center justify-between"}
[:div {:class "flex items-center justify-start"}
- [:button {:aria-controls "left-nav", :id "left-nav-toggle" :type "button", :class "inline-flex items-center p-2 mt-2 ml-2 mr-2 text-sm text-gray-500 rounded-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"}
+ [:button {:aria-controls "left-nav", :id "left-nav-toggle" :type "button", :class "inline-flex items-center p-2 mt-2 ml-2 mr-2 text-sm text-gray-500 rounded-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
+ "@click" "leftNavShow = !leftNavShow"}
[:span {:class "sr-only"} "Open sidebar"]
[:svg {:class "w-6 h-6", :aria-hidden "true", :fill "currentColor", :viewbox "0 0 20 20", :xmlns "http://www.w3.org/2000/svg"}
[:path {:clip-rule "evenodd", :fill-rule "evenodd", :d "M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"}]]]
diff --git a/src/clj/auto_ap/ssr/components/page.clj b/src/clj/auto_ap/ssr/components/page.clj
index dc7840ec..0fbcdaef 100644
--- a/src/clj/auto_ap/ssr/components/page.clj
+++ b/src/clj/auto_ap/ssr/components/page.clj
@@ -3,20 +3,26 @@
[auto-ap.ssr.components.aside :refer [left-aside-]]
[auto-ap.ssr.components.navbar :refer [navbar-]]
[hiccup2.core :as hiccup]
- [auto-ap.ssr.svg :as svg]))
+ [auto-ap.ssr.svg :as svg]
+ [auto-ap.ssr.hx :as hx]))
(defn page- [{:keys [nav page-specific client client-selection identity app-params] :or {app-params {}}} & children]
[:div#app {"_" (hiccup/raw "
on notification put event.detail.value into #notification-details then add .htmx-added to #notification-holder then remove .hidden from #notification-holder then wait 30ms then remove .htmx-added from #notification-holder
on htmx:responseError put event.detail.xhr.response into #error-details then add .htmx-added to #error-holder then remove .hidden from #error-holder then wait 30ms then remove .htmx-added from #error-holder"
- )}
+ )
+ :x-data (hx/json {:leftNavShow true})}
(navbar- {:client-selection client-selection
- :client client
- :identity identity})
- [:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params :hx-disinherit "*")
- (left-aside- {:nav nav
+ :client client
+ :identity identity})
+ [:div#app-contents.flex.pt-16.overflow-hidden (assoc app-params
+ :hx-disinherit "*"
+ :x-init "leftNavShow = true")
+ (left-aside- {:nav nav
:page-specific page-specific})
- [:div#main-content {:class "relative w-full h-full lg:pl-64 overflow-y-auto px-4 bg-gray-100 dark:bg-gray-900 min-h-content "
+ [:div#main-content {:class "relative w-full h-full overflow-y-auto px-4 bg-gray-100 dark:bg-gray-900 min-h-content lg:pl-64"
+ ":class" "leftNavShow ? 'lg:pl-64' : ''"
+ :x-effect "leftNavShow ? $el.classList.add('lg:pl-64') : $el.classList.remove('lg:pl-64')"
}
[:div#notification-holder.hidden
[:div.fixed.top-0.right-0.left-0.z-30.mx-auto.max-w-screen-lg.w-screen-lg.my-0.pt-8.rounded-lg
diff --git a/src/clj/auto_ap/ssr/core.clj b/src/clj/auto_ap/ssr/core.clj
index 0935bbd0..d4eeaa9c 100644
--- a/src/clj/auto_ap/ssr/core.clj
+++ b/src/clj/auto_ap/ssr/core.clj
@@ -46,10 +46,6 @@
:bank-account-typeahead (wrap-client-redirect-unauthenticated (wrap-secure company/bank-account-typeahead))
:company (wrap-client-redirect-unauthenticated (wrap-secure company/page))
- :company-1099 (wrap-client-redirect-unauthenticated (wrap-secure company-1099/page))
- :company-1099-vendor-table (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-table))
- :company-1099-vendor-dialog (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-dialog))
- :company-1099-vendor-save (wrap-client-redirect-unauthenticated (wrap-secure company-1099/vendor-save))
:company-plaid (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/page))
:company-plaid-table (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/table))
:company-plaid-link (wrap-client-redirect-unauthenticated (wrap-secure company-plaid/link))
@@ -76,6 +72,7 @@
:transaction-insight-explain (wrap-client-redirect-unauthenticated (wrap-admin insights/explain))
:admin-ezcater-xls (wrap-client-redirect-unauthenticated (wrap-admin ezcater-xls/page))
:search (wrap-client-redirect-unauthenticated (wrap-secure search/dialog-contents))}
+ (into company-1099/key->handler)
(into pos-sales/key->handler)
(into pos-expected-deposits/key->handler)
(into pos-tenders/key->handler)
diff --git a/src/clj/auto_ap/ssr/form_cursor.clj b/src/clj/auto_ap/ssr/form_cursor.clj
index 536a3a2f..00921e5e 100644
--- a/src/clj/auto_ap/ssr/form_cursor.clj
+++ b/src/clj/auto_ap/ssr/form_cursor.clj
@@ -30,6 +30,15 @@
`(with-cursor (get *current* ~field )
~@rest))
+(defmacro with-field-default [field default & rest]
+ `(let [next-cursor# (get *current* ~field )
+ next-cursor# (if (nil? @next-cursor#)
+ (cursor/update! next-cursor# default)
+ next-cursor#)]
+ (with-cursor next-cursor#
+ ~@rest)))
+
+
(defn field-name
([] (field-name *current*))
([cursor]
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 1e17b887..080fd2cc 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -243,7 +243,8 @@
(defn ref->enum-schema [n]
(into [:enum {:decode/string #(if (keyword? %)
%
- (keyword n %)
+ (when (not-empty %)
+ (keyword n %))
)}]
(for [{:db/keys [ident]} (all-schema)
:when (= n (namespace ident))]
@@ -266,20 +267,6 @@
{:value (name ident) :content (str/replace (str/capitalize (name ident)) "-" " ")})))
-
-
-(defn wrap-form-4xx [handler]
- (fn [request]
- (try+
- (handler request)
-
-
- (catch [:type :validation] e
- (alog/warn ::form-4xx :error e)
- (html-response [:span.error-content.text-red-500 (:message &throw-context)]
- :status 400)))))
-
-
(defn wrap-form-4xx-2 [handler form-handler]
(fn [request]
(try+
From 5ed23f26be7acd2ea3dd66b1047d62a4009a7afc Mon Sep 17 00:00:00 2001
From: Bryce
Date: Thu, 26 Oct 2023 15:54:41 -0700
Subject: [PATCH 32/34] fixes
---
src/clj/auto_ap/cursor.clj | 1 -
src/clj/auto_ap/ssr/admin/accounts.clj | 19 +--------
src/clj/auto_ap/ssr/admin/background_jobs.clj | 2 +-
.../auto_ap/ssr/admin/transaction_rules.clj | 10 ++---
src/clj/auto_ap/ssr/company.clj | 2 +-
src/clj/auto_ap/ssr/company/company_1099.clj | 23 ++++++++---
src/clj/auto_ap/ssr/company/yodlee.clj | 1 -
src/clj/auto_ap/ssr/components.clj | 3 +-
src/clj/auto_ap/ssr/components/inputs.clj | 40 +------------------
src/clj/auto_ap/ssr/form_cursor.clj | 8 +---
src/clj/auto_ap/ssr/pos/refunds.clj | 16 ++------
src/clj/auto_ap/ssr/users.clj | 4 +-
src/clj/auto_ap/ssr/utils.clj | 8 ++--
13 files changed, 37 insertions(+), 100 deletions(-)
diff --git a/src/clj/auto_ap/cursor.clj b/src/clj/auto_ap/cursor.clj
index 6a7f25cc..4247b9f5 100644
--- a/src/clj/auto_ap/cursor.clj
+++ b/src/clj/auto_ap/cursor.clj
@@ -1,7 +1,6 @@
(ns auto-ap.cursor
(:import (clojure.lang IDeref Atom ILookup Counted IFn AFn Indexed ISeq Seqable)))
-; TODO not sure if these methods are needed at all; ICursor is used solely as a marker right now
(defprotocol ICursor
(path [cursor])
(state [cursor]))
diff --git a/src/clj/auto_ap/ssr/admin/accounts.clj b/src/clj/auto_ap/ssr/admin/accounts.clj
index 5c913a68..53061b12 100644
--- a/src/clj/auto_ap/ssr/admin/accounts.clj
+++ b/src/clj/auto_ap/ssr/admin/accounts.clj
@@ -232,7 +232,6 @@
"hx-reswap" "afterbegin")
(= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-account)))))))
-;; TODO decide when cursors are used. other cases it's not, some are
(defn client-override* [override]
(com/data-grid-row (-> {:x-ref "p"
:data-key "show"
@@ -245,7 +244,7 @@
(fc/with-field :account-client-override/client
(com/data-grid-cell {}
(com/validated-field {:errors (fc/field-errors)}
- (com/typeahead-2 {:name (fc/field-name)
+ (com/typeahead {:name (fc/field-name)
:placeholder "Search..."
:class "w-96"
:url (bidi/path-for ssr-routes/only-routes
@@ -262,20 +261,6 @@
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
-;; TODO each form:
-;; elimante typeahead1
-;; work with new dialog
-;; use cursor
-;; ensure all dialogs are opened the same way
-;; form level validation
-;; form level validation
-;; componentize
-;; ensure all dependency oriented stuff works the same way
-;; make sure that "new row index" stuff works ok
-;; TODO figure out when hx-targets are decided
-;; ensure that adding a new one results in a new row
-
-
(defn dialog* [{:keys [entity form-params form-errors]}]
(fc/start-form form-params form-errors
[:div {:x-data (hx/json {"accountName" (or (:account/name form-params) (:account/numeric-code entity))
@@ -383,8 +368,6 @@
(com/validated-save-button {:errors (seq form-errors)}
"Save account")])]])]))
-;; TODO saving new row should att it to the tbody
-
(defn new-client-override [{ {:keys [index]} :query-params}]
(html-response
(fc/start-form-with-prefix
diff --git a/src/clj/auto_ap/ssr/admin/background_jobs.clj b/src/clj/auto_ap/ssr/admin/background_jobs.clj
index ec1ecdfc..f09879bd 100644
--- a/src/clj/auto_ap/ssr/admin/background_jobs.clj
+++ b/src/clj/auto_ap/ssr/admin/background_jobs.clj
@@ -182,7 +182,7 @@
(fc/with-field :client
(com/validated-field {:label "Client"
:errors (fc/field-errors)}
- (com/typeahead-2 {:name (fc/field-name)
+ (com/typeahead {:name (fc/field-name)
:value (fc/field-value)
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 87e02b7f..734a3aac 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -56,7 +56,7 @@
[:fieldset.space-y-6
(com/field {:label "Vendor"}
- (com/typeahead-2 {:name "vendor"
+ (com/typeahead {:name "vendor"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes
:vendor-search)
@@ -318,7 +318,7 @@
(defn- account-typeahead*
[{:keys [name value client-id x-model]}]
[:div.flex.flex-col
- (com/typeahead-2 {:name name
+ (com/typeahead {:name name
:placeholder "Search..."
:url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id)
:id name
@@ -389,7 +389,6 @@
(com/data-grid-cell {:class "align-top"}
(com/a-icon-button {"@click.prevent.stop" "show=false; setTimeout(() => $refs.p.remove(), 500)"} svg/x))))
-;; TODO background jobs and company 1099
(defn dialog* [{:keys [entity form-params form-errors]}]
(fc/start-form form-params form-errors
(com/modal
@@ -448,7 +447,7 @@
:x-show "clientFilter"}
(hx/alpine-appear))
[:div.w-96
- (com/typeahead-2 {:name (fc/field-name)
+ (com/typeahead {:name (fc/field-name)
:error? (fc/error?)
:class "w-96"
:placeholder "Search..."
@@ -520,7 +519,7 @@
(com/validated-field {:label "Assign Vendor"
:errors (fc/field-errors)}
[:div.w-96
- (com/typeahead-2 {:name (fc/field-name)
+ (com/typeahead {:name (fc/field-name)
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :vendor-search)
:class "w-96"
@@ -572,7 +571,6 @@
(some->> client-id (pull-attr (dc/db conn) :client/locations) client-id)))))
-;; TODO check to see if it should be called "Shared" or "shared" for the value
(defn location-select [{{:keys [name account-id client-id value] :as qp} :query-params}]
(html-response (location-select* {:name name
diff --git a/src/clj/auto_ap/ssr/company.clj b/src/clj/auto_ap/ssr/company.clj
index 075bae63..aa1a19d2 100644
--- a/src/clj/auto_ap/ssr/company.clj
+++ b/src/clj/auto_ap/ssr/company.clj
@@ -108,7 +108,7 @@
(defn bank-account-typeahead* [{:keys [client-id name value]}]
(if client-id
- (com/typeahead-2 {:name name
+ (com/typeahead {:name name
:class "w-96"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes :bank-account-search
diff --git a/src/clj/auto_ap/ssr/company/company_1099.clj b/src/clj/auto_ap/ssr/company/company_1099.clj
index fdbb27bb..ecf21bf2 100644
--- a/src/clj/auto_ap/ssr/company/company_1099.clj
+++ b/src/clj/auto_ap/ssr/company/company_1099.clj
@@ -176,8 +176,20 @@
{:keys [vendor-id]} :route-params
{:keys [client-id]} :query-params}]
+
(assert-can-see-client identity client-id)
- @(dc/transact conn [[:upsert-entity (assoc form-params :db/id (:vendor-id route-params))]])
+
+ @(dc/transact conn [[:upsert-entity (-> form-params
+ (assoc :db/id (:vendor-id route-params))
+ (update :vendor/address (fn [a]
+ (if (or (:address/street1 a)
+ (:address/street2 a)
+ (:address/city a)
+ (:address/state a)
+ (:address/zip a)
+ (:db/id a))
+ a
+ nil)) ))]])
(html-response
(row* identity [(dc/pull (dc/db conn) [:db/id :client/code] client-id)
@@ -192,7 +204,7 @@
(def form-schema (mc/schema [:map
- [:vendor/address {:default {} }
+ [:vendor/address {:default {}}
[:maybe
[:map
[:db/id {:optional true} [:maybe entity-id]]
@@ -234,7 +246,8 @@
[:div.flex [:div.p-2 "Vendor 1099 Info"] [:p.ml-2.rounded.bg-gray-200.p-2.dark:bg-gray-600 (:vendor/name entity)]]
[:div.grid.grid-cols-6.gap-x-4.gap-y-2
- (fc/with-field :vendor/address ;; TODO support default
+ (fc/with-field-default :vendor/address {}
+ (println "ADDRESS" fc/*current*)
(list [:h4.text-xl.border-b.col-span-6 "Address"]
[:div.col-span-6
(fc/with-field :db/id
@@ -335,11 +348,11 @@
:errors (fc/field-errors)}
(com/select {:name (fc/field-name)
:allow-blank? true
- :value (some-> (fc/field-value) name) ;; TODO use ref stuff
+ :value (some-> (fc/field-value) name)
:options (ref->select-options "legal-entity-1099-type")})))]]
[:div
(com/form-errors {:errors (:errors fc/*form-errors*)})
- (com/validated-save-button {:errors form-errors} "Save rule")])]]))))
+ (com/validated-save-button {:errors form-errors} "Save vendor")])]]))))
(def vendor-table (helper/table-route grid-page))
(def page (helper/page-route grid-page))
diff --git a/src/clj/auto_ap/ssr/company/yodlee.clj b/src/clj/auto_ap/ssr/company/yodlee.clj
index 699c40fa..7bae6fa2 100644
--- a/src/clj/auto_ap/ssr/company/yodlee.clj
+++ b/src/clj/auto_ap/ssr/company/yodlee.clj
@@ -208,7 +208,6 @@ fastlink.open({fastLinkURL: '%s',
(def page (helper/page-route grid-page))
(def table (helper/table-route grid-page))
-;; TODO delete-after-settle
(defn refresh-provider-account [{:keys [form-params identity]}]
(let [provider-account (dc/pull (dc/db conn) default-read (some-> (get form-params "id") not-empty Long/parseLong))]
(yodlee/refresh-provider-account (:client/code (:yodlee-provider-account/client provider-account))
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index 305afc49..8187030d 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -31,8 +31,7 @@
(def date-input inputs/date-input-)
(def hidden inputs/hidden-)
(def select inputs/select-)
-(def typeahead inputs/typeahead-)
-(def typeahead-2 inputs/typeahead-2-)
+(def typeahead inputs/tytypeahead-
(def field-errors inputs/field-errors-)
(def field inputs/field-)
(def validated-field inputs/validated-field-)
diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj
index acc46704..8bfb07db 100644
--- a/src/clj/auto_ap/ssr/components/inputs.clj
+++ b/src/clj/auto_ap/ssr/components/inputs.clj
@@ -32,45 +32,8 @@
(:allow-blank? params) (conj [:option {:value "" :selected (not (:value params))} ""]))]
children))
+
(defn typeahead- [params]
- [:select (-> params
- (dissoc :url)
- (dissoc :value)
- (dissoc :value-fn)
- (dissoc :content-fn))
- (for [value (if (:multiple params)
- (:value params)
- [(:value params)])
- :when ((:value-fn params first) value)]
- [:option {:value ((:value-fn params first) value) :selected true} ((:content-fn params second) value)])
-
- [:script {:lang "javascript"}
- (hiccup/raw (format "
-(function () {
-var element = document.getElementById('%s');
-var c = new Choices(element, {removeItems: true, removeItemButton:true, searchFloor: 3, searchPlaceholderValue: '%s'});
-let baseUrl = '%s';
-
-element.addEventListener('search', function (e) {
- let fullUrl = baseUrl + (baseUrl.includes(\"?\") ? \"&\" : \"?\") + \"q=\" + e.detail.value;
- let data = fetch(fullUrl)
- .then(res => res.json())
- .then(data => {
- c.setChoices(data, 'value', 'label', true)
- });
-});
-element.addEventListener('choice', function (e) {
-c.clearChoices();
- })
-})();
-
-"
- (:id params)
- (:placeholder params)
- (:url params)
- ))]])
-
-(defn typeahead-2- [params]
[:div {:x-data (hx/json {:open false
:baseUrl (if (str/includes? (:url params) "?")
(str (:url params) "&q=")
@@ -152,7 +115,6 @@ c.clearChoices();
]])
-;; TODO fix search modal
(defn use-size [size]
(if (= :small size)
(str " " "text-xs p-2")
diff --git a/src/clj/auto_ap/ssr/form_cursor.clj b/src/clj/auto_ap/ssr/form_cursor.clj
index 00921e5e..b1617452 100644
--- a/src/clj/auto_ap/ssr/form_cursor.clj
+++ b/src/clj/auto_ap/ssr/form_cursor.clj
@@ -31,12 +31,8 @@
~@rest))
(defmacro with-field-default [field default & rest]
- `(let [next-cursor# (get *current* ~field )
- next-cursor# (if (nil? @next-cursor#)
- (cursor/update! next-cursor# default)
- next-cursor#)]
- (with-cursor next-cursor#
- ~@rest)))
+ `(with-cursor (get *current* ~field ~default)
+ ~@rest))
(defn field-name
diff --git a/src/clj/auto_ap/ssr/pos/refunds.clj b/src/clj/auto_ap/ssr/pos/refunds.clj
index 49f741b1..2651307e 100644
--- a/src/clj/auto_ap/ssr/pos/refunds.clj
+++ b/src/clj/auto_ap/ssr/pos/refunds.clj
@@ -8,25 +8,15 @@
merge-query
pull-many
query2]]
- [auto-ap.graphql.utils :refer [extract-client-ids]]
- [auto-ap.routes.utils
- :refer [wrap-client-redirect-unauthenticated wrap-secure]]
- [auto-ap.ssr.pos.common :refer [date-range-field* processor-field* total-field*]]
+ [auto-ap.query-params :as query-params]
[auto-ap.ssr-routes :as ssr-routes]
[auto-ap.ssr.components :as com]
[auto-ap.ssr.grid-page-helper :as helper]
- [auto-ap.ssr.svg :as svg]
+ [auto-ap.ssr.pos.common :refer [date-range-field* total-field*]]
[auto-ap.time :as atime]
[bidi.bidi :as bidi]
[clj-time.coerce :as c]
- [datomic.api :as dc]
- [clojure.set :as set]
- [auto-ap.query-params :as query-params]
- [malli.core :as m]))
-
-;; TODO refunds
-;; always should be fast
-;; make params parsing composable
+ [datomic.api :as dc]))
(defn filters [request]
[:form {"hx-trigger" "change delay:500ms, keyup changed from:.hot-filter delay:1000ms"
diff --git a/src/clj/auto_ap/ssr/users.clj b/src/clj/auto_ap/ssr/users.clj
index 7861f1d2..7d481140 100644
--- a/src/clj/auto_ap/ssr/users.clj
+++ b/src/clj/auto_ap/ssr/users.clj
@@ -80,7 +80,7 @@
{:value "none"
:content "None"}]}))
(com/field {:label "Client"}
- (com/typeahead-2 {:name "client"
+ (com/typeahead {:name "client"
:placeholder "Search..."
:url (bidi/path-for ssr-routes/only-routes
:company-search)
@@ -273,7 +273,7 @@
hx/alpine-mount-then-appear)
(com/data-grid-cell {}
(com/validated-field {:errors (fc/field-errors (:db/id fc/*current*))}
- (com/typeahead-2 {:name (fc/field-name (:db/id fc/*current*))
+ (com/typeahead {:name (fc/field-name (:db/id fc/*current*))
:class "w-full"
:url (bidi/path-for ssr-routes/only-routes
:company-search)
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 080fd2cc..80479333 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -102,7 +102,8 @@
(defn parse-empty-as-nil []
(mt2/transformer
{:decoders
- {:double empty->nil
+ {:string empty->nil
+ :double empty->nil
:int empty->nil
:long empty->nil
'nat-int? empty->nil}}))
@@ -160,10 +161,7 @@
(subs (str k) 1))
-;; TODO need to remove or at least remove usages as the form is not included
-(defn validation-error [m & {:as data}]
- (throw+ (ex-info m (merge data {:type :validation}))))
-
+;; TODO make this bubble the form data automatically
(defn field-validation-error [m path & {:as data}]
(throw+ (ex-info m (merge data {:type :field-validation
:form-errors (assoc-in {} path [m])}))))
From 7f7458d54ae7bcaa64b7c608ba50ddb47ba26998 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Thu, 26 Oct 2023 21:23:52 -0700
Subject: [PATCH 33/34] Makes testing of transaction rules work
---
resources/input.css | 23 +++
resources/public/output.css | 2 +-
.../auto_ap/ssr/admin/transaction_rules.clj | 173 +++++++++++++++---
src/clj/auto_ap/ssr/components.clj | 2 +-
src/clj/auto_ap/ssr/components/aside.clj | 3 +-
src/clj/auto_ap/ssr/components/buttons.clj | 5 +-
src/clj/auto_ap/ssr/components/dialog.clj | 4 +-
src/clj/auto_ap/ssr/nested_form_params.clj | 4 +-
src/clj/auto_ap/ssr/pos/common.clj | 3 -
src/clj/auto_ap/ssr/ui.clj | 6 +-
src/clj/auto_ap/ssr/utils.clj | 9 +
src/cljc/auto_ap/ssr_routes.cljc | 2 +
12 files changed, 196 insertions(+), 40 deletions(-)
diff --git a/resources/input.css b/resources/input.css
index 9e3a576e..0f061e61 100644
--- a/resources/input.css
+++ b/resources/input.css
@@ -26,6 +26,29 @@
}
+
+.htmx-added.swipe-left-swap , .htmx-added .swipe-left-swap{
+ @apply opacity-100 !important;
+ @apply scale-100 !important;
+ @apply -translate-x-1/2 !important;
+
+}
+
+.htmx-added.swipe-left-swap , .htmx-added .swipe-left-swap{
+ @apply opacity-100;
+ @apply scale-100;
+ @apply translate-x-0;
+
+}
+.htmx-settling.htmx-added .swipe-left-swap, .htmx-settling.htmx-added.swipe-left-swap{
+
+ @apply opacity-0 !important;
+ @apply scale-75 !important;
+ @apply translate-x-1/2 !important;
+
+}
+
+
.htmx-settling .slide-up-settle {
@apply translate-y-5 !important;
}
diff --git a/resources/public/output.css b/resources/public/output.css
index 6bb05656..740c8b37 100644
--- a/resources/public/output.css
+++ b/resources/public/output.css
@@ -1 +1 @@
-/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-4{margin:1rem}.m-2{margin:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.\!mt-0{margin-top:0!important}.\!mt-1{margin-top:.25rem!important}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-96{height:24rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.w-72{width:18rem}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.-translate-x-0,.translate-y-full{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-x-0{--tw-translate-x:-0px}.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))}.\!scale-100{--tw-scale-x:1!important;--tw-scale-y:1!important}.\!scale-100,.\!scale-50{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}.\!scale-50{--tw-scale-x:.5!important;--tw-scale-y:.5!important}.transform{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(255 3 3/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-5{padding-top:1.25rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group:hover .group-hover\:text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:flex{display:flex}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:translate-x-0{--tw-translate-x:0px}.lg\:-translate-x-full,.lg\:translate-x-0{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))}.lg\:-translate-x-full{--tw-translate-x:-100%}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
+/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Calibri,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}select:not([size]){background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236B7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#007dbb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid #0000;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark [type=checkbox]:checked,.dark [type=radio]:checked,[type=checkbox]:checked,[type=radio]:checked{border-color:#0000;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:indeterminate,[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:#0000;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px auto inherit}input[type=file]::file-selector-button{color:#fff;background:#1f2937;border:0;font-weight:500;font-size:.875rem;cursor:pointer;padding:.625rem 1rem .625rem 2rem;-webkit-margin-start:-1rem;margin-inline-start:-1rem;-webkit-margin-end:1rem;margin-inline-end:1rem}input[type=file]::file-selector-button:hover{background:#374151}.dark input[type=file]::file-selector-button{color:#fff;background:#4b5563}.dark input[type=file]::file-selector-button:hover{background:#6b7280}input[type=range]::-webkit-slider-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-webkit-slider-thumb{background:#9ca3af}.dark input[type=range]:disabled::-webkit-slider-thumb{background:#6b7280}input[type=range]:focus::-webkit-slider-thumb{outline:2px solid #0000;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-opacity:1px;--tw-ring-color:rgb(164 202 254/var(--tw-ring-opacity))}input[type=range]::-moz-range-thumb{height:1.25rem;width:1.25rem;background:#007dbb;border-radius:9999px;border:0;appearance:none;-moz-appearance:none;-webkit-appearance:none;cursor:pointer}input[type=range]:disabled::-moz-range-thumb{background:#9ca3af}.dark input[type=range]:disabled::-moz-range-thumb{background:#6b7280}input[type=range]::-moz-range-progress{background:#009cea}input[type=range]::-ms-fill-lower{background:#009cea}.toggle-bg:after{content:"";position:absolute;top:.125rem;left:.125rem;background:#fff;border-color:#d1d5db;border-width:1px;border-radius:9999px;height:1.25rem;width:1.25rem;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-duration:.15s;box-shadow:var(--tw-ring-inset) 0 0 0 calc(var(--tw-ring-offset-width)) var(--tw-ring-color)}input:checked+.toggle-bg:after{transform:translateX(100%);;border-color:#fff}input:checked+.toggle-bg{background:#007dbb;border-color:#007dbb}.tooltip-arrow,.tooltip-arrow:before{position:absolute;width:8px;height:8px;background:inherit}.tooltip-arrow{visibility:hidden}.tooltip-arrow:before{content:"";visibility:visible;transform:rotate(45deg)}[data-tooltip-style^=light]+.tooltip>.tooltip-arrow:before{border-style:solid;border-color:#e5e7eb}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=top]>.tooltip-arrow:before{border-bottom-width:1px;border-right-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=right]>.tooltip-arrow:before{border-bottom-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=bottom]>.tooltip-arrow:before{border-top-width:1px;border-left-width:1px}[data-tooltip-style^=light]+.tooltip[data-popper-placement^=left]>.tooltip-arrow:before{border-top-width:1px;border-right-width:1px}.tooltip[data-popper-placement^=top]>.tooltip-arrow{bottom:-4px}.tooltip[data-popper-placement^=bottom]>.tooltip-arrow{top:-4px}.tooltip[data-popper-placement^=left]>.tooltip-arrow{right:-4px}.tooltip[data-popper-placement^=right]>.tooltip-arrow{left:-4px}.tooltip.invisible>.tooltip-arrow:before{visibility:hidden}[data-popper-arrow],[data-popper-arrow]:before{position:absolute;width:8px;height:8px;background:inherit}[data-popper-arrow]{visibility:hidden}[data-popper-arrow]:after,[data-popper-arrow]:before{content:"";visibility:visible;transform:rotate(45deg)}[data-popper-arrow]:after{position:absolute;width:9px;height:9px;background:inherit}[role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:before{border-style:solid;border-color:#4b5563}[role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#e5e7eb}.dark [role=tooltip]>[data-popper-arrow]:after{border-style:solid;border-color:#4b5563}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]:before{border-bottom-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]:before{border-bottom-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]:before{border-top-width:1px;border-left-width:1px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:after,[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]:before{border-top-width:1px;border-right-width:1px}[data-popover][role=tooltip][data-popper-placement^=top]>[data-popper-arrow]{bottom:-5px}[data-popover][role=tooltip][data-popper-placement^=bottom]>[data-popper-arrow]{top:-5px}[data-popover][role=tooltip][data-popper-placement^=left]>[data-popper-arrow]{right:-5px}[data-popover][role=tooltip][data-popper-placement^=right]>[data-popper-arrow]{left:-5px}[role=tooltip].invisible>[data-popper-arrow]:after,[role=tooltip].invisible>[data-popper-arrow]:before{visibility:hidden}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#009cea80;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-.5rem}.-top-2{top:-.5rem}.bottom-0{bottom:0}.bottom-\[60px\]{bottom:60px}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-2{right:.5rem}.top-0{top:0}.top-2{top:.5rem}.top-2\/4{top:50%}.top-5{top:1.25rem}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[99\]{z-index:99}.col-span-1{grid-column:span 1/span 1}.col-span-2{grid-column:span 2/span 2}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.col-start-1{grid-column-start:1}.m-1{margin:.25rem}.m-2{margin:.5rem}.m-4{margin:1rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-4{margin-top:1rem;margin-bottom:1rem}.-mb-1{margin-bottom:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-10{margin-right:2.5rem}.mr-16{margin-right:4rem}.mr-2{margin-right:.5rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.ml-4{margin-left:1rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-10{height:2.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-48{height:12rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-8{height:2rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-full{max-height:100%}.w-1\/2{width:50%}.w-16{width:4rem}.w-24{width:6rem}.w-3{width:.75rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-8{width:2rem}.w-96{width:24rem}.w-auto{width:auto}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.w-screen{width:100vw}.min-w-\[700px\]{min-width:700px}.max-w-2xl{max-width:42rem}.max-w-6xl{max-width:72rem}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-screen-2xl{max-width:1536px}.max-w-screen-lg{max-width:1024px}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-1\/4{flex-basis:25%}.\!translate-y-0{--tw-translate-y:0px!important}.\!translate-y-0,.\!translate-y-32{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}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-x-full{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-x-full{--tw-translate-x:-100%}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.-translate-y-full{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-full{--tw-translate-y:-100%}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-full{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-x-full{--tw-translate-x:100%}.translate-y-full{--tw-translate-y:100%}.rotate-180,.translate-y-full{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{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))}.transform-none{transform:none}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes shake{0%{transform:translateX(0)}12.5%{transform:translateX(-5px)}25%{transform:translateX(0)}37.5%{transform:translateX(5px)}50%{transform:translateX(0)}62.5%{transform:translateX(-5px)}75%{transform:translateX(5px)}87.5%{transform:translateX(5px)}to{transform:translateX(0)}}.animate-shake{animation:shake .5s ease-out 1}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.items-stretch{align-items:stretch}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-stretch{justify-content:stretch}.justify-items-stretch{justify-items:stretch}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.gap-x-4{-moz-column-gap:1rem;column-gap:1rem}.gap-y-2{row-gap:.5rem}.-space-x-px>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(-1px*var(--tw-space-x-reverse));margin-left:calc(-1px*(1 - var(--tw-space-x-reverse)))}.space-x-1>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.25rem*var(--tw-space-x-reverse));margin-left:calc(.25rem*(1 - var(--tw-space-x-reverse)))}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.5rem*var(--tw-space-x-reverse));margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-gray-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(243 244 246/var(--tw-divide-opacity))}.self-center{align-self:center}.self-stretch{align-self:stretch}.justify-self-end{justify-self:end}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-scroll{overflow:scroll}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-b-lg{border-bottom-right-radius:.5rem}.rounded-b-lg,.rounded-l-lg{border-bottom-left-radius:.5rem}.rounded-l-lg{border-top-left-radius:.5rem}.rounded-r-lg{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.rounded-t{border-top-left-radius:.25rem;border-top-right-radius:.25rem}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-dashed{border-style:dashed}.border-blue-300{--tw-border-opacity:1;border-color:rgb(102 196 242/var(--tw-border-opacity))}.border-blue-600{--tw-border-opacity:1;border-color:rgb(0 125 187/var(--tw-border-opacity))}.border-blue-700{--tw-border-opacity:1;border-color:rgb(0 94 140/var(--tw-border-opacity))}.border-gray-100{--tw-border-opacity:1;border-color:rgb(243 244 246/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-primary-300{--tw-border-opacity:1;border-color:rgb(175 211 130/var(--tw-border-opacity))}.border-red-300{--tw-border-opacity:1;border-color:rgb(255 104 104/var(--tw-border-opacity))}.border-white{--tw-border-opacity:1;border-color:rgb(255 255 255/var(--tw-border-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(204 235 251/var(--tw-bg-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(153 215 247/var(--tw-bg-opacity))}.bg-blue-300{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.bg-blue-400{--tw-bg-opacity:1;background-color:rgb(51 176 238/var(--tw-bg-opacity))}.bg-blue-50{--tw-bg-opacity:1;background-color:rgb(230 245 253/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(0 156 234/var(--tw-bg-opacity))}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.bg-blue-700{--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-gray-400{--tw-bg-opacity:1;background-color:rgb(156 163 175/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.bg-green-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-green-300{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(148 196 88/var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(121 181 46/var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.bg-green-700{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}.bg-green-800{--tw-bg-opacity:1;background-color:rgb(48 72 18/var(--tw-bg-opacity))}.bg-primary-200{--tw-bg-opacity:1;background-color:rgb(201 225 171/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(242 248 234/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(255 205 205/var(--tw-bg-opacity))}.bg-red-200{--tw-bg-opacity:1;background-color:rgb(255 154 154/var(--tw-bg-opacity))}.bg-red-300{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/50{background-color:#ffffff80}.bg-yellow-100{--tw-bg-opacity:1;background-color:rgb(253 246 178/var(--tw-bg-opacity))}.\!bg-opacity-0{--tw-bg-opacity:0!important}.\!bg-opacity-100{--tw-bg-opacity:1!important}.\!bg-opacity-50{--tw-bg-opacity:0.5!important}.bg-opacity-50{--tw-bg-opacity:0.5}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pb-2{padding-bottom:.5rem}.pb-3{padding-bottom:.75rem}.pl-10{padding-left:2.5rem}.pl-11{padding-left:2.75rem}.pl-2{padding-left:.5rem}.pl-3{padding-left:.75rem}.pr-2{padding-right:.5rem}.pr-2\.5{padding-right:.625rem}.pt-16{padding-top:4rem}.pt-2{padding-top:.5rem}.pt-8{padding-top:2rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-baseline{vertical-align:initial}.align-top{vertical-align:top}.text-2xl{font-size:1.5rem;line-height:2rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-6{line-height:1.5rem}.leading-9{line-height:2.25rem}.leading-none{line-height:1}.leading-tight{line-height:1.25}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.text-blue-800{--tw-text-opacity:1;color:rgb(0 62 94/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-green-800{--tw-text-opacity:1;color:rgb(48 72 18/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(97 145 37/var(--tw-text-opacity))}.text-red-500{--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(204 2 2/var(--tw-text-opacity))}.text-red-800{--tw-text-opacity:1;color:rgb(102 1 1/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-yellow-800{--tw-text-opacity:1;color:rgb(114 59 19/var(--tw-text-opacity))}.underline{text-decoration-line:underline}.\!opacity-0{opacity:0!important}.\!opacity-100{opacity:1!important}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-2xl{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-md{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.outline-0{outline-width:0}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.blur{--tw-blur:blur(8px)}.blur,.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.duration-500{transition-duration:.5s}.duration-75{transition-duration:75ms}.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\]{transition-timing-function:cubic-bezier(.3,2.3,.6,1)}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.htmx-added .fade-in,.htmx-added.fade-in{opacity:0!important}.fade-in{opacity:1}.htmx-settling .fade-in-settle,.htmx-settling.fade-in-settle{opacity:0!important}.fade-in-settle{opacity:1}.htmx-added .swipe-left-swap,.htmx-added.swipe-left-swap{--tw-translate-x:-50%!important;opacity:1;--tw-scale-x:1;--tw-scale-y:1;--tw-translate-x: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))}.htmx-settling.htmx-added .swipe-left-swap,.htmx-settling.htmx-added.swipe-left-swap{opacity:0!important;--tw-scale-x:.75!important;--tw-scale-y:.75!important;--tw-translate-x:50%!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}.htmx-settling .slide-up-settle,.htmx-settling.slide-up-settle{--tw-translate-y:1.25rem!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}.slide-up-settle{--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))}.hidden .slide-up,.htmx-added .slide-up{--tw-translate-y:1.25rem!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}.slide-up{--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))}.live-added{animation:pulse-green .3s 2;animation-direction:alternate;animation-timing-function:ease-in-out}.dark .live-added{animation:pulse-dark-green .3s 2!important;animation-direction:alternate;animation-timing-function:ease-in-out}@keyframes pulse-green{0%{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}:is(.dark to){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}}@keyframes pulse-dark-green{:is(.dark 0%){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}to{--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}}.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inherit!important}.htmx-indicator{display:none}.htmx-request .htmx-indicator-hidden{display:none!important}.htmx-indicator-hidden{display:inherit}.htmx-swapping .fade-out{opacity:0!important}.fade-out{opacity:1}.min-h-content{min-height:calc(100vh - 4em)}.choices{margin-bottom:0!important;border-width:0!important}.choices__inner{display:block!important;width:100%!important;border-radius:.5rem!important;border-width:1px!important;--tw-border-opacity:1!important;border-color:rgb(209 213 219/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important;padding:.25rem!important;font-size:.875rem!important;line-height:1.25rem!important;--tw-text-opacity:1!important;color:rgb(17 24 39/var(--tw-text-opacity))!important}.choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error .choices__inner{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(255 230 230/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(51 1 1/var(--tw-text-opacity))!important}.group.has-error .choices__inner::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner::placeholder{--tw-placeholder-opacity:1!important;color:rgb(153 2 2/var(--tw-placeholder-opacity))!important}.group.has-error .choices__inner:focus{--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))!important}:is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(75 85 99/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}:is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(156 163 175/var(--tw-placeholder-opacity))!important}:is(.dark .choices__inner:focus){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.group.has-error :is(.dark .choices__inner){--tw-border-opacity:1!important;border-color:rgb(255 3 3/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 3 3/var(--tw-text-opacity))!important}.group.has-error :is(.dark .choices__inner)::-moz-placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.group.has-error :is(.dark .choices__inner)::placeholder{--tw-placeholder-opacity:1!important;color:rgb(255 3 3/var(--tw-placeholder-opacity))!important}.choices:focus-within .choices__inner,:is(.dark .choices:focus-within .choices__inner){--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices:focus-within .choices__inner{outline:2px solid #0000!important;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#007dbb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#007dbb}.choices__inner .choices__input{margin:0!important;--tw-bg-opacity:1!important;background-color:rgb(249 250 251/var(--tw-bg-opacity))!important}:is(.dark .choices__inner .choices__input){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(255 255 255/var(--tw-text-opacity))!important}.choices__inner .choices__item{white-space:nowrap!important;border-radius:.25rem!important;--tw-border-opacity:1!important;border-color:rgb(156 163 175/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;padding:.125rem .5rem!important;font-size:.75rem!important;line-height:1rem!important;font-weight:500!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__inner .choices__item){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices__list--dropdown{border-radius:.5rem!important;--tw-bg-opacity:1!important;background-color:rgb(255 255 255/var(--tw-bg-opacity))!important;--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a!important;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)!important;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)!important}:is(.dark .choices__list--dropdown){--tw-bg-opacity:1!important;background-color:rgb(55 65 81/var(--tw-bg-opacity))!important}.choices__list--dropdown .choices__item--selectable.is-highlighted{--tw-bg-opacity:1!important;background-color:rgb(175 211 130/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(48 72 18/var(--tw-text-opacity))!important}:is(.dark .choices__list--dropdown .choices__item--selectable.is-highlighted){--tw-bg-opacity:1!important;background-color:rgb(24 36 9/var(--tw-bg-opacity))!important;--tw-text-opacity:1!important;color:rgb(175 211 130/var(--tw-text-opacity))!important}.choices[data-type*=select-multiple] .choices__button{--tw-border-opacity:1!important;border-color:rgb(107 114 128/var(--tw-border-opacity))!important}.choices[data-type*=select-multiple] .choices__button:focus{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__inner .choices__item:focus-within{--tw-border-opacity:1!important;border-color:rgb(0 156 234/var(--tw-border-opacity))!important;--tw-bg-opacity:1!important;background-color:rgb(121 181 46/var(--tw-bg-opacity))!important;--tw-ring-opacity:1!important;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))!important}.choices__list--single .choices__item{display:flex!important;width:auto!important}.choices__list--single{width:auto!important}.choices__list--single button{position:relative!important;margin:0!important;display:block!important;height:auto!important}.choices[data-type*=select-one] .choices__button{right:auto!important}.arrow,.arrow:before{position:absolute;width:24px;height:24px;background:inherit}.arrow{visibility:hidden}.arrow:before{visibility:visible;content:"";transform:rotate(45deg)}.arrow{bottom:-4px}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{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))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:border-gray-300:hover{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.hover\:bg-blue-300:hover{--tw-bg-opacity:1;background-color:rgb(102 196 242/var(--tw-bg-opacity))}.hover\:bg-blue-600:hover{--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}.hover\:bg-blue-800:hover{--tw-bg-opacity:1;background-color:rgb(0 62 94/var(--tw-bg-opacity))}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.hover\:bg-green-100:hover{--tw-bg-opacity:1;background-color:rgb(228 240 213/var(--tw-bg-opacity))}.hover\:bg-green-300:hover{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.hover\:bg-green-600:hover{--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}.hover\:bg-green-700:hover{--tw-bg-opacity:1;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))}.hover\:bg-red-300:hover{--tw-bg-opacity:1;background-color:rgb(255 104 104/var(--tw-bg-opacity))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(0 125 187/var(--tw-text-opacity))}.hover\:text-gray-600:hover{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.hover\:text-gray-700:hover{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.hover\:text-gray-800:hover{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.hover\:text-gray-900:hover{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.hover\:text-primary-700:hover{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.hover\:underline:hover{text-decoration-line:underline}.focus\:z-10:focus{z-index:10}.focus\:border-blue-500:focus{--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}.focus\:border-primary-500:focus{--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}.focus\:bg-neutral-100:focus{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity))}.focus\:text-green-700:focus{--tw-text-opacity:1;color:rgb(73 109 28/var(--tw-text-opacity))}.focus\:outline-none:focus{outline:2px solid #0000;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-2:focus,.focus\:ring-4:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-4:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-blue-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(153 215 247/var(--tw-ring-opacity))}.focus\:ring-blue-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(102 196 242/var(--tw-ring-opacity))}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}.focus\:ring-gray-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(229 231 235/var(--tw-ring-opacity))}.focus\:ring-gray-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity))}.focus\:ring-green-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(201 225 171/var(--tw-ring-opacity))}.focus\:ring-green-300:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(175 211 130/var(--tw-ring-opacity))}.focus\:ring-green-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(73 109 28/var(--tw-ring-opacity))}.focus\:ring-primary-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}.focus\:ring-red-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 154 154/var(--tw-ring-opacity))}.group:hover .group-hover\:scale-110{--tw-scale-x:1.1;--tw-scale-y:1.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))}.group:hover .group-hover\:text-blue-500{--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:border-red-500{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:bg-red-50{--tw-bg-opacity:1;background-color:rgb(255 230 230/var(--tw-bg-opacity))}.group.has-error .group-\[\.has-error\]\:text-red-900{--tw-text-opacity:1;color:rgb(51 1 1/var(--tw-text-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:placeholder-red-700::placeholder{--tw-placeholder-opacity:1;color:rgb(153 2 2/var(--tw-placeholder-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:border-red-500:focus{--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error .group-\[\.has-error\]\:focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(255 3 3/var(--tw-ring-opacity))}:is(.dark .dark\:block){display:block}:is(.dark .dark\:hidden){display:none}:is(.dark .dark\:divide-gray-600)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(75 85 99/var(--tw-divide-opacity))}:is(.dark .dark\:border-blue-500){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-500){--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-600){--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-700){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}:is(.dark .dark\:border-gray-900){--tw-border-opacity:1;border-color:rgb(17 24 39/var(--tw-border-opacity))}:is(.dark .dark\:border-transparent){border-color:#0000}:is(.dark .dark\:bg-blue-600){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-700){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:bg-blue-900){--tw-bg-opacity:1;background-color:rgb(0 31 47/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-600){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:bg-gray-800\/50){background-color:#1f293780}:is(.dark .dark\:bg-gray-900){--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-600){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-700){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:bg-green-900){--tw-bg-opacity:1;background-color:rgb(24 36 9/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-700){--tw-bg-opacity:1;background-color:rgb(153 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:bg-red-900){--tw-bg-opacity:1;background-color:rgb(51 1 1/var(--tw-bg-opacity))}:is(.dark .dark\:bg-yellow-900){--tw-bg-opacity:1;background-color:rgb(99 49 18/var(--tw-bg-opacity))}:is(.dark .dark\:bg-opacity-80){--tw-bg-opacity:0.8}:is(.dark .dark\:text-blue-200){--tw-text-opacity:1;color:rgb(153 215 247/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-300){--tw-text-opacity:1;color:rgb(102 196 242/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-400){--tw-text-opacity:1;color:rgb(51 176 238/var(--tw-text-opacity))}:is(.dark .dark\:text-blue-500){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-100){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-200){--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-300){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-400){--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-50){--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}:is(.dark .dark\:text-gray-500){--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}:is(.dark .dark\:text-green-300){--tw-text-opacity:1;color:rgb(175 211 130/var(--tw-text-opacity))}:is(.dark .dark\:text-red-300){--tw-text-opacity:1;color:rgb(255 104 104/var(--tw-text-opacity))}:is(.dark .dark\:text-red-400){--tw-text-opacity:1;color:rgb(255 53 53/var(--tw-text-opacity))}:is(.dark .dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}:is(.dark .dark\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:text-yellow-300){--tw-text-opacity:1;color:rgb(250 202 21/var(--tw-text-opacity))}:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:placeholder-gray-400)::placeholder{--tw-placeholder-opacity:1;color:rgb(156 163 175/var(--tw-placeholder-opacity))}:is(.dark .dark\:ring-offset-gray-700){--tw-ring-offset-color:#374151}:is(.dark .dark\:ring-offset-gray-800){--tw-ring-offset-color:#1f2937}:is(.dark .dark\:hover\:bg-blue-600:hover){--tw-bg-opacity:1;background-color:rgb(0 125 187/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-blue-700:hover){--tw-bg-opacity:1;background-color:rgb(0 94 140/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-600:hover){--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-700:hover){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-gray-800:hover){--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-600:hover){--tw-bg-opacity:1;background-color:rgb(97 145 37/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-green-700:hover){--tw-bg-opacity:1;background-color:rgb(73 109 28/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:bg-red-600:hover){--tw-bg-opacity:1;background-color:rgb(204 2 2/var(--tw-bg-opacity))}:is(.dark .dark\:hover\:text-blue-500:hover){--tw-text-opacity:1;color:rgb(0 156 234/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-100:hover){--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-gray-300:hover){--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}:is(.dark .dark\:hover\:text-white:hover){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:border-blue-500:focus){--tw-border-opacity:1;border-color:rgb(0 156 234/var(--tw-border-opacity))}:is(.dark .dark\:focus\:border-primary-500:focus){--tw-border-opacity:1;border-color:rgb(121 181 46/var(--tw-border-opacity))}:is(.dark .dark\:focus\:text-white:focus){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}:is(.dark .dark\:focus\:ring-blue-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 156 234/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 125 187/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-blue-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(0 62 94/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-gray-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(75 85 99/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-green-800:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(48 72 18/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-500:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(121 181 46/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-primary-600:focus){--tw-ring-opacity:1;--tw-ring-color:rgb(97 145 37/var(--tw-ring-opacity))}:is(.dark .dark\:focus\:ring-offset-gray-700:focus){--tw-ring-offset-color:#374151}:is(.dark .group:hover .dark\:group-hover\:text-white){--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:border-red-500){--tw-border-opacity:1;border-color:rgb(255 3 3/var(--tw-border-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:bg-gray-700){--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:text-red-500){--tw-text-opacity:1;color:rgb(255 3 3/var(--tw-text-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}.group.has-error :is(.dark .group-\[\.has-error\]\:dark\:placeholder-red-500)::placeholder{--tw-placeholder-opacity:1;color:rgb(255 3 3/var(--tw-placeholder-opacity))}@media (min-width:640px){.sm\:block{display:block}.sm\:rounded-lg{border-radius:.5rem}.sm\:p-6{padding:1.5rem}.sm\:py-5{padding-top:1.25rem;padding-bottom:1.25rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:ml-2{margin-left:.5rem}.md\:mr-24{margin-right:6rem}.md\:table-cell{display:table-cell}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-center{justify-content:center}.md\:space-x-3>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(.75rem*var(--tw-space-x-reverse));margin-left:calc(.75rem*(1 - var(--tw-space-x-reverse)))}.md\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.md\:p-12{padding:3rem}}@media (min-width:1024px){.lg\:block{display:block}.lg\:table-cell{display:table-cell}.lg\:hidden{display:none}.lg\:w-96{width:24rem}.lg\:-translate-x-full{--tw-translate-x:-100%}.lg\:-translate-x-full,.lg\:translate-x-0{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))}.lg\:translate-x-0{--tw-translate-x:0px}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:justify-end{justify-content:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-right:calc(1rem*var(--tw-space-x-reverse));margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)))}.lg\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}.lg\:px-5{padding-left:1.25rem;padding-right:1.25rem}.lg\:pl-3{padding-left:.75rem}.lg\:pl-64{padding-left:16rem}}.\[\&\.active\]\:bg-primary-300.active{--tw-bg-opacity:1;background-color:rgb(175 211 130/var(--tw-bg-opacity))}.\[\&\.active\]\:bg-primary-500.active{--tw-bg-opacity:1;background-color:rgb(121 181 46/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))}
\ No newline at end of file
diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
index 734a3aac..c5a9c0bc 100644
--- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj
+++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj
@@ -41,6 +41,7 @@
wrap-entity
wrap-form-4xx-2
wrap-schema-decode]]
+ [auto-ap.time :as atime]
[auto-ap.utils :refer [dollars=]]
[bidi.bidi :as bidi]
[clojure.string :as str]
@@ -258,33 +259,31 @@
(set))
bank-account-id))
+(defn validate-transaction-rule [form-params]
+ (doseq [[{:transaction-rule-account/keys [account location]} i] (map vector (:transaction-rule/accounts form-params) (range))
+ :let [account-location (pull-attr (dc/db conn) :account/location account)]
+ :when (and account-location (not= account-location location))]
+ (field-validation-error (str "must be " account-location)
+ [:transaction-rule/accounts i :transaction-rule-account/location]
+ :form form-params))
+
+ (let [total (reduce + 0.0 (map :transaction-rule-account/percentage (:transaction-rule/accounts form-params)))]
+ (when-not (dollars= 1.0 total)
+ (form-validation-error (format "Expense accounts total (%d%%) must add to 100%%" (int (* 100.0 total)))
+ :form form-params)))
+
+ (when (and (:transaction-rule/bank-account form-params)
+ (not (bank-account-belongs-to-client? (:transaction-rule/bank-account form-params)
+ (:transaction-rule/client form-params))))
+ (field-validation-error "does not belong to client"
+ [:transaction-rule/bank-account]
+ :form form-params)))
+
(defn transaction-rule-save [{:keys [form-params request-method identity] :as request}]
+ (validate-transaction-rule form-params)
(let [entity (cond-> form-params
(= :post request-method) (assoc :db/id "new")
true (assoc :transaction-rule/note (entity->note form-params)))
- _ (doseq [[{:transaction-rule-account/keys [account location]} i] (map vector (:transaction-rule/accounts entity) (range))
- :let [account-location (pull-attr (dc/db conn) :account/location account)]
- :when (and account-location (not= account-location location))]
- (field-validation-error (str "must be " account-location)
- [:transaction-rule/accounts i :transaction-rule-account/location]
- :form form-params))
-
- total (reduce +
- 0.0
- (map :transaction-rule-account/percentage
- (:transaction-rule/accounts entity)))
- _ (when-not (dollars= 1.0 total)
- (form-validation-error (format "Expense accounts total (%d%%) must add to 100%%" (int (* 100.0 total)))
- :form form-params))
-
- _ (when (and (:transaction-rule/bank-account entity)
- (not (bank-account-belongs-to-client? (:transaction-rule/bank-account entity)
- (:transaction-rule/client entity))))
- (field-validation-error "does not belong to client"
- [:transaction-rule/bank-account]
- :form form-params))
-
-
{:keys [tempids]} (audit-transact [[:upsert-entity entity]]
(:identity request))
updated-rule (dc/pull (dc/db conn)
@@ -295,7 +294,112 @@
:headers (cond-> {"hx-trigger" "modalclose"}
(= :post request-method) (assoc "hx-retarget" "#entity-table tbody"
"hx-reswap" "afterbegin")
- (= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule)))))))
+ (= :put request-method) (assoc "hx-retarget" (format "#entity-table tr[data-id=\"%d\"]" (:db/id updated-rule))
+ "hx-reswap" "outerHTML")))))
+
+
+
+(def transaction-read '[{:transaction/client [:client/name]
+ :transaction/bank-account [:bank-account/name]}
+ :transaction/description-original
+ [:transaction/date :xform clj-time.coerce/from-date]])
+
+(defn transaction-rule-test [{:keys [form-params request-method identity] :as request
+ {:transaction-rule/keys [description client bank-account amount-lte amount-gte dom-lte dom-gte yodlee-merchant]} :form-params}]
+ (validate-transaction-rule form-params)
+ (let [valid-clients (extract-client-ids (:clients request)
+ client)
+ query (cond-> {:query {:find ['(pull ?e read)]
+ :in ['$ 'read]
+ :where []}
+ :args [(dc/db conn) transaction-read]}
+ description
+ (merge-query {:query {:in ['?descr]
+ :where ['[(iol-ion.query/->pattern ?descr) ?description-regex]]}
+ :args [description]})
+
+ valid-clients
+ (merge-query {:query {:in ['[?xx ...]]
+ :where ['[?e :transaction/client ?xx]]}
+ :args [(set valid-clients)]})
+
+ bank-account
+ (merge-query {:query {:in ['?bank-account-id]
+ :where ['[?e :transaction/bank-account ?bank-account-id]]}
+ :args [bank-account]})
+
+ description
+ (merge-query {:query {:where ['[?e :transaction/description-original ?do]
+ '[(re-find ?description-regex ?do)]]}})
+
+ amount-gte
+ (merge-query {:query {:in ['?amount-gte]
+ :where ['[?e :transaction/amount ?ta]
+ '[(>= ?ta ?amount-gte)]]}
+ :args [amount-gte]})
+
+ amount-lte
+ (merge-query {:query {:in ['?amount-lte]
+ :where ['[?e :transaction/amount ?ta]
+ '[(<= ?ta ?amount-lte)]]}
+ :args [amount-lte]})
+
+ dom-lte
+ (merge-query {:query {:in ['?dom-lte]
+ :where ['[?e :transaction/date ?transaction-date]
+ '[(iol-ion.query/dom ?transaction-date) ?dom]
+ '[(<= ?dom ?dom-lte)]]}
+ :args [dom-lte]})
+
+ dom-gte
+ (merge-query {:query {:in ['?dom-gte]
+ :where ['[?e :transaction/date ?transaction-date]
+ '[(iol-ion.query/dom ?transaction-date) ?dom]
+ '[(>= ?dom ?dom-gte)]]}
+ :args [dom-gte]})
+
+ client
+ (merge-query {:query {:in ['?client-id]
+ :where ['[?e :transaction/client ?client-id]]}
+ :args [client]})
+
+
+ true
+ (merge-query {:query {:where ['[?e :transaction/id]]}}))
+ results (->>
+ (query2 query)
+ (map first))]
+
+ (html-response
+ (com/modal-card {:class "fade-in transition duration-300"}
+ [:div.p-2.flex.space-x-4 [:div "Transaction Rule"] [:div ">"] [:div "Results"] [:div.ml-4.relative (com/badge {} (count results))]]
+ (com/data-grid
+ {:headers [(com/data-grid-header {} "Client")
+ (com/data-grid-header {} "Bank")
+ (com/data-grid-header {} "Date")
+ (com/data-grid-header {} "Description")]}
+ (for [r (take 15 results)]
+ (com/data-grid-row
+ {}
+ (com/data-grid-cell {} (-> r :transaction/client :client/name))
+ (com/data-grid-cell {} (-> r :transaction/bank-account :bank-account/name))
+ (com/data-grid-cell {} (some-> r :transaction/date (atime/unparse-local atime/normal-date)))
+ (com/data-grid-cell {} (some-> r :transaction/description-original )))))
+ [:div
+ (com/button (cond-> {:color :primary
+ :hx-vals (hx/json (:raw-form-params request))
+ }
+ (:db/id form-params) (assoc :hx-put (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-save))
+ (not (:db/id form-params)) (assoc :hx-post (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-save)))
+ "Save")
+ (com/button {:hx-vals (hx/json (:raw-form-params request))
+ :hx-put (bidi/path-for ssr-routes/only-routes
+ :admin-transaction-rule-filled-account
+ )} "Back")
+ ])
+ :headers (-> {}
+ (assoc "hx-retarget" ".modal-card")
+ (assoc "hx-reswap" "outerHTML")))))
@@ -366,6 +470,7 @@
:x-data (hx/json {:location (fc/field-value)})}
[:div {:hx-trigger "changed"
:hx-target "next *"
+ :hx-swap "outerHTML"
:hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || '', value: event.detail.location}" (fc/field-name) )
:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select)
:x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data) )"}]
@@ -554,7 +659,11 @@
]]
[:div
(com/form-errors {:errors (:errors fc/*form-errors*)})
- (com/validated-save-button {:errors form-errors} "Save rule")])])))
+ (com/validated-save-button {:errors form-errors} "Save rule")
+ (com/validated-save-button {:errors form-errors :color :secondary
+ :hx-post (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-test)}
+
+ "Test rule")])])))
(defn new-account [{{:keys [client-id index]} :query-params}]
@@ -607,6 +716,7 @@
[:transaction-rule-account/percentage percentage])]]))
(defn transaction-dialog [{:keys [entity form-params form-errors]}]
+ (clojure.pprint/pprint form-params)
(modal-response (dialog* {:entity entity
:form-params (or (when (seq form-params)
form-params)
@@ -649,6 +759,19 @@
(wrap-nested-form-params)
(wrap-form-4xx-2 (-> transaction-dialog
(wrap-entity [:form-params :db/id] default-read))))
+
+ :admin-transaction-rule-test (-> transaction-rule-test
+ (wrap-entity [:form-params :db/id] default-read)
+ (wrap-schema-decode :form-schema form-schema)
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 (-> transaction-dialog
+ (wrap-entity [:form-params :db/id] default-read))))
+ :admin-transaction-rule-filled-account (-> transaction-dialog
+ (wrap-entity [:form-params :db/id] default-read)
+ (wrap-schema-decode :form-schema form-schema)
+ (wrap-nested-form-params)
+ (wrap-form-4xx-2 (-> transaction-dialog
+ (wrap-entity [:form-params :db/id] default-read))))
:admin-transaction-rule-edit-dialog (-> transaction-dialog
(wrap-entity [:route-params :db/id] default-read)
(wrap-schema-decode :route-schema [:map [:db/id entity-id]]))
diff --git a/src/clj/auto_ap/ssr/components.clj b/src/clj/auto_ap/ssr/components.clj
index 8187030d..7e01d7c7 100644
--- a/src/clj/auto_ap/ssr/components.clj
+++ b/src/clj/auto_ap/ssr/components.clj
@@ -31,7 +31,7 @@
(def date-input inputs/date-input-)
(def hidden inputs/hidden-)
(def select inputs/select-)
-(def typeahead inputs/tytypeahead-
+(def typeahead inputs/typeahead-)
(def field-errors inputs/field-errors-)
(def field inputs/field-)
(def validated-field inputs/validated-field-)
diff --git a/src/clj/auto_ap/ssr/components/aside.clj b/src/clj/auto_ap/ssr/components/aside.clj
index 7cad9ff8..075e7163 100644
--- a/src/clj/auto_ap/ssr/components/aside.clj
+++ b/src/clj/auto_ap/ssr/components/aside.clj
@@ -214,8 +214,7 @@
[:li
(menu-button- {:icon svg/cog
- :href (bidi/path-for client-routes/routes
- :admin-rules)}
+ :href (bidi/path-for ssr-routes/only-routes :admin-transaction-rules)}
"Rules")]
[:li
diff --git a/src/clj/auto_ap/ssr/components/buttons.clj b/src/clj/auto_ap/ssr/components/buttons.clj
index d23281d7..ee276f37 100644
--- a/src/clj/auto_ap/ssr/components/buttons.clj
+++ b/src/clj/auto_ap/ssr/components/buttons.clj
@@ -176,7 +176,7 @@
(defn validated-save-button- [{:keys [errors class] :as params} & children]
- (button- (-> {:color :primary
+ (button- (-> {:color (or (:color params) :primary)
:type "submit" :class (cond-> (or class "")
true (hh/add-class "w-32")
(seq errors) (hh/add-class "animate-shake"))}
@@ -184,5 +184,4 @@
(dissoc :errors))
(if (seq children)
children
- "Save"))
- )
+ "Save")))
diff --git a/src/clj/auto_ap/ssr/components/dialog.clj b/src/clj/auto_ap/ssr/components/dialog.clj
index e6fc4e47..572a98d4 100644
--- a/src/clj/auto_ap/ssr/components/dialog.clj
+++ b/src/clj/auto_ap/ssr/components/dialog.clj
@@ -9,10 +9,10 @@
children])
(defn modal-card- [params header content footer]
- [:div#modal-card (update params
+ [:div (update params
:class (fn [c] (-> c
(or "")
- (hh/add-class "w-full p-4 h-full")
+ (hh/add-class "w-full p-4 h-full modal-card")
)))
[:div {:class "bg-white rounded-lg shadow dark:bg-gray-700 dark:text-white modal-content w-full flex flex-col h-full"}
[:div {:class "flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600 shrink-0"} header]
diff --git a/src/clj/auto_ap/ssr/nested_form_params.clj b/src/clj/auto_ap/ssr/nested_form_params.clj
index 1fa4648e..83286aa5 100644
--- a/src/clj/auto_ap/ssr/nested_form_params.clj
+++ b/src/clj/auto_ap/ssr/nested_form_params.clj
@@ -64,7 +64,9 @@
(nested-params-request request {}))
([request options]
(let [parse (:key-parser options parse-nested-keys)]
- (update-in request [:form-params] nest-params parse))))
+ (-> request
+ (assoc :raw-form-params (:form-params request))
+ (update-in [:form-params] nest-params parse)))))
(defn wrap-nested-form-params
"Middleware to converts a flat map of parameters into a nested map.
diff --git a/src/clj/auto_ap/ssr/pos/common.clj b/src/clj/auto_ap/ssr/pos/common.clj
index ef37e0af..97022a42 100644
--- a/src/clj/auto_ap/ssr/pos/common.clj
+++ b/src/clj/auto_ap/ssr/pos/common.clj
@@ -3,9 +3,6 @@
[auto-ap.time :as atime]
[auto-ap.ssr.svg :as svg]))
-;; TODO make date-input take clj date
-;; TODO make total fields take decimals
-
(defn date-range-field* [request]
[:div#date-range {}
(com/field {:label "Date Range"}
diff --git a/src/clj/auto_ap/ssr/ui.clj b/src/clj/auto_ap/ssr/ui.clj
index 68e01e9a..f0fe6ed0 100644
--- a/src/clj/auto_ap/ssr/ui.clj
+++ b/src/clj/auto_ap/ssr/ui.clj
@@ -33,7 +33,9 @@
:crossorigin= "anonymous"}]
[:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
:crossorigin= "anonymous"}])
-
+
+ [:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/ext/class-tools.js" :crossorigin= "anonymous"}]
+
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
[:script {:src "/js/htmx-disable.js"}]
[:script {:type "text/javascript", :src "https://cdn.yodlee.com/fastlink/v4/initialize.js", :async "async"}]]
@@ -62,7 +64,7 @@ input[type=number] {
} "]
- [:body {:hx-ext "disable-submit"}
+ [:body {:hx-ext "disable-submit, class-tools"}
contents
[:script {:src "/js/flowbite.min.js"}]
diff --git a/src/clj/auto_ap/ssr/utils.clj b/src/clj/auto_ap/ssr/utils.clj
index 80479333..13b53c0d 100644
--- a/src/clj/auto_ap/ssr/utils.clj
+++ b/src/clj/auto_ap/ssr/utils.clj
@@ -37,6 +37,15 @@
(assoc-in [:headers "hx-retarget"] "#modal-content")
(assoc-in [:headers "hx-reswap"] "innerHTML"))))))
+(defn next-step-modal-response [hiccup & {:as opts}]
+ (apply html-response
+ (into
+ [hiccup]
+ (mapcat identity
+ (-> opts
+ (assoc-in [:headers "hx-retarget"] "#modal-content")
+ (assoc-in [:headers "hx-reswap"] "innerHTML"))))))
+
(defn wrap-error-response [handler]
(fn [request]
(try
diff --git a/src/cljc/auto_ap/ssr_routes.cljc b/src/cljc/auto_ap/ssr_routes.cljc
index 7da78c5e..bddbcebc 100644
--- a/src/cljc/auto_ap/ssr_routes.cljc
+++ b/src/cljc/auto_ap/ssr_routes.cljc
@@ -37,9 +37,11 @@
:put :admin-transaction-rule-save
:post :admin-transaction-rule-save}
"/table" :admin-transaction-rule-table
+ "/account/filled" :admin-transaction-rule-filled-account
"/account/new" :admin-transaction-rule-new-account
"/account/location-select" :admin-transaction-rule-location-select
"/account/typeahead" :admin-transaction-rule-account-typeahead
+ "/test" :admin-transaction-rule-test
"/new" {:get :admin-transaction-rule-new-dialog}
[[#"\d+" :db/id] "/edit"] :admin-transaction-rule-edit-dialog
}}
From 58c34715e2b2910051b703ded162c615f96c3db9 Mon Sep 17 00:00:00 2001
From: Bryce
Date: Thu, 26 Oct 2023 21:24:35 -0700
Subject: [PATCH 34/34] moves youngs market to RNDC
---
src/clj/auto_ap/parse/templates.clj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/clj/auto_ap/parse/templates.clj b/src/clj/auto_ap/parse/templates.clj
index ab43ca87..181e6639 100644
--- a/src/clj/auto_ap/parse/templates.clj
+++ b/src/clj/auto_ap/parse/templates.clj
@@ -254,7 +254,7 @@
:total [:trim-commas-and-negate nil]}}
;; Young's Market Co new statement
- {:vendor "Youngs Market"
+ {:vendor "RNDC"
:keywords [#"(YOUNG'S MARKET COMPANY|Young.*Statement)"]
:extract {:date #"([0-9]+/[0-9]+/[0-9]+)"
:customer-identifier #"Customer Name +([\w ]+)"
@@ -266,7 +266,7 @@
:multi-match? #"^[0-9]+.*\$?([0-9,]+\.[0-9]+).*\$?([0-9,]+\.[0-9]+)"}
;; Young's Market Co - INVOICE
- {:vendor "Youngs Market"
+ {:vendor "RNDC"
:keywords [#"P.O.Box 743564"]
:extract {:date #"(?:INVOICE|CREDIT) DATE\n(?:.*?)(\S+)\n"
#_#_:customer-identifier #"(?:INVOICE|CREDIT) DATE\n [0-9]+\s+(.*?)\s{2,}"