progress towards sales.

This commit is contained in:
2023-09-26 14:30:21 -07:00
parent 94ef7ebf03
commit 160c289f03
12 changed files with 299 additions and 73 deletions

View File

@@ -1095,6 +1095,14 @@ input:checked + .toggle-bg {
top: 1.25rem; top: 1.25rem;
} }
.left-1\/2 {
left: 50%;
}
.top-2\/4 {
top: 50%;
}
.z-10 { .z-10 {
z-index: 10; z-index: 10;
} }
@@ -1324,6 +1332,10 @@ input:checked + .toggle-bg {
height: 100vh; height: 100vh;
} }
.h-56 {
height: 14rem;
}
.max-h-96 { .max-h-96 {
max-height: 24rem; max-height: 24rem;
} }
@@ -1348,6 +1360,10 @@ input:checked + .toggle-bg {
width: 1rem; width: 1rem;
} }
.w-48 {
width: 12rem;
}
.w-5 { .w-5 {
width: 1.25rem; width: 1.25rem;
} }
@@ -1368,8 +1384,8 @@ input:checked + .toggle-bg {
width: 100%; width: 100%;
} }
.w-48 { .w-56 {
width: 12rem; width: 14rem;
} }
.max-w-2xl { .max-w-2xl {
@@ -1437,6 +1453,16 @@ 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)); 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-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-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));
}
.rotate-180 { .rotate-180 {
--tw-rotate: 180deg; --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: 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));
@@ -1460,6 +1486,16 @@ input:checked + .toggle-bg {
animation: spin 1s linear infinite; animation: spin 1s linear infinite;
} }
@keyframes pulse {
50% {
opacity: .5;
}
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.cursor-default { .cursor-default {
cursor: default; cursor: default;
} }
@@ -1480,6 +1516,12 @@ input:checked + .toggle-bg {
list-style-type: none; list-style-type: none;
} }
.appearance-none {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.grid-cols-3 { .grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
} }
@@ -1670,6 +1712,10 @@ input:checked + .toggle-bg {
border-radius: 0.5rem; border-radius: 0.5rem;
} }
.rounded-md {
border-radius: 0.375rem;
}
.rounded-l-lg { .rounded-l-lg {
border-top-left-radius: 0.5rem; border-top-left-radius: 0.5rem;
border-bottom-left-radius: 0.5rem; border-bottom-left-radius: 0.5rem;
@@ -1876,11 +1922,6 @@ input:checked + .toggle-bg {
--tw-bg-opacity: 0.5; --tw-bg-opacity: 0.5;
} }
.object-contain {
-o-object-fit: contain;
object-fit: contain;
}
.p-1 { .p-1 {
padding: 0.25rem; padding: 0.25rem;
} }
@@ -2095,6 +2136,10 @@ input:checked + .toggle-bg {
line-height: 1.25; line-height: 1.25;
} }
.leading-none {
line-height: 1;
}
.text-black { .text-black {
--tw-text-opacity: 1; --tw-text-opacity: 1;
color: rgb(0 0 0 / var(--tw-text-opacity)); color: rgb(0 0 0 / var(--tw-text-opacity));
@@ -2187,6 +2232,14 @@ input:checked + .toggle-bg {
opacity: 1; opacity: 1;
} }
.opacity-50 {
opacity: 0.5;
}
.opacity-5 {
opacity: 0.05;
}
.shadow { .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: 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); --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
@@ -2493,6 +2546,10 @@ input:checked + .toggle-bg {
text-decoration-line: underline; text-decoration-line: underline;
} }
.focus\:z-10:focus {
z-index: 10;
}
.focus\:border-blue-500:focus { .focus\:border-blue-500:focus {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(0 156 234 / var(--tw-border-opacity)); border-color: rgb(0 156 234 / var(--tw-border-opacity));
@@ -2503,6 +2560,11 @@ input:checked + .toggle-bg {
border-color: rgb(121 181 46 / var(--tw-border-opacity)); border-color: rgb(121 181 46 / var(--tw-border-opacity));
} }
.focus\:text-green-700:focus {
--tw-text-opacity: 1;
color: rgb(73 109 28 / var(--tw-text-opacity));
}
.focus\:outline-none:focus { .focus\:outline-none:focus {
outline: 2px solid transparent; outline: 2px solid transparent;
outline-offset: 2px; outline-offset: 2px;
@@ -2555,6 +2617,11 @@ input:checked + .toggle-bg {
--tw-ring-color: rgb(175 211 130 / var(--tw-ring-opacity)); --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 { .focus\:ring-primary-500:focus {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(121 181 46 / var(--tw-ring-opacity)); --tw-ring-color: rgb(121 181 46 / var(--tw-ring-opacity));
@@ -2766,6 +2833,11 @@ input:checked + .toggle-bg {
color: rgb(250 202 21 / var(--tw-text-opacity)); color: rgb(250 202 21 / var(--tw-text-opacity));
} }
:is(.dark .dark\:text-blue-200) {
--tw-text-opacity: 1;
color: rgb(153 215 247 / var(--tw-text-opacity));
}
:is(.dark .dark\:placeholder-gray-400)::-moz-placeholder { :is(.dark .dark\:placeholder-gray-400)::-moz-placeholder {
--tw-placeholder-opacity: 1; --tw-placeholder-opacity: 1;
color: rgb(156 163 175 / var(--tw-placeholder-opacity)); color: rgb(156 163 175 / var(--tw-placeholder-opacity));
@@ -2776,14 +2848,14 @@ input:checked + .toggle-bg {
color: rgb(156 163 175 / var(--tw-placeholder-opacity)); color: rgb(156 163 175 / var(--tw-placeholder-opacity));
} }
:is(.dark .dark\:ring-offset-gray-800) {
--tw-ring-offset-color: #1F2937;
}
:is(.dark .dark\:ring-offset-gray-700) { :is(.dark .dark\:ring-offset-gray-700) {
--tw-ring-offset-color: #374151; --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) { :is(.dark .dark\:hover\:bg-blue-600:hover) {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(0 125 187 / var(--tw-bg-opacity)); background-color: rgb(0 125 187 / var(--tw-bg-opacity));
@@ -2854,11 +2926,21 @@ input:checked + .toggle-bg {
border-color: rgb(121 181 46 / var(--tw-border-opacity)); 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) { :is(.dark .dark\:focus\:ring-blue-500:focus) {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(0 156 234 / var(--tw-ring-opacity)); --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) { :is(.dark .dark\:focus\:ring-blue-800:focus) {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(0 62 94 / var(--tw-ring-opacity)); --tw-ring-color: rgb(0 62 94 / var(--tw-ring-opacity));
@@ -2869,6 +2951,11 @@ input:checked + .toggle-bg {
--tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity)); --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) { :is(.dark .dark\:focus\:ring-green-800:focus) {
--tw-ring-opacity: 1; --tw-ring-opacity: 1;
--tw-ring-color: rgb(48 72 18 / var(--tw-ring-opacity)); --tw-ring-color: rgb(48 72 18 / var(--tw-ring-opacity));
@@ -2884,11 +2971,6 @@ input:checked + .toggle-bg {
--tw-ring-color: rgb(97 145 37 / var(--tw-ring-opacity)); --tw-ring-color: rgb(97 145 37 / 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-offset-gray-700:focus) { :is(.dark .dark\:focus\:ring-offset-gray-700:focus) {
--tw-ring-offset-color: #374151; --tw-ring-offset-color: #374151;
} }

View File

@@ -18,6 +18,8 @@
(def button-icon buttons/button-icon-) (def button-icon buttons/button-icon-)
(def icon-button buttons/icon-button-) (def icon-button buttons/icon-button-)
(def a-icon-button buttons/a-icon-button-) (def a-icon-button buttons/a-icon-button-)
(def button-group buttons/group-)
(def button-group-button buttons/group-button-)
(def modal dialog/modal-) (def modal dialog/modal-)
(def modal-card dialog/modal-card-) (def modal-card dialog/modal-card-)

View File

@@ -178,8 +178,9 @@
:icon svg/receipt-register-1} :icon svg/receipt-register-1}
"Sales") "Sales")
(sub-menu- {:id "dropdown-sales"} (sub-menu- {:id "dropdown-sales"}
(menu-button- {:href (bidi/path-for client-routes/routes (menu-button- {:href (str (bidi/path-for client-routes/routes
:sales-orders)} "Sales") :pos-sales)
"?date-range=week")} "Sales")
(menu-button- {:href (bidi/path-for client-routes/routes (menu-button- {:href (bidi/path-for client-routes/routes
:expected-deposits)} "Expected Deposits") :expected-deposits)} "Expected Deposits")
#_(menu-button- {:href "Sales"} "Cash Shifts") #_(menu-button- {:href "Sales"} "Cash Shifts")

View File

@@ -46,3 +46,31 @@
(svg/spinner {:class "inline w-4 h-4 text-white"}) (svg/spinner {:class "inline w-4 h-4 text-white"})
[:div.ml-3 "Loading..."]] [:div.ml-3 "Loading..."]]
(into [:div.htmx-indicator-hidden ] children)]) (into [:div.htmx-indicator-hidden ] children)])
(defn group-button- [{:keys [size] :or {size :normal} :as params} & children]
(into [:button (cond-> params
true (assoc :type (or (:type params) "button"))
true (update :class (fn [c]
(cond-> c
true (str " font-medium text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-2 focus:ring-green-700 focus:text-green-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-green-500 dark:focus:text-white")
(= :small size)
(str " text-xs px-3 py-2")
(= :normal size)
(str " text-sm px-4 py-2")
)
))
true (dissoc :size))] children ))
(defn group- [{:keys [name]} & children]
(let [children (-> children
vec
(update-in [0 1 :class] str " rounded-l-lg")
(update-in [(dec (count children)) 1 :class] str " rounded-r-lg"))]
(into [:div {:class "inline-flex rounded-md shadow-sm", :role "group"
: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)))

View File

@@ -69,6 +69,7 @@
:hx-trigger "clientSelected from:body" :hx-trigger "clientSelected from:body"
:hx-swap "outerHTML swap:300ms" :hx-swap "outerHTML swap:300ms"
:id id} :id id}
(content-card- (content-card-
{} {}
[:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"} [:div {:class "flex flex-col px-4 py-3 space-y-3 lg:flex-row lg:items-center lg:justify-between lg:space-y-0 lg:space-x-4 text-gray-800 dark:text-gray-100"}
@@ -97,4 +98,8 @@
:request-method :get) :request-method :get)
"?start=" (* page per-page)) "?start=" (* page per-page))
:hx-target (str "#" id) :hx-target (str "#" id)
:hx-swap "outerHTML show:#app:top"})})))]) :hx-swap "outerHTML show:#app:top"
:hx-indicator (str "#" id)})}))
[: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..."]]])])

View File

@@ -11,28 +11,39 @@
(:allow-blank? params) (conj [:option {:value "" :selected (not (:value params))} ""]))] (:allow-blank? params) (conj [:option {:value "" :selected (not (:value params))} ""]))]
children)) children))
(defn text-input- [params] (defn use-size [size]
(if (= :small size)
(str " " "text-xs p-2")
(str " " "text-sm p-2.25")))
(defn text-input- [{:keys [size] :as params}]
[:input [:input
(update params (-> params
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500") (update
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
(update :class #(str % (use-size size)))
)
]) ])
(defn money-input- [params] (defn money-input- [{:keys [size] :as params}]
[:input [:input
(-> params (-> params
(update (update
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 text-right" :class str " bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 text-right appearance-none"
) )
(update :class #(str % (use-size size)))
(assoc :type "number" (assoc :type "number"
:step "0.01")) :step "0.01")
(dissoc :size))
]) ])
(defn date-input- [params] (defn date-input- [{:keys [size] :as params}]
[:input [:input
(-> params (-> params
(update (update
:class str " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500") :class str " bg-gray-50 border border-gray-300 text-gray-900 rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500")
(assoc :type "date"))]) (assoc :type "date")
(update :class #(str % (use-size size)))
(dissoc :size))])
(defn field- [params & rest] (defn field- [params & rest]
(into (into

View File

@@ -1,6 +1,6 @@
(ns auto-ap.ssr.components.radio) (ns auto-ap.ssr.components.radio)
(defn radio- [{:keys [options name title]}] (defn radio- [{:keys [options name title size] :or {size :medium}}]
[:h3 {:class "mb-4 font-semibold text-gray-900 dark:text-white"} title] [: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 "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"}
(for [{:keys [value content]} options] (for [{:keys [value content]} options]
@@ -9,5 +9,19 @@
[:input {:id (str "list-" name "-" value) [:input {:id (str "list-" name "-" value)
:type "radio", :type "radio",
:value value :value value
:name name :class "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"}] :name name
[:label {:for (str "list-" name "-" value) :class "w-full py-3 ml-2 text-sm font-medium text-gray-900 dark:text-gray-300"} content]]])]) :class
(cond-> "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-700 dark:focus:ring-offset-gray-700 focus:ring-2 dark:bg-gray-600 dark:border-gray-500"
(= size :small)
(str " " "text-xs")
(= size :medium)
(str " " "text-sm"))}]
[:label {:for (str "list-" name "-" value)
:class
(cond-> "w-full ml-2 font-medium text-gray-900 dark:text-gray-300"
(= size :small)
(str " " "text-xs py-2")
(= size :medium)
(str " " "text-sm py-3"))} content]]])])

View File

@@ -10,7 +10,9 @@
[clojure.string :as str] [clojure.string :as str]
[auto-ap.ssr.svg :as svg] [auto-ap.ssr.svg :as svg]
[unilog.context :as lc] [unilog.context :as lc]
[com.brunobonacci.mulog :as mu])) [com.brunobonacci.mulog :as mu]
[auto-ap.time :as atime]
[clj-time.core :as time]))
(defn row* [gridspec user entity {:keys [flash? delete-after-settle? params] :as options}] (defn row* [gridspec user entity {:keys [flash? delete-after-settle? params] :as options}]
(let [cells (->> gridspec (let [cells (->> gridspec
@@ -72,15 +74,16 @@
[entities total] ((:fetch-page grid-spec) [entities total] ((:fetch-page grid-spec)
user user
params)] params)]
(com/data-grid-card {:id (:id grid-spec) (com/data-grid-card {:id (:id grid-spec)
:title (:title grid-spec) :title (:title grid-spec)
:route (:route grid-spec) :route (:route grid-spec)
:start start :start start
:per-page per-page :per-page per-page
:total total :total total
:subtitle [:div.flex.items-center.gap-2 :subtitle [:div.flex.items-center.gap-2
[:span (format "Total %s: %d, " (:entity-name grid-spec) total)] [:span (format "Total %s: %d, " (:entity-name grid-spec) total)]
(sort-by-list grid-spec sort)] (sort-by-list grid-spec sort)]
:action-buttons ((:action-buttons grid-spec) user params) :action-buttons ((:action-buttons grid-spec) user params)
:rows (for [entity entities] :rows (for [entity entities]
(row* grid-spec user entity {:flash? (= flash-id ((:id-fn grid-spec) entity)) :params params})) (row* grid-spec user entity {:flash? (= flash-id ((:id-fn grid-spec) entity)) :params params}))
@@ -174,9 +177,33 @@
(update :sort sort->query) (update :sort sort->query)
(url/map->query))) (url/map->query)))
(defn use-date-range [query-params date-range]
(condp = date-range
"week"
(assoc query-params
:start-date (atime/unparse-local (time/plus (time/now) (time/days -7)) atime/iso-date)
:end-date (atime/unparse-local (time/now) atime/iso-date))
"month"
(assoc query-params
:start-date (atime/unparse-local (time/plus (time/now) (time/months -1)) atime/iso-date)
:end-date (atime/unparse-local (time/now) atime/iso-date))
"year"
(assoc query-params
:start-date (atime/unparse-local (time/plus (time/now) (time/years -1)) atime/iso-date)
:end-date (atime/unparse-local (time/now) atime/iso-date))
"all"
(assoc query-params
:start-date (atime/unparse-local (time/plus (time/now) (time/years -3)) atime/iso-date)
:end-date (atime/unparse-local (time/now) atime/iso-date))
query-params))
(defn extract-params [grid-spec {:keys [query-params hx-query-params identity session] :as request}] (defn extract-params [grid-spec {:keys [query-params hx-query-params identity session] :as request}]
(let [{hx-start "start" hx-per-page "per-page" hx-sort "sort" } hx-query-params (let [{hx-start "start" hx-per-page "per-page" hx-sort "sort" } hx-query-params
{q-start "start" q-per-page "per-page" q-sort "sort" q-toggle-sort "toggle-sort" q-remove-sort "remove-sort"} query-params {q-start "start" q-per-page "per-page" q-sort "sort" q-toggle-sort "toggle-sort" q-remove-sort "remove-sort" date-range "date-range"} query-params
raw-query-params (merge (or hx-query-params {}) query-params) raw-query-params (merge (or hx-query-params {}) query-params)
parsed-query-params (cond-> (into {} (map (fn [[k v]] [(keyword k) v]) raw-query-params)) parsed-query-params (cond-> (into {} (map (fn [[k v]] [(keyword k) v]) raw-query-params))
@@ -184,11 +211,12 @@
q-start (assoc :start (some-> q-start not-empty (Long/parseLong ))) q-start (assoc :start (some-> q-start not-empty (Long/parseLong )))
hx-per-page (assoc :per-page (some-> hx-per-page not-empty (Long/parseLong ))) hx-per-page (assoc :per-page (some-> hx-per-page not-empty (Long/parseLong )))
q-per-page (assoc :per-page (some-> q-per-page not-empty (Long/parseLong ))) q-per-page (assoc :per-page (some-> q-per-page not-empty (Long/parseLong )))
hx-sort (assoc :sort (doto (parse-sort grid-spec hx-sort) println)) hx-sort (assoc :sort (parse-sort grid-spec hx-sort))
q-sort (assoc :sort (doto (parse-sort grid-spec q-sort) println )) q-sort (assoc :sort (parse-sort grid-spec q-sort))
(not-empty q-toggle-sort) (update :sort #(toggle-sort grid-spec % q-toggle-sort) ) (not-empty q-toggle-sort) (update :sort #(toggle-sort grid-spec % q-toggle-sort) )
(not-empty q-remove-sort) (update :sort (fn [s] (filter (comp (complement #{q-remove-sort}) :sort-key) s)) ) (not-empty q-remove-sort) (update :sort (fn [s] (filter (comp (complement #{q-remove-sort}) :sort-key) s)) )
true (dissoc :toggle-sort :remove-sort))] date-range (use-date-range date-range)
true (dissoc :toggle-sort :remove-sort :date-range))]
{:raw-query-params raw-query-params {:raw-query-params raw-query-params
:parsed-query-params parsed-query-params :parsed-query-params parsed-query-params
:client-selection (:client-selection (:session request)) :client-selection (:client-selection (:session request))
@@ -202,7 +230,9 @@
grid-spec grid-spec
identity identity
params) params)
:headers {"hx-push-url" (str "?" (params->query-string params))}))) :headers {"hx-push-url" (str "?" (params->query-string params))}
:oob (when-let [oob-render (:oob-render grid-spec)]
(oob-render identity params)))))
(defn page [grid-spec {:keys [identity] :as request}] (defn page [grid-spec {:keys [identity] :as request}]
(let [params (extract-params grid-spec request)] (let [params (extract-params grid-spec request)]
@@ -210,7 +240,7 @@
request request
(com/page {:nav (:nav grid-spec) (com/page {:nav (:nav grid-spec)
:page-specific (when-let [page-specific-nav (:page-specific-nav grid-spec)] :page-specific (when-let [page-specific-nav (:page-specific-nav grid-spec)]
(page-specific-nav params)) [:div#page-specific-nav (page-specific-nav params)])
:client-selection (:client-selection (:session request)) :client-selection (:client-selection (:session request))
:clients (:clients request) :clients (:clients request)
:client (:client request) :client (:client request)

View File

@@ -14,40 +14,65 @@
;; TODO refunds ;; TODO refunds
;; TODO expected deposits ;; TODO expected deposits
;; TODO loading screen ;; TODO loading screen
;; TODO default date range
;; always should be fast ;; always should be fast
;; make params parsing composable
(defn filters [params] (defn date-range-field* [params]
[:form {"hx-trigger" "change delay:1000ms" [:div#date-range {}
"hx-get" (bidi/path-for ssr-routes/only-routes (com/field {:label "Date Range"}
:pos-sales-table) [:div.space-y-4
"hx-target" "#sales-table"} [:div
[:div.space-y-6 (com/button-group {:name "date-range"}
[:div (com/button-group-button {:size :small :value "all" :hx-trigger "click"} "All")
(com/field {:label "Starting"} (com/button-group-button {:size :small :value "week" :hx-trigger "click"} "Week")
(com/button-group-button {:size :small :value "month" :hx-trigger "click"} "Month")
(com/button-group-button {:size :small :value "year" :hx-trigger "click"} "Year"))
]
[:div.flex.space-x-1.items-baseline
(com/date-input {:name "start-date" (com/date-input {:name "start-date"
:value (:start-date (:parsed-query-params params)) :value (:start-date (:parsed-query-params params))
:placeholder "Date"}))] :placeholder "Date"
[:div :size :small})
(com/field {:label "Ending"}
(com/date-input {:name "end-date" (com/date-input {:name "end-date"
:value (:end-date (:parsed-query-params params)) :value (:end-date (:parsed-query-params params))
:placeholder "Date"}))] :placeholder "Date"
:size :small})]]
)])
(defn filters [params]
[:form {"hx-trigger" "change delay:500ms, keyup from:.hot-filter delay:1000ms"
"hx-get" (bidi/path-for ssr-routes/only-routes
:pos-sales-table)
"hx-target" "#sales-table"
"hx-indicator" "#sales-table"
#_#_:hx-disabled-elt "find fieldset"}
[:fieldset.space-y-6
(date-range-field* params)
[:div [:div
(com/field {:label "Total"} (com/field {:label "Total"}
[:div.flex.space-x-4.items-baseline [:div.flex.space-x-4.items-baseline
(com/money-input {:name "total-gte" (com/money-input {:name "total-gte"
:id "total-gte"
:hx-preserve "true"
:class "hot-filter"
:value (:total-gte (:parsed-query-params params)) :value (:total-gte (:parsed-query-params params))
:placeholder "0.01"}) :placeholder "0.01"
:size :small})
[:div.align-baseline [:div.align-baseline
"to"] "to"]
(com/money-input {:name "total-lte" (com/money-input {:name "total-lte"
:hx-preserve "true"
:id "total-lte"
:class "hot-filter"
:value (:total-lte (:parsed-query-params params)) :value (:total-lte (:parsed-query-params params))
:placeholder "9999.34"})])] :placeholder "9999.34"
:size :small})])]
[:div [:div
(com/field {:label "Payment Method"} (com/field {:label "Payment Method"}
(com/radio {:name "payment-method" (com/radio {:size :small
:options [{:value "all" :name "payment-method"
:options [{:value "all"
:content "All"} :content "All"}
{:value "cash" {:value "cash"
:content "Cash"} :content "Cash"}
@@ -61,7 +86,8 @@
[:div [:div
(com/field {:label "Processor"} (com/field {:label "Processor"}
(com/radio {:name "processor" (com/radio {:size :small
:name "processor"
:options [{:value "" :options [{:value ""
:content "All"} :content "All"}
{:value "square" {:value "square"
@@ -81,10 +107,14 @@
]}))] ]}))]
[:div [:div
(com/field {:label "Total"} (com/field {:label "Category"}
(com/text-input {:name "category" (com/text-input {:name "category"
:class "hot-filter"
:id "category"
:hx-preserve "true"
:value (:category (:parsed-query-params params)) :value (:category (:parsed-query-params params))
:placeholder "Fries"}))]]]) :placeholder "Fries"
:size :small}))]]])
(defn args->graphql-params [args] (defn args->graphql-params [args]
{:clients (:clients args) {:clients (:clients args)
@@ -93,12 +123,12 @@
:per-page (:per-page (:parsed-query-params args)) :per-page (:per-page (:parsed-query-params args))
:category (not-empty (:category (:parsed-query-params args))) :category (not-empty (:category (:parsed-query-params args)))
:date-range {:start (some-> args :date-range {:start (some-> args
:raw-query-params :parsed-query-params
(get "start-date") :start-date
(atime/parse atime/iso-date)) (atime/parse atime/iso-date))
:end (some-> args :end (some-> args
:raw-query-params :parsed-query-params
(get "end-date") :end-date
(atime/parse atime/iso-date))} (atime/parse atime/iso-date))}
:total-gte (some-> args :raw-query-params (get "total-gte") not-empty (#(if (string? %) (Double/parseDouble %) (double %)))) :total-gte (some-> args :raw-query-params (get "total-gte") not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
:total-lte (some-> args :raw-query-params (get "total-lte") not-empty (#(if (string? %) (Double/parseDouble %) (double %)))) :total-lte (some-> args :raw-query-params (get "total-lte") not-empty (#(if (string? %) (Double/parseDouble %) (double %))))
@@ -118,8 +148,10 @@
:id-fn :db/id :id-fn :db/id
:fetch-page (fn [user args] :fetch-page (fn [user args]
(d-sales/get-graphql (d-sales/get-graphql
(args->graphql-params args) (args->graphql-params args)))
)) :oob-render
(fn [user params]
[(assoc-in (date-range-field* params) [1 :hx-swap-oob] true)])
:breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes :breadcrumbs [[:a {:href (bidi/path-for ssr-routes/only-routes
:company)} :company)}
"POS"] "POS"]
@@ -183,7 +215,6 @@
{:key "Payment methods" {:key "Payment methods"
:name "Payment Methods" :name "Payment Methods"
:render (fn [sales-order] :render (fn [sales-order]
(println )
(for [method (->> sales-order :sales-order/charges (map :charge/type-name) set)] (for [method (->> sales-order :sales-order/charges (map :charge/type-name) set)]
(com/pill {:color :primary } (com/pill {:color :primary }
method)))}]}) method)))}]})

View File

@@ -30,7 +30,7 @@
#_[:script {:src "https://unpkg.com/htmx.org@1.8.4" #_[:script {:src "https://unpkg.com/htmx.org@1.8.4"
:integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV" :integrity "sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
:crossorigin= "anonymous"}] :crossorigin= "anonymous"}]
[:script {:src "https://unpkg.com/htmx.org@1.9.0/dist/htmx.js" [:script {:src "https://unpkg.com/htmx.org@1.9.6/dist/htmx.min.js"
:crossorigin= "anonymous"}] :crossorigin= "anonymous"}]
[:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}] [:script {:src "https://unpkg.com/htmx.org/dist/ext/debug.js"}]
[:script {:src "/js/htmx-disable.js"}] [:script {:src "/js/htmx-disable.js"}]
@@ -38,6 +38,21 @@
[:script {:type "text/javascript", :src "https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/autoComplete.min.js"}] [:script {:type "text/javascript", :src "https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.7/dist/autoComplete.min.js"}]
[:script {:src "https://unpkg.com/dropzone@5.9.3/dist/min/dropzone.min.js"}] [: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"}] [:link {:rel "stylesheet" :href "https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" :type "text/css"}]
[:style
"
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
/* display: none; <- Crashes Chrome on hover */
-webkit-appearance: none;
margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
}
input[type=number] {
-moz-appearance:textfield; /* Firefox */
}
"
]
[:body {:hx-ext "disable-submit"} [:body {:hx-ext "disable-submit"}
contents contents
[:script {:src "/js/flowbite.min.js"}]]])) [:script {:src "/js/flowbite.min.js"}]]]))

View File

@@ -5,14 +5,21 @@
[hiccup2.core :as hiccup] [hiccup2.core :as hiccup]
[clojure.string :as str])) [clojure.string :as str]))
(defn html-response [hiccup & {:keys [status headers] :or {status 200 headers {}}}] (defn html-response [hiccup & {:keys [status headers oob] :or {status 200 headers {} oob []}}]
{:status status {:status status
:headers (into {"Content-Type" "text/html"} :headers (into {"Content-Type" "text/html"}
headers) headers)
:body (str :body (str
(hiccup/html (hiccup/html
{} {}
hiccup))}) hiccup)
"\n"
(str/join "\n"
(map (fn [o]
(hiccup/html
{}
o))
oob)))})
(defn wrap-error-response [handler] (defn wrap-error-response [handler]
(fn [request] (fn [request]

View File

@@ -173,8 +173,8 @@
:href (bidi/path-for routes/routes :payments)} :href (bidi/path-for routes/routes :payments)}
"Payments" ] "Payments" ]
(when (= "admin" (:user/role @user)) (when (= "admin" (:user/role @user))
[:a.navbar-item {:class [(active-when ap = :sales-orders)] [:a.navbar-item {:class [(active-when ap = :pos-sales)]
:href (bidi/path-for routes/routes :sales-orders)} :href (str (bidi/path-for ssr-routes/only-routes :pos-sales) "?date-range=week")}
"POS" ]) "POS" ])
[:a.navbar-item {:class [(active-when ap = :transactions)] [:a.navbar-item {:class [(active-when ap = :transactions)]
:href (bidi/path-for routes/routes :transactions)} :href (bidi/path-for routes/routes :transactions)}