mirror of
https://github.com/mruwnik/chicken-master.git
synced 2025-06-08 13:24:42 +02:00
143 lines
6.0 KiB
Clojure
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]}])))
|