From 95f0af672f1cbb4746406b4d2c853cdbe099142e Mon Sep 17 00:00:00 2001 From: Daniel O'Connell Date: Sat, 6 Feb 2021 14:18:54 +0100 Subject: [PATCH] add clients view --- src/clj/chicken_master/css.clj | 14 ++-- src/cljs/chicken_master/backend_mocks.cljs | 41 +++++++---- src/cljs/chicken_master/calendar.cljs | 55 ++++++--------- src/cljs/chicken_master/config.cljs | 1 + src/cljs/chicken_master/core.cljs | 1 - src/cljs/chicken_master/customers.cljs | 56 +++++++++++++++ src/cljs/chicken_master/db.cljs | 8 ++- src/cljs/chicken_master/events.cljs | 75 ++++++++++++++------- src/cljs/chicken_master/html.cljs | 32 +++++---- src/cljs/chicken_master/products.cljs | 47 +++++++++++-- src/cljs/chicken_master/subs.cljs | 3 + src/cljs/chicken_master/views.cljs | 29 ++++---- test/cljs/chicken_master/calendar_test.cljs | 28 ++++---- 13 files changed, 267 insertions(+), 123 deletions(-) create mode 100644 src/cljs/chicken_master/customers.cljs diff --git a/src/clj/chicken_master/css.clj b/src/clj/chicken_master/css.clj index a64bb52..da39a71 100644 --- a/src/clj/chicken_master/css.clj +++ b/src/clj/chicken_master/css.clj @@ -20,7 +20,7 @@ :overflow :auto :z-index 1 :background-color "rgba(0,0,0,0.4)"} - [:form { + [:.popup-content { :background-color "#fefefe" :margin "15% auto" :padding "20px" @@ -30,7 +30,7 @@ [:.input-item [:label {:min-width "60px" :display :inline-block}]] - [:.form-buttons {:margin "10px"} + [:..popup-form-buttons {:margin "10px"} [:* {:margin "20px"}]]]] [:.scroll-button {:display :none}] @@ -41,7 +41,7 @@ :font-size "3em" :display :inherit}] [:.popup - [:form { + [:.popup-content { :background-color "#fefefe" :margin "3% auto" :padding "20px" @@ -56,7 +56,7 @@ (at-media {:min-width "800px"} [:.popup - [:form { + [:.popup-content { :background-color "#fefefe" :margin "15% auto" :padding "20px" @@ -122,6 +122,12 @@ [:label {:display :none}]] ]] ] + + [:.customers-modal + [:details.customer-order {:margin-left "1em" :padding "0.5em"} + [:.order-date-picker {:display :inline-block :width "75%" :cursor :pointer}] + [:.product-item-edit {:margin-left "1em"}]]] + ]] ; Chrome, Safari, Edge, Opera diff --git a/src/cljs/chicken_master/backend_mocks.cljs b/src/cljs/chicken_master/backend_mocks.cljs index b2dc6fe..afe2d51 100644 --- a/src/cljs/chicken_master/backend_mocks.cljs +++ b/src/cljs/chicken_master/backend_mocks.cljs @@ -23,9 +23,10 @@ "wisi 2.50" "chciała ukraść kozę"]) (def products (atom [:eggs :milk :cabbage :carrots])) -(def customer-names (atom ["mr.blobby (649 234 234)" "da police (0118 999 881 999 119 725 123123 12 3123 123 )" "johnny"])) - -(def customers +(def customers (atom [{:id 1 :name "mr.blobby (649 234 234)"} + {:id 2 :name "da police (0118 999 881 999 119 725 123123 12 3123 123 )"} + {:id 3 :name "johnny"}])) +(def orders (atom (->> @days (map (fn [[day ids]] @@ -33,7 +34,7 @@ {:id i :day day :notes (when (> (rand) 0.7) (rand-nth notes)) :state :waiting - :who (rand-nth @customer-names) + :who (rand-nth @customers) :products (->> @products (random-sample 0.4) (map #(vector % (rand-int 10))) @@ -44,13 +45,25 @@ (map #(vector (:id %) %)) (into {})))) -(defn- day-customers [day] [day (->> day (get @days) (map (partial get @customers)))]) + +(defn fetch-customers [_] + @customers) + +(defn fetch-stock [params] + {:customers (fetch-customers params) + :products (get-all-products)}) + +(defn add-customer [{:keys [customer-name] :as params}] + (swap! customers conj {:id (->> @customers (map :id) (apply max) inc) + :name customer-name}) + (fetch-stock params)) + +(defn- day-customers [day] [day (->> day (get @days) (map (partial get @orders)))]) (defn- days-between [from to] (time/days-range (int (/ (- (time/parse-date to) (time/parse-date from)) (* 24 3600000))) (time/parse-date from))) - (defn fetch-days [{:keys [from to]}] (->> (days-between from to) (map time/iso-date) @@ -61,24 +74,24 @@ (println "replacing order" order) (let [order (update order :id #(or % (swap! id-counter inc)))] (swap! days (fn [ds] (update ds (:day order) #(distinct (conj % (:id order)))))) - (swap! customers #(assoc % (:id order) order)) + (swap! orders #(assoc % (:id order) order)) {(->> order :day) (->> order :day day-customers second)})) (defn- delete-order [{id :id}] (println "deleting order" id) - (let [day (-> (get @customers id) :day)] + (let [day (-> (get @orders id) :day)] (swap! days (fn [ds] (update ds day (partial remove #{id})))) - (swap! customers #(dissoc % id)) + (swap! orders #(dissoc % id)) {day (->> day day-customers second)})) (defn- order-state [{id :id state :state :as bla}] (prn "fulfilling order" id state bla) (condp = state - :fulfilled (->> id (get @customers) :products (swap! stock-products #(merge-with - %1 %2))) - :waiting (->> id (get @customers) :products (swap! stock-products #(merge-with + %1 %2)))) - (let [day (-> (get @customers id) :day)] - (swap! customers #(assoc-in % [id :state] state)) - (println id (get @customers id)) + :fulfilled (->> id (get @orders) :products (swap! stock-products #(merge-with - %1 %2))) + :waiting (->> id (get @orders) :products (swap! stock-products #(merge-with + %1 %2)))) + (let [day (-> (get @orders id) :day)] + (swap! orders #(assoc-in % [id :state] state)) + (println id (get @orders id)) {day (->> day day-customers second)})) diff --git a/src/cljs/chicken_master/calendar.cljs b/src/cljs/chicken_master/calendar.cljs index 8004bd3..aab6b5d 100644 --- a/src/cljs/chicken_master/calendar.cljs +++ b/src/cljs/chicken_master/calendar.cljs @@ -1,6 +1,5 @@ (ns chicken-master.calendar (:require - [clojure.string :as str] [re-frame.core :as re-frame] [chicken-master.config :refer [settings]] [chicken-master.subs :as subs] @@ -9,39 +8,24 @@ [chicken-master.events :as event] [chicken-master.time :as time])) -(defn format-raw-order [{:strs [who notes] :as raw-values}] - {:who who +(defn format-raw-order [{:strs [who who-id notes] :as raw-values}] + {:who {:name who :id (prod/num-or-nil who-id)} :notes notes - :products (->> raw-values - (remove (comp #{"who" "notes"} first)) - (remove (comp str/blank? second)) - (map (fn [[k v]] [(str/split k "-") v])) - (group-by (comp last first)) - (map #(sort-by first (second %))) - (map (fn [[[_ amount] [_ product]]] [(keyword product) (prod/num-or-nil amount)])) - (remove (comp nil? first)) - (remove (comp zero? second)) - (group-by first) - (map (fn [[product items]] [product (->> items (map last) (reduce +))])) - (into {}))}) + :products (prod/collect-products (remove (comp #{"who" "notes"} first) raw-values))}) (defn edit-order [] (html/modal :order-edit [:div - (html/input :who "kto" - {:required true - :default @(re-frame/subscribe [::subs/order-edit-who])}) + (let [who @(re-frame/subscribe [::subs/order-edit-who])] + [:div + (html/input :who "kto" {:required true :default (:name who)}) + [:input {:id :who-id :name :who-id :type :hidden :value (or (:id who) "")}]]) (html/input :notes "notka" {:default @(re-frame/subscribe [::subs/order-edit-notes])}) - (let [available-prods @(re-frame/subscribe [::subs/available-products]) - selected-prods @(re-frame/subscribe [::subs/order-edit-products])] - [:div {:class :product-items-edit} - (for [[i {product :prod amount :amount}] (map-indexed vector selected-prods)] - (prod/product-item product amount available-prods i))]) - ] + [prod/products-edit @(re-frame/subscribe [::subs/order-edit-products])]] ;; On success - (fn [form] (prn (format-raw-order form))(re-frame/dispatch [::event/save-order (format-raw-order form)])))) + (fn [form] (re-frame/dispatch [::event/save-order (format-raw-order form)])))) (defn format-order [{:keys [id who day hour notes products state]}] [:div {:class [:order state] :key (gensym)} @@ -56,7 +40,7 @@ [::event/confirm-action "na pewno usunąć?" ::event/remove-order id])} "-"]] - [:div {:class :who} who] + [:div {:class :who} (:name who)] (if (settings :show-order-time) [:div {:class :when} hour]) (if (and (settings :show-order-notes) notes) @@ -65,25 +49,28 @@ (map prod/format-product) (into [:div {:class :products}]))]) -(defn day [{:keys [date customers]}] +(defn day [{:keys [date orders]}] [:div {:class [:day (when (time/today? date) :today)]} [:div {:class :day-header} (time/format-date date)] [:div [:div {:class :orders} (if (settings :hide-fulfilled-orders) - (->> customers (remove (comp #{:fulfilled} :state)) (map format-order)) - (map format-order customers)) - [:button {:type :button - :on-click #(re-frame/dispatch [::event/edit-order (time/iso-date date)])} "+"] - (when (seq (map :products customers)) + (->> orders (remove (comp #{:fulfilled} :state)) (map format-order)) + (map format-order orders)) + (when (settings :show-day-add-order) + [:button {:type :button + :on-click #(re-frame/dispatch [::event/edit-order (time/iso-date date)])} "+"]) + (when (seq (map :products orders)) [:div {:class :summary} + [:hr {:class :day-seperator}] [:div {:class :header} "w sumie:"] - (->> customers + (->> orders (map :products) (apply merge-with +) (sort-by first) (map prod/format-product) - (into [:div {:class :products-sum}]))])]]]) + (into [:div {:class :products-sum}]))]) + ]]]) (defn calendar-header [] (->> (:day-names settings) diff --git a/src/cljs/chicken_master/config.cljs b/src/cljs/chicken_master/config.cljs index da58581..72fbf8a 100644 --- a/src/cljs/chicken_master/config.cljs +++ b/src/cljs/chicken_master/config.cljs @@ -8,6 +8,7 @@ :calendar-heading false ; show a header with the names of days :show-date true ; display the date for each day :show-day-name-with-date true ; add the day name to each date + :show-day-add-order false ; Show an add order button in each day :show-order-time false ; display the time of each order :show-order-notes true ; display notes diff --git a/src/cljs/chicken_master/core.cljs b/src/cljs/chicken_master/core.cljs index 27e934e..08cea23 100644 --- a/src/cljs/chicken_master/core.cljs +++ b/src/cljs/chicken_master/core.cljs @@ -20,6 +20,5 @@ (defn init [] (re-frame/dispatch-sync [::events/initialize-db]) - (re-frame/dispatch-sync [::events/show-from-date (new js/Date)]) (dev-setup) (mount-root)) diff --git a/src/cljs/chicken_master/customers.cljs b/src/cljs/chicken_master/customers.cljs new file mode 100644 index 0000000..faf927f --- /dev/null +++ b/src/cljs/chicken_master/customers.cljs @@ -0,0 +1,56 @@ +(ns chicken-master.customers + (:require + [re-frame.core :as re-frame] + [reagent.core :as reagent] + [chicken-master.config :refer [settings]] + [chicken-master.products :as prod] + [chicken-master.subs :as subs] + [chicken-master.html :as html] + [chicken-master.events :as event])) + +(defn item-adder [& {:keys [type value callback button class] + :or {type :text value "" button nil}}] + (let [state (reagent/atom value)] + (fn [] + [:div {:class class :on-click #(.stopPropagation %)} + [:input {:type type :name :user-name :default value :value @state + :on-change #(let [val (-> % .-target .-value)] + (reset! state val) + (if-not button (callback val)))}] + (if button + [:button {:class :add-product + :type :button + :disabled (= @state "") + :on-click (if callback #(-> state (reset-vals! value) first callback))} button])]))) + +(defn order-adder [order] + (let [state (reagent/atom order)] + (fn [] + [:details {:class :customer-order :key (gensym) :open (:open @state)} + [:summary {:on-click #(swap! state update :open not)} + [item-adder + :type :date + :value (:day @state) + :class :order-date-picker + :callback (fn [day] (swap! state #(assoc % :day day :open true)))]] + (if (:day @state) + [prod/products-edit (:products @state) + :getter-fn #(re-frame/dispatch [::event/save-order (assoc @state :products %)])])]))) + +(defn show-customers [] + (html/modal + :clients + [:div {:class :customers-modal} + [:h2 "Clienci"] + [item-adder :callback #(re-frame/dispatch [::event/add-customer %]) :button "+"] + (let [client-orders (->> @(re-frame/subscribe [::subs/orders]) + vals + (group-by #(get-in % [:who :id])))] + (for [{:keys [name id] :as who} @(re-frame/subscribe [::subs/available-customers])] + [:details {:class "client" :key (gensym)} + [:summary name] + (for [order (sort-by :day (client-orders id))] + [order-adder (assoc order :key (gensym))]) + [order-adder who :class :new-user] + ]))] + )) diff --git a/src/cljs/chicken_master/db.cljs b/src/cljs/chicken_master/db.cljs index 24b7f9c..fd61722 100644 --- a/src/cljs/chicken_master/db.cljs +++ b/src/cljs/chicken_master/db.cljs @@ -2,9 +2,6 @@ (def default-db {;; set automatically - ;; :customers {1 {:id 1 :who "mr.blobby (649 234 234)" :day "2020-10-10" :hour "02:12" :products {:eggs 2 :milk 3}} - ;; 2 {:id 2 :who "da police (0118 999 881 999 119 725 123123 12 3123 123 )" :day "2020-10-10" :hour "02:12" :products {:eggs 12}} - ;; 3 {:id 3 :who "johnny" :day "2020-10-10" :hour "02:12" :products {:eggs 5}}} ;; :days {"2020-10-05" [1 2 3] ;; "2020-10-06" [1 2 3] ;; "2020-10-07" [1 2 3] @@ -24,6 +21,11 @@ ;; :show-confirmation-modal {:show nil ;; :on-confirm-event :bla-bla-bla ;; :params [1 2 3]} + + + ;; :current-days [{:day (google.date "2020-01-01") :orders []}] + ;; :customers [] + ::clients {:show nil} ; customers edit modal :stock {:show nil} :products {:eggs 22 :milk 32 :cabbage 54 :carrots 11 :cows 32 :ants 21} }) diff --git a/src/cljs/chicken_master/events.cljs b/src/cljs/chicken_master/events.cljs index 20d7dbb..c3133b7 100644 --- a/src/cljs/chicken_master/events.cljs +++ b/src/cljs/chicken_master/events.cljs @@ -7,7 +7,16 @@ ;; required for http mocks [chicken-master.backend-mocks :as mocks])) -(re-frame/reg-event-db ::initialize-db (fn [_ _] db/default-db)) +(re-frame/reg-event-fx + ::initialize-db + (fn [_ _] + {:db db/default-db + :dispatch [::show-from-date (new js/Date)] + :http {:method :post + :url "get-stock" + :params {} + :on-success [::process-stock] + :on-fail [::failed-blah]}})) (re-frame/reg-event-db ::hide-modal (fn [db [_ modal]] (assoc-in db [modal :show] nil))) @@ -28,19 +37,17 @@ (re-frame/reg-event-db ::edit-order - (fn [{customers :customers :as db} [_ day id]] + (fn [{orders :orders :as db} [_ day id]] (assoc db :order-edit - (-> customers + (-> orders (get id {:state :waiting}) - (update :products (comp vec (partial map (partial zipmap [:prod :amount])))) - (update :products conj {}) (merge {:show true :day day}))))) (re-frame/reg-event-fx ::fulfill-order (fn [{db :db} [_ id]] - {:db (assoc-in db [:customers id :state] :pending) - :fx [[:dispatch [::set-current-days]]] + {:db (assoc-in db [:orders id :state] :pending) + :dispatch [::set-current-days] :http {:method :post :url "fulfill-order" :params {:id id} @@ -50,7 +57,7 @@ (re-frame/reg-event-fx ::reset-order (fn [{db :db} [_ id]] - {:db (assoc-in db [:customers id :state] :waiting) + {:db (assoc-in db [:orders id :state] :waiting) :fx [[:dispatch [::set-current-days]]] :http {:method :post :url "reset-order" @@ -61,12 +68,12 @@ (re-frame/reg-event-fx ::save-order (fn [{{order :order-edit} :db} [_ form]] - {:fx [[:dispatch [::hide-modal :order-edit]]] + {:dispatch [::hide-modal :order-edit] :http {:method :post :url "save-order" :params (merge (select-keys order [:id :day :hour :state]) - (select-keys form [:who :notes :products])) + (select-keys form [:id :day :hour :state :who :notes :products])) :on-success [::process-fetched-days] :on-fail [::failed-blah]}})) @@ -83,12 +90,12 @@ (assoc-in db [:order-edit :products product-no :amount] amount))) -(defn get-day [{:keys [days customers]} date] +(defn get-day [{:keys [days orders]} date] {:date date - :customers (->> date - time/iso-date - (get days) - (map customers))}) + :orders (->> date + time/iso-date + (get days) + (map orders))}) (re-frame/reg-event-db ::set-current-days @@ -106,7 +113,7 @@ (println "fetched days" days) {:db (-> db (update :days #(reduce-kv (fn [m k v] (assoc m k (map :id v))) % days)) - (update :customers #(reduce (fn [m cust] (assoc m (:id cust) cust)) % (-> days vals flatten)))) + (update :orders #(reduce (fn [m cust] (assoc m (:id cust) cust)) % (-> days vals flatten)))) :fx [[:dispatch [::set-current-days]] [:dispatch [::fetch-stock]]]})) @@ -126,14 +133,14 @@ (re-frame/reg-event-fx ::scroll-weeks (fn [{db :db} [_ offset]] - {:fx [[:dispatch [::show-from-date (-> db :start-date time/parse-date (time/date-offset (* 7 offset)))]]]})) + {:dispatch [::show-from-date (-> db :start-date time/parse-date (time/date-offset (* 7 offset)))]})) (re-frame/reg-event-fx ::show-from-date (fn [{db :db} [_ day]] (let [missing (missing-days db day) effects {:db (assoc db :start-date day) - :fx [[:dispatch [::set-current-days]]]}] + :dispatch [::set-current-days]}] (if-not missing effects (assoc effects :http {:method :get @@ -141,6 +148,21 @@ :params missing :on-success [::process-fetched-days] :on-fail [::failed-blah]}))))) +;; Customers events +(re-frame/reg-event-fx + ::show-customers + (fn [{db :db} _] + {:db (assoc-in db [:clients :show] true) + :dispatch [::fetch-stock]})) + +(re-frame/reg-event-fx + ::add-customer + (fn [_ [_ customer-name]] + {:http {:method :post + :url "add-customer" + :params {:customer-name customer-name} + :on-success [::process-stock] + :on-fail [::failed-blah]}})) ;;; Storage events @@ -148,21 +170,23 @@ ::show-stock (fn [{db :db} _] {:db (assoc-in db [:stock :show] true) - :fx [[:dispatch [::fetch-stock]]]})) + :dispatch [::fetch-stock]})) (re-frame/reg-event-fx ::fetch-stock (fn [_ _] {:http {:method :get - :url "get-all-products" + :url "get-stock" :on-success [::process-stock] :on-fail [::failed-blah]}})) (re-frame/reg-event-db ::process-stock - (fn [db [_ stock]] - (println "fetched stock" stock) - (assoc db :products stock))) + (fn [db [_ {:keys [products customers]}]] + (println "fetched stock" products) + (assoc db + :products products + :customers customers))) (re-frame/reg-event-db ::update-product-stock @@ -184,7 +208,7 @@ (re-frame/reg-event-fx ::save-stock (fn [{db :db} [_ products]] - {:fx [[:dispatch [::hide-modal :stock]]] + {:dispatch [::hide-modal :stock] :http {:method :post :url "save-stock" :body products @@ -212,6 +236,9 @@ "fulfill-order" (re-frame/dispatch (conj on-success (mocks/order-state (assoc params :state :fulfilled)))) "reset-order" (re-frame/dispatch (conj on-success (mocks/order-state (assoc params :state :waiting)))) + "get-stock" (re-frame/dispatch (conj on-success (mocks/fetch-stock params))) + "get-customers" (re-frame/dispatch (conj on-success (mocks/fetch-customers params))) + "add-customer" (re-frame/dispatch (conj on-success (mocks/add-customer params))) "get-all-products" (re-frame/dispatch (conj on-success (mocks/get-all-products))) "save-stock" (re-frame/dispatch (conj on-success (mocks/save-stocks body))) ))) diff --git a/src/cljs/chicken_master/html.cljs b/src/cljs/chicken_master/html.cljs index 3cab334..8c3947c 100644 --- a/src/cljs/chicken_master/html.cljs +++ b/src/cljs/chicken_master/html.cljs @@ -25,24 +25,32 @@ ([id label] (input id label {})) ([id label options] [:div {:class :input-item} - [:label {:for id} label] + (if label [:label {:for id} label]) [:input (-> options (assoc :defaultValue (:default options)) (dissoc :default) (merge {:name id :id id}))]])) -(defn modal [modal-id content on-submit] - [:div {:class :popup} - [:form {:action "#" - :on-submit (fn [e] - (.preventDefault e) - (when (-> e .-target form-values on-submit) - (re-frame/dispatch [::event/hide-modal])))} - content - [:div {:class :form-buttons} - [:button "ok"] - [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal modal-id])} "anuluj"]]]]) +(defn modal + ([modal-id content] + [:div {:class :popup} + [:div {:class :popup-content} + content + [:div {:class :form-buttons} + [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal modal-id])} "ok"]]]]) + ([modal-id content on-submit] + [:div {:class :popup} + [:form {:action "#" + :class :popup-content + :on-submit (fn [e] + (.preventDefault e) + (when (-> e .-target form-values on-submit) + (re-frame/dispatch [::event/hide-modal modal-id])))} + content + [:div {:class :form-buttons} + [:button "ok"] + [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal modal-id])} "anuluj"]]]])) (comment diff --git a/src/cljs/chicken_master/products.cljs b/src/cljs/chicken_master/products.cljs index 260a3d9..81f873c 100644 --- a/src/cljs/chicken_master/products.cljs +++ b/src/cljs/chicken_master/products.cljs @@ -1,8 +1,11 @@ (ns chicken-master.products (:require + [clojure.string :as str] [re-frame.core :as re-frame] + [reagent.core :as reagent] [chicken-master.config :refer [settings]] [chicken-master.html :as html] + [chicken-master.subs :as subs] [chicken-master.events :as event])) (defn num-or-nil [val] @@ -20,21 +23,55 @@ :step :any :on-blur on-blur})) -(defn product-item [what amount available product-no] +(defn collect-products [raw-values] + (->> raw-values + (remove (comp str/blank? second)) + (map (fn [[k v]] [(str/split k "-") v])) + (group-by (comp last first)) + (map #(sort-by first (second %))) + (map (fn [[[_ amount] [_ product]]] [(keyword product) (num-or-nil amount)])) + (remove (comp nil? first)) + (remove (comp zero? second)) + (group-by first) + (map (fn [[product items]] [product (->> items (map last) (reduce +))])) + (into {}))) + +(defn product-item [available state what] (let [id (gensym)] [:div {:class :product-item-edit :key (gensym)} [:div {:class :input-item} - [:label {:for :product} "co"] + ;; [:label {:for :product} "co"] [:select {:name (str "product-" id) :id :product :defaultValue what - :on-change #(re-frame/dispatch [::event/selected-product (-> % .-target .-value) product-no])} + :on-change #(let [prod (-> % .-target .-value keyword)] + (swap! state assoc prod (+ (@state prod) (@state what))) + (swap! state dissoc what) + (if (not (contains? @state nil)) + (swap! state assoc nil 0)) + )} [:option {:value ""} "-"] (for [[product _] available] [:option {:key (gensym) :value product} (name product)])] ] - (number-input (str "amount-" id) "ile" amount - #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no])) + (number-input (str "amount-" id) nil (@state what) + #(do (swap! state assoc what (-> % .-target .-value num-or-nil)) + (prn @state))) ])) +(defn products-edit [selected-prods & {:keys [available-prods getter-fn] + :or {available-prods @(re-frame/subscribe [::subs/available-products])}}] + (let [state (reagent/atom (assoc selected-prods nil 0))] + (fn [] + (let [products (->> @state + keys + (map (partial product-item available-prods state)) + (into [:div {:class :product-items-edit}]))] + (if getter-fn + (conj products + [:button {:type :button + :on-click #(getter-fn (dissoc @state nil))} "ok"]) + products + ))))) + (defn format-product [[product amount]] [:div {:key (gensym) :class :product} [:span {:class :product-name} product] diff --git a/src/cljs/chicken_master/subs.cljs b/src/cljs/chicken_master/subs.cljs index e141282..85a72b0 100644 --- a/src/cljs/chicken_master/subs.cljs +++ b/src/cljs/chicken_master/subs.cljs @@ -3,9 +3,12 @@ (re-frame/reg-sub ::name (fn [db] (:name db))) (re-frame/reg-sub ::available-products (fn [db] (:products db))) +(re-frame/reg-sub ::available-customers (fn [db] (:customers db))) +(re-frame/reg-sub ::orders (fn [db] (:orders db))) (re-frame/reg-sub ::show-edit-modal (fn [db] (-> db :order-edit :show))) (re-frame/reg-sub ::show-stock-modal (fn [db] (-> db :stock :show))) +(re-frame/reg-sub ::show-customers-modal (fn [db] (-> db :clients :show))) (re-frame/reg-sub ::order-edit-who (fn [db] (println (:order-edit db)) (-> db :order-edit :who))) (re-frame/reg-sub ::order-edit-notes (fn [db] (-> db :order-edit :notes))) diff --git a/src/cljs/chicken_master/views.cljs b/src/cljs/chicken_master/views.cljs index 48a15ba..e5baa3c 100644 --- a/src/cljs/chicken_master/views.cljs +++ b/src/cljs/chicken_master/views.cljs @@ -3,24 +3,27 @@ [re-frame.core :as re-frame] [chicken-master.subs :as subs] [chicken-master.stock :as stock] + [chicken-master.customers :as cust] [chicken-master.calendar :as cal] [chicken-master.events :as event])) (defn main-panel [] - (let [name (re-frame/subscribe [::subs/name])] - [:div {:class :full-height} - (cond - @(re-frame/subscribe [::subs/show-stock-modal]) (stock/show-available) - @(re-frame/subscribe [::subs/show-edit-modal]) (cal/edit-order)) + [:div {:class :full-height} + (cond + @(re-frame/subscribe [::subs/show-stock-modal]) (stock/show-available) + @(re-frame/subscribe [::subs/show-customers-modal]) (cust/show-customers) + @(re-frame/subscribe [::subs/show-edit-modal]) (cal/edit-order)) - [:button {:id :show-stock-button :class :menu-button :on-click #(re-frame/dispatch [::event/show-stock])} "Magazyn"] - [:button {:id :scroll-up-button :class [:menu-button :scroll-button] :on-click #(re-frame/dispatch [::event/scroll-weeks -2])} "^"] + [:button {:id :show-stock-button :class :menu-button :on-click #(re-frame/dispatch [::event/show-stock])} "Magazyn"] + [:button {:id :show-clients-button :class :menu-button :on-click #(re-frame/dispatch [::event/show-customers])} "Klienci"] - [:div {:class :scroll-bar} - [:button {:id :scroll-up :on-click #(re-frame/dispatch [::event/scroll-weeks -2])} "^"] - [:button {:id :scroll-down :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"]] + [:button {:id :scroll-up-button :class [:menu-button :scroll-button] :on-click #(re-frame/dispatch [::event/scroll-weeks -2])} "^"] - (cal/calendar @(re-frame/subscribe [::subs/current-days])) - [:button {:id :scroll-down-button :class [:menu-button :scroll-button] :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"] - ])) + [:div {:class :scroll-bar} + [:button {:id :scroll-up :on-click #(re-frame/dispatch [::event/scroll-weeks -2])} "^"] + [:button {:id :scroll-down :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"]] + + (cal/calendar @(re-frame/subscribe [::subs/current-days])) + [:button {:id :scroll-down-button :class [:menu-button :scroll-button] :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"] + ]) diff --git a/test/cljs/chicken_master/calendar_test.cljs b/test/cljs/chicken_master/calendar_test.cljs index 231d47b..5ecd0b3 100644 --- a/test/cljs/chicken_master/calendar_test.cljs +++ b/test/cljs/chicken_master/calendar_test.cljs @@ -1,43 +1,45 @@ -(ns chicken-master.calendar-test +(ns chicken-master.sutendar-test (:require - [chicken-master.calendar :as cal] + [chicken-master.calendar :as sut] [cljs.test :refer-macros [deftest is testing]])) (deftest format-raw-order-test (testing "no products" - (is (= (cal/format-raw-order {}) {:who nil :notes nil :products {}})) - (is (= (cal/format-raw-order {"who" "bla" "notes" "ble"}) - {:who "bla" :notes "ble" :products {}}))) + (is (= (sut/format-raw-order {}) {:who {:name nil :id nil} :notes nil :products {}})) + (is (= (sut/format-raw-order {"who" "bla" "notes" "ble"}) + {:who {:name "bla" :id nil} :notes "ble" :products {}})) + (is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble"}) + {:who {:name "bla" :id 123} :notes "ble" :products {}}))) (testing "decent products" - (is (= (cal/format-raw-order {"who" "bla" "notes" "ble" + (is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble" "product-eggs" "eggs" "amount-eggs" "12" "product-cows" "cows" "amount-cows" "22" "product-milk" "milk" "amount-milk" "3.2"}) - {:who "bla" :notes "ble" :products {:eggs 12 :cows 22 :milk 3.2}}))) + {:who {:name "bla" :id 123} :notes "ble" :products {:eggs 12 :cows 22 :milk 3.2}}))) (testing "duplicate products" - (is (= (cal/format-raw-order {"who" "bla" "notes" "ble" + (is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble" "product-eggs" "eggs" "amount-eggs" "12" "product-eggs1" "eggs" "amount-eggs1" "12" "product-cows1" "cows" "amount-cows1" "1" "product-cows2" "cows" "amount-cows2" "2" "product-milk" "milk" "amount-milk" "3.2"}) - {:who "bla" :notes "ble" :products {:eggs 24 :cows 3 :milk 3.2}}))) + {:who {:name "bla" :id 123} :notes "ble" :products {:eggs 24 :cows 3 :milk 3.2}}))) (testing "unselected are ignored" - (is (= (cal/format-raw-order {"who" "bla" "notes" "ble" + (is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble" "product-eggs" "eggs" "amount-eggs" "12" "product-bad1" "" "amount-bad1" "12" "product-bad2" "" "amount-bad2" "1" "product-milk" "milk" "amount-milk" "3.2" "product-bad3" "" "amount-bad3" "2"}) - {:who "bla" :notes "ble" :products {:eggs 12 :milk 3.2}}))) + {:who {:name "bla" :id 123} :notes "ble" :products {:eggs 12 :milk 3.2}}))) (testing "items with 0 are removed" - (is (= (cal/format-raw-order {"who" "bla" "notes" "ble" + (is (= (sut/format-raw-order {"who" "bla" "who-id" "123" "notes" "ble" "product-eggs" "eggs" "amount-eggs" "12" "product-eggs1" "eggs" "amount-eggs1" "0" "product-cow" "cow" "amount-cow" "0" "product-milk" "milk" "amount-milk" "3.2"}) - {:who "bla" :notes "ble" :products {:eggs 12 :milk 3.2}})))) + {:who {:name "bla" :id 123} :notes "ble" :products {:eggs 12 :milk 3.2}}))))