2021-03-27 18:13:05 +01:00

143 lines
6.0 KiB
Clojure

(ns chicken-master.calendar
(:require
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[chicken-master.subs :as subs]
[chicken-master.html :as html]
[chicken-master.config :as config]
[chicken-master.products :as prod]
[chicken-master.events :as event]
[chicken-master.time :as time]))
(defn format-raw-order [{:strs [day who who-id notes] :as raw-values}]
{:who {:name who
:id (if (prod/num-or-nil who-id)
(prod/num-or-nil who-id)
;; seeing as there's an autocomplete thingy, assume that if the name is the same,
;; then so is the user
(some->> @(re-frame/subscribe [::subs/available-customers])
(filter (comp #{who} :name))
first :id))}
:day day
:notes notes
:products (prod/collect-products (remove (comp #{"who" "notes"} first) raw-values))})
(defn get-group-products [customers who]
(some->> customers (filter (comp #{who} :name))
first :product-groups
(reduce-kv #(assoc %1 %2 (:products %3)) {})))
(defn calc-order-prices [{:keys [who products] :as order}]
(->> products
(reduce-kv (fn [coll prod {:keys [amount price]}]
(assoc-in coll [prod :final-price]
(prod/calc-price (:id who) prod price amount))) products)
(assoc order :products)))
(defn merge-product-values [& products]
(apply merge-with
(fn [& values] (some->> values (remove nil?) seq (reduce +)))
products))
(defn order-form
([order] (order-form order #{:who :day :notes :products :group-products}))
([order fields]
(let [customers @(re-frame/subscribe [::subs/available-customers])
available-prods @(re-frame/subscribe [::subs/available-products])
state (-> (or order {})
(update :products reagent/atom)
(assoc :group-products
(get-group-products customers (-> order :who :name)))
reagent/atom)]
(fn []
[:div
(when (:who fields)
(let [who (:who @state)]
[:div
(html/input :who "kto" {:required true
:default (:name who)
:list :customers
:on-change (fn [e]
(if-let [products (->> e .-target .-value (get-group-products customers))]
(swap! state assoc :group-products products)))})
(into [:datalist {:id :customers}]
(for [cust customers] [:option {:value (:name cust) :id (:id cust)}]))
[:input {:id :who-id :name :who-id :type :hidden :value (or (:id who) "")}]]))
(when (:day fields)
(html/input :day "dzień" {:type :date :required true :default (:day order)}))
(when (and (:group-products fields) (-> @state :group-products seq))
[prod/group-products state])
(when (:notes fields)
(html/input :notes "notka"
{:default (:notes @state)}))
(when (:products fields)
[prod/products-edit (:products @state)
:available-prods available-prods
:fields (if (config/settings :prices) #{:amount :price} #{:amount})])]))))
(defn edit-order []
(html/modal
:order-edit
[order-form @(re-frame/subscribe [::subs/editted-order])]
;; On success
:on-submit (fn [form] (re-frame/dispatch [::event/save-order (format-raw-order form)]))))
(defn format-order [settings {:keys [id who day hour notes state products]}]
[:div {:class [:order state] :key (gensym)
:draggable true
:on-drag-start #(-> % .-dataTransfer (.setData "text" id))}
[:div {:class :actions}
(condp = state
:waiting [:button {:on-click #(re-frame/dispatch [::event/fulfill-order id])} "✓"]
:fulfilled [:button {:on-click #(re-frame/dispatch [::event/reset-order id])} "X"]
:pending nil
nil nil)
[:button {:on-click #(re-frame/dispatch [::event/edit-order day id])} "E"]
[:button {:on-click #(re-frame/dispatch
[::event/confirm-action
"na pewno usunąć?"
::event/remove-order id])} "-"]]
[:div {:class :who} (:name who)]
(if (settings :show-order-time)
[:div {:class :when} hour])
(if (and (settings :show-order-notes) notes)
[:div {:class :notes} notes])
(->> products
(map (partial prod/format-product settings))
(into [:div {:class :products}]))])
(defn day [settings [date orders]]
(let [orders (map calc-order-prices orders)]
[:div {:class [:day (when (-> date time/parse-date time/today?) :today)]
:on-drag-over #(.preventDefault %)
:on-drop #(let [id (-> % .-dataTransfer (.getData "text") prod/num-or-nil)]
(.preventDefault %)
(re-frame/dispatch [::event/move-order id date]))}
[:div {:class :day-header} (-> date time/parse-date time/format-date)]
[:div
[:div {:class :orders}
(->> (if (settings :hide-fulfilled-orders)
(remove (comp #{:fulfilled} :state) orders)
orders)
(map (partial format-order settings))
doall)
(when (settings :show-day-add-order)
[:button {:type :button
:on-click #(re-frame/dispatch [::event/edit-order date])} "+"])
(when (seq (map :products orders))
[:div {:class :summary}
[:hr {:class :day-seperator}]
[:div {:class :header} "w sumie:"]
(->> orders
(map :products)
(apply merge-with merge-product-values)
(sort-by first)
(map (partial prod/format-product settings))
(into [:div {:class :products-sum}]))])]]]))
(defn calendar [days settings]
(->> days
(map (partial day settings))
(into [:div {:class [:calendar :full-height]}])))