From 731dd8ce99731b454aa14d950fffa2073ddffc26 Mon Sep 17 00:00:00 2001 From: Daniel O'Connell Date: Wed, 3 Feb 2021 22:36:21 +0100 Subject: [PATCH] better edition --- src/cljs/chicken_master/calendar.cljs | 9 +++-- src/cljs/chicken_master/events.cljs | 7 +++- src/cljs/chicken_master/html.cljs | 4 +- src/cljs/chicken_master/products.cljs | 29 +++++++++----- src/cljs/chicken_master/stock.cljs | 12 ++---- test/cljs/chicken_master/calendar_test.cljs | 43 +++++++++++++++++++++ test/cljs/chicken_master/products_test.cljs | 42 ++++++++++++++++++++ 7 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 test/cljs/chicken_master/calendar_test.cljs create mode 100644 test/cljs/chicken_master/products_test.cljs diff --git a/src/cljs/chicken_master/calendar.cljs b/src/cljs/chicken_master/calendar.cljs index f0a57bf..8004bd3 100644 --- a/src/cljs/chicken_master/calendar.cljs +++ b/src/cljs/chicken_master/calendar.cljs @@ -14,10 +14,13 @@ :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) (js/parseInt amount)])) + (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 {}))}) @@ -36,9 +39,9 @@ [:div {:class :product-items-edit} (for [[i {product :prod amount :amount}] (map-indexed vector selected-prods)] (prod/product-item product amount available-prods i))]) - [:button {:type :button :on-click #(re-frame/dispatch [::event/add-product])} "+"]] + ] ;; On success - (fn [form] (re-frame/dispatch [::event/save-order (format-raw-order form)])))) + (fn [form] (prn (format-raw-order 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)} diff --git a/src/cljs/chicken_master/events.cljs b/src/cljs/chicken_master/events.cljs index 1bbd05b..20d7dbb 100644 --- a/src/cljs/chicken_master/events.cljs +++ b/src/cljs/chicken_master/events.cljs @@ -33,6 +33,7 @@ (-> customers (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 @@ -69,11 +70,13 @@ :on-success [::process-fetched-days] :on-fail [::failed-blah]}})) -(re-frame/reg-event-db ::add-product (fn [db _] (update-in db [:order-edit :products] conj {}))) (re-frame/reg-event-db ::selected-product (fn [db [_ product product-no]] - (assoc-in db [:order-edit :products product-no :prod] product))) + (let [db (assoc-in db [:order-edit :products product-no :prod] product)] + (if (-> db :order-edit :products last :prod) + (update-in db [:order-edit :products] conj {}) + db)))) (re-frame/reg-event-db ::changed-amount (fn [db [_ amount product-no]] diff --git a/src/cljs/chicken_master/html.cljs b/src/cljs/chicken_master/html.cljs index e17d1f5..3cab334 100644 --- a/src/cljs/chicken_master/html.cljs +++ b/src/cljs/chicken_master/html.cljs @@ -41,8 +41,8 @@ (re-frame/dispatch [::event/hide-modal])))} content [:div {:class :form-buttons} - [:button "add"] - [:button {:type :button :on-click #(re-frame/dispatch [::event/hide-modal modal-id])} "cancel"]]]]) + [: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 237b09b..260a3d9 100644 --- a/src/cljs/chicken_master/products.cljs +++ b/src/cljs/chicken_master/products.cljs @@ -5,6 +5,21 @@ [chicken-master.html :as html] [chicken-master.events :as event])) +(defn num-or-nil [val] + (let [i (js/parseFloat val)] + (when-not (js/isNaN i) i))) + +(defn round [num digits] + (let [div (js/Math.pow 10 digits)] + (/ (js/Math.round (* num div)) div))) + +(defn number-input [id label amount on-blur] + (html/input id label + {:type :number + :default (round amount 3) + :step :any + :on-blur on-blur})) + (defn product-item [what amount available product-no] (let [id (gensym)] [:div {:class :product-item-edit :key (gensym)} @@ -12,21 +27,17 @@ [: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} "-"] - (prn available) + [:option {:value ""} "-"] (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]) - }) + (number-input (str "amount-" id) "ile" amount + #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no])) ])) (defn format-product [[product amount]] [:div {:key (gensym) :class :product} [:span {:class :product-name} product] (if (settings :editable-number-inputs) - [:input {:class :product-amount :type :number :min 0 :defaultValue amount}] - [:span {:class :product-amount} amount])]) + (number-input (str "amount-" product) "" amount nil) + [:span {:class :product-amount} amount])]) diff --git a/src/cljs/chicken_master/stock.cljs b/src/cljs/chicken_master/stock.cljs index a53999b..273daf8 100644 --- a/src/cljs/chicken_master/stock.cljs +++ b/src/cljs/chicken_master/stock.cljs @@ -2,16 +2,12 @@ (:require [re-frame.core :as re-frame] [chicken-master.config :refer [settings]] + [chicken-master.products :refer [num-or-nil number-input]] [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 @@ -23,10 +19,8 @@ [: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)]) - }) + (number-input (name product) "" (or amount 0) + #(re-frame/dispatch [::event/set-stock-amount product (-> % .-target .-value num-or-nil)])) [:button {:type :button :on-click #(re-frame/dispatch [::event/update-product-stock product 1])} "+"] ]])] ;; On success diff --git a/test/cljs/chicken_master/calendar_test.cljs b/test/cljs/chicken_master/calendar_test.cljs new file mode 100644 index 0000000..231d47b --- /dev/null +++ b/test/cljs/chicken_master/calendar_test.cljs @@ -0,0 +1,43 @@ +(ns chicken-master.calendar-test + (:require + [chicken-master.calendar :as cal] + [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 {}}))) + + (testing "decent products" + (is (= (cal/format-raw-order {"who" "bla" "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}}))) + + (testing "duplicate products" + (is (= (cal/format-raw-order {"who" "bla" "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}}))) + + (testing "unselected are ignored" + (is (= (cal/format-raw-order {"who" "bla" "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}}))) + + (testing "items with 0 are removed" + (is (= (cal/format-raw-order {"who" "bla" "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}})))) diff --git a/test/cljs/chicken_master/products_test.cljs b/test/cljs/chicken_master/products_test.cljs new file mode 100644 index 0000000..3de92c1 --- /dev/null +++ b/test/cljs/chicken_master/products_test.cljs @@ -0,0 +1,42 @@ +(ns chicken-master.products-test + (:require + [chicken-master.products :as sut] + [cljs.test :refer-macros [deftest is testing]])) + + +(deftest test-num-or-nil + (testing "valid integers" + (is (= (sut/num-or-nil "1") 1)) + (is (= (sut/num-or-nil "-10") -10))) + + (testing "valid floats" + (is (= (sut/num-or-nil "1.23456") 1.23456))) + + (testing "strange numbers" + (is (= (sut/num-or-nil " 1") 1)) + (is (= (sut/num-or-nil "1asd") 1))) + + (testing "invalid numbers" + (is (nil? (sut/num-or-nil ""))) + (is (nil? (sut/num-or-nil "asd"))) + (is (nil? (sut/num-or-nil "asd23"))) + (is (nil? (sut/num-or-nil nil))))) + +(deftest test-round + (testing "rounding works" + (is (= (sut/round 1.234567 0) 1)) + (is (= (sut/round 1.234567 1) 1.2)) + (is (= (sut/round 1.234567 2) 1.23)) + (is (= (sut/round 1.234567 3) 1.235)))) + +(deftest test-number-input + (testing "proper format" + (is (= (sut/number-input :id :label 12 nil) + [:div {:class :input-item} + [:label {:for :id} :label] + [:input {:type :number :step :any :on-blur nil :defaultValue 12 :name :id :id :id}]]))) + (testing "numbers get rounded" + (is (= (sut/number-input :id :label 12.123456789 nil) + [:div {:class :input-item} + [:label {:for :id} :label] + [:input {:type :number :step :any :on-blur nil :defaultValue 12.123 :name :id :id :id}]]))))