From fee4de5fd58d5cf50c2175940dc6aacd6b404a48 Mon Sep 17 00:00:00 2001 From: Daniel O'Connell Date: Sun, 24 Jan 2021 18:53:47 +0100 Subject: [PATCH] basic stock --- src/clj/chicken_master/css.clj | 24 ++++-- .../{orders.cljs => backend_mocks.cljs} | 20 +++-- src/cljs/chicken_master/calendar.cljs | 1 + src/cljs/chicken_master/db.cljs | 6 +- src/cljs/chicken_master/events.cljs | 85 ++++++++++++++++--- src/cljs/chicken_master/html.cljs | 4 +- src/cljs/chicken_master/products.cljs | 11 ++- src/cljs/chicken_master/stock.cljs | 37 ++++++++ src/cljs/chicken_master/subs.cljs | 4 +- src/cljs/chicken_master/views.cljs | 14 ++- 10 files changed, 168 insertions(+), 38 deletions(-) rename src/cljs/chicken_master/{orders.cljs => backend_mocks.cljs} (82%) create mode 100644 src/cljs/chicken_master/stock.cljs diff --git a/src/clj/chicken_master/css.clj b/src/clj/chicken_master/css.clj index b6e6c49..a64bb52 100644 --- a/src/clj/chicken_master/css.clj +++ b/src/clj/chicken_master/css.clj @@ -37,9 +37,9 @@ (at-media {:max-width "800px"} [:.scroll-bar {:display :none}] - [:.scroll-button {:width "100%" - :font-size "3em" - :display :inherit}] + [:.menu-button {:width "100%" + :font-size "3em" + :display :inherit}] [:.popup [:form { :background-color "#fefefe" @@ -75,7 +75,7 @@ [:.day-header {:border "2px solid black" :text-align :center :font-size "2em"}] - [:.day.today {:border "2px solid red"}] + [:.day.today {:border "0.4em solid red"}] [:.day {:border "2px solid black" :overflow :auto} @@ -108,7 +108,21 @@ :max-height "5px"}] ]] - [:.summary {:margin-top "10px"}]]]]] + [:.summary {:margin-top "10px"}]]] + + + [:.stock-modal + [:.add-product {:float :right}] + [:.stock-product {:margin "1em 0"} + [:.product-name {:display :inline-block + :width "6em"}] + [:.stock-product-amount {:display :inline-block} + [:.input-item {:display :inline} + [:input {:width "40px"}] + [:label {:display :none}]] + ]] + ] + ]] ; Chrome, Safari, Edge, Opera ["input::-webkit-outer-spin-button" {:-webkit-appearance :none :margin 0}] diff --git a/src/cljs/chicken_master/orders.cljs b/src/cljs/chicken_master/backend_mocks.cljs similarity index 82% rename from src/cljs/chicken_master/orders.cljs rename to src/cljs/chicken_master/backend_mocks.cljs index 4131e56..b2dc6fe 100644 --- a/src/cljs/chicken_master/orders.cljs +++ b/src/cljs/chicken_master/backend_mocks.cljs @@ -1,7 +1,14 @@ -(ns chicken-master.orders +(ns chicken-master.backend-mocks (:require [chicken-master.time :as time])) -;;;;;;;; Backend mocks +;;;; Stock + +(def stock-products (atom {:eggs 22 :milk 32 :cabbage 54 :carrots 11 :cows 32 :ants 21})) + +(defn get-all-products [] @stock-products) +(defn save-stocks [new-products] (reset! stock-products new-products)) + +;;; Orders (def id-counter (atom -1)) (def days (atom @@ -43,7 +50,6 @@ (int (/ (- (time/parse-date to) (time/parse-date from)) (* 24 3600000))) (time/parse-date from))) -;;; Actual stuff (defn fetch-days [{:keys [from to]}] (->> (days-between from to) @@ -65,13 +71,17 @@ (swap! customers #(dissoc % id)) {day (->> day day-customers second)})) -(defn- order-state [{id :id state :state}] - (println "fulfilling order" id) +(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)) {day (->> day day-customers second)})) + (comment (replace-order {:id 194, :day "2020-11-21", :hour "02:12", :who "mr.blobby (649 234 234)", :products {:eggs 13 :milk 4 :cabbage 7}}) diff --git a/src/cljs/chicken_master/calendar.cljs b/src/cljs/chicken_master/calendar.cljs index 5318597..f0a57bf 100644 --- a/src/cljs/chicken_master/calendar.cljs +++ b/src/cljs/chicken_master/calendar.cljs @@ -24,6 +24,7 @@ (defn edit-order [] (html/modal + :order-edit [:div (html/input :who "kto" {:required true diff --git a/src/cljs/chicken_master/db.cljs b/src/cljs/chicken_master/db.cljs index ba5db24..24b7f9c 100644 --- a/src/cljs/chicken_master/db.cljs +++ b/src/cljs/chicken_master/db.cljs @@ -24,8 +24,6 @@ ;; :show-confirmation-modal {:show nil ;; :on-confirm-event :bla-bla-bla ;; :params [1 2 3]} - :products {:eggs {} - :milk {} - :cabbage {} - :carrots {}} + :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 896bc09..1bbd05b 100644 --- a/src/cljs/chicken_master/events.cljs +++ b/src/cljs/chicken_master/events.cljs @@ -2,12 +2,14 @@ (:require [re-frame.core :as re-frame] [chicken-master.db :as db] - [chicken-master.orders :as orders] - [chicken-master.time :as time])) + [chicken-master.time :as time] + + ;; 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-db ::hide-modal (fn [db _] (assoc db :order-edit {}))) +(re-frame/reg-event-db ::hide-modal (fn [db [_ modal]] (assoc-in db [modal :show] nil))) (re-frame/reg-event-fx ::confirm-action @@ -58,7 +60,7 @@ (re-frame/reg-event-fx ::save-order (fn [{{order :order-edit} :db} [_ form]] - {:fx [[:dispatch [::hide-modal]]] + {:fx [[:dispatch [::hide-modal :order-edit]]] :http {:method :post :url "save-order" :params (merge @@ -102,7 +104,8 @@ {: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)))) - :fx [[:dispatch [::set-current-days]]]})) + :fx [[:dispatch [::set-current-days]] + [:dispatch [::fetch-stock]]]})) (defn missing-days @@ -136,20 +139,76 @@ :on-success [::process-fetched-days] :on-fail [::failed-blah]}))))) +;;; Storage events + +(re-frame/reg-event-fx + ::show-stock + (fn [{db :db} _] + {:db (assoc-in db [:stock :show] true) + :fx [[:dispatch [::fetch-stock]]]})) + +(re-frame/reg-event-fx + ::fetch-stock + (fn [_ _] + {:http {:method :get + :url "get-all-products" + :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))) + +(re-frame/reg-event-db + ::update-product-stock + (fn [db [_ product i]] + (update-in db [:products product] + i))) + +(re-frame/reg-event-db + ::set-stock-amount + (fn [db [_ product i]] + (prn i) + (assoc-in db [:products product] i))) + +(re-frame/reg-event-db + ::set-stock-amount + (fn [db [_ product i]] + (prn i) + (assoc-in db [:products product] i))) + +(re-frame/reg-event-fx + ::save-stock + (fn [{db :db} [_ products]] + {:fx [[:dispatch [::hide-modal :stock]]] + :http {:method :post + :url "save-stock" + :body products + :on-success [::process-fetched-days] + :on-fail [::failed-blah]}})) + + + (comment - (re-frame/dispatch-sync [::show-from-date "2020-11-11"]) + (re-frame/dispatch-sync [::show-stock]) + (re-frame/dispatch-sync [::update-product-stock :eggs 2]) ) ;;;;;;;; Backend mocks + + (re-frame/reg-fx :http - (fn [{:keys [method url params on-success on-fail]}] - (println params) + (fn [{:keys [method url params body on-success on-fail]}] (condp = url - "get-days" (re-frame/dispatch (conj on-success (orders/fetch-days params))) - "save-order" (re-frame/dispatch (conj on-success (orders/replace-order params))) - "delete-order" (re-frame/dispatch (conj on-success (orders/delete-order params))) - "fulfill-order" (re-frame/dispatch (conj on-success (orders/order-state (assoc params :state :fulfilled)))) - "reset-order" (re-frame/dispatch (conj on-success (orders/order-state (assoc params :state :waiting)))) + "get-days" (re-frame/dispatch (conj on-success (mocks/fetch-days params))) + "save-order" (re-frame/dispatch (conj on-success (mocks/replace-order params))) + "delete-order" (re-frame/dispatch (conj on-success (mocks/delete-order params))) + "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-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 cf71041..e17d1f5 100644 --- a/src/cljs/chicken_master/html.cljs +++ b/src/cljs/chicken_master/html.cljs @@ -32,7 +32,7 @@ (merge {:name id :id id}))]])) -(defn modal [content on-submit] +(defn modal [modal-id content on-submit] [:div {:class :popup} [:form {:action "#" :on-submit (fn [e] @@ -42,7 +42,7 @@ content [:div {:class :form-buttons} [:button "add"] - [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal])} "cancel"]]]]) + [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal modal-id])} "cancel"]]]]) (comment diff --git a/src/cljs/chicken_master/products.cljs b/src/cljs/chicken_master/products.cljs index cf4f7b2..237b09b 100644 --- a/src/cljs/chicken_master/products.cljs +++ b/src/cljs/chicken_master/products.cljs @@ -9,17 +9,20 @@ (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])} [:option {:value nil} "-"] - (for [product available] - [:option {:key (gensym) :value product} (name product)])]] + (prn available) + (for [[product _] available] + [:option {:key (gensym) :value product} (name product)])] + ] (html/input (str "amount-" id) "ile" {:type :number :default amount :min 0 :on-blur #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no]) ;; :on-change #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no]) - })])) + }) + ])) (defn format-product [[product amount]] [:div {:key (gensym) :class :product} diff --git a/src/cljs/chicken_master/stock.cljs b/src/cljs/chicken_master/stock.cljs new file mode 100644 index 0000000..a53999b --- /dev/null +++ b/src/cljs/chicken_master/stock.cljs @@ -0,0 +1,37 @@ +(ns chicken-master.stock + (:require + [re-frame.core :as re-frame] + [chicken-master.config :refer [settings]] + [chicken-master.subs :as subs] + [chicken-master.html :as html] + [chicken-master.events :as event])) + + +(defn num-or-nil [val] + (let [i (js/parseInt val)] + (when-not (js/isNaN i) i))) + + +(defn show-available [] + (html/modal + :stock + [:div {:class :stock-modal} + [:button {:class :add-product :type :button :on-click #(re-frame/dispatch [::event/add-stock-product])} "dodaj"] + [:h2 "Magazyn"] + (for [[product amount] @(re-frame/subscribe [::subs/available-products])] + [:div {:key (gensym) :class :stock-product} + [:span {:class :product-name} product] + [:div {:class :stock-product-amount} + [:button {:type :button :on-click #(re-frame/dispatch [::event/update-product-stock product -1])} "-"] + (html/input (name product) "" + {:type :number :default (or amount 0) :min 0 + :on-blur #(re-frame/dispatch [::event/set-stock-amount product (-> % .-target .-value js/parseInt)]) + }) + [:button {:type :button :on-click #(re-frame/dispatch [::event/update-product-stock product 1])} "+"] + ]])] + ;; On success + (fn [form] + (->> form + (reduce-kv #(assoc %1 (keyword %2) (num-or-nil %3)) {}) + (conj [::event/save-stock]) + re-frame/dispatch)))) diff --git a/src/cljs/chicken_master/subs.cljs b/src/cljs/chicken_master/subs.cljs index 6b1a7db..e141282 100644 --- a/src/cljs/chicken_master/subs.cljs +++ b/src/cljs/chicken_master/subs.cljs @@ -2,9 +2,11 @@ (:require [re-frame.core :as re-frame])) (re-frame/reg-sub ::name (fn [db] (:name db))) -(re-frame/reg-sub ::available-products (fn [db] (-> db :products keys))) +(re-frame/reg-sub ::available-products (fn [db] (:products 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 ::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))) (re-frame/reg-sub ::order-edit-products (fn [db] (-> db :order-edit :products))) diff --git a/src/cljs/chicken_master/views.cljs b/src/cljs/chicken_master/views.cljs index 5fc012c..48a15ba 100644 --- a/src/cljs/chicken_master/views.cljs +++ b/src/cljs/chicken_master/views.cljs @@ -2,6 +2,7 @@ (:require [re-frame.core :as re-frame] [chicken-master.subs :as subs] + [chicken-master.stock :as stock] [chicken-master.calendar :as cal] [chicken-master.events :as event])) @@ -9,12 +10,17 @@ (defn main-panel [] (let [name (re-frame/subscribe [::subs/name])] [:div {:class :full-height} - [:button {:id :scroll-up-button :class :scroll-button :on-click #(re-frame/dispatch [::event/scroll-weeks -2])} "^"] + (cond + @(re-frame/subscribe [::subs/show-stock-modal]) (stock/show-available) + @(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])} "^"] + [: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"]] - (when @(re-frame/subscribe [::subs/show-edit-modal]) - (cal/edit-order)) + (cal/calendar @(re-frame/subscribe [::subs/current-days])) - [:button {:id :scroll-down-button :class :scroll-button :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"] + [:button {:id :scroll-down-button :class [:menu-button :scroll-button] :on-click #(re-frame/dispatch [::event/scroll-weeks 2])} "v"] ]))