mirror of
https://github.com/mruwnik/chicken-master.git
synced 2025-06-08 21:34:43 +02:00
Mock requests
This commit is contained in:
parent
fa69a0ed98
commit
5870093a4c
@ -44,6 +44,8 @@
|
||||
[:.actions {:display :none
|
||||
:float :right}]
|
||||
[:.order:hover [:.actions {:display :inline}]]
|
||||
[:.order.pending {:color :grey}]
|
||||
[:.order.fulfilled {:color :red}]
|
||||
|
||||
[:.who {:font-size "18px"
|
||||
:font-weight :bold
|
||||
|
@ -9,7 +9,7 @@
|
||||
[chicken-master.time :as time]))
|
||||
|
||||
|
||||
(defn add-order [date]
|
||||
(defn edit-order []
|
||||
(html/modal
|
||||
[:div
|
||||
(html/input :who "kto"
|
||||
@ -25,14 +25,19 @@
|
||||
(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])} "+"]]
|
||||
js/console.log))
|
||||
;; On success
|
||||
(fn [] (re-frame/dispatch [::event/save-order]))))
|
||||
|
||||
(defn format-order [{:keys [id who day hour products]}]
|
||||
[:li {:class :order :key (gensym)}
|
||||
(defn format-order [{:keys [id who day hour products state]}]
|
||||
[:li {:class [:order state] :key (gensym)}
|
||||
[:div {:class :actions}
|
||||
[:button "O"]
|
||||
(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
|
||||
:default nil)
|
||||
[:button {:on-click #(re-frame/dispatch [::event/edit-order day id])} "E"]
|
||||
[:button "-"]]
|
||||
[:button {:on-click #(re-frame/dispatch [::event/remove-order id])} "-"]]
|
||||
[:div {:class :who} who]
|
||||
(if (settings :show-order-time)
|
||||
[:div {:class :when} hour])
|
||||
@ -45,17 +50,21 @@
|
||||
[:div {:class :day-header} (time/format-date date)]
|
||||
[:div
|
||||
[:ul {:class :orders}
|
||||
(map format-order customers)
|
||||
(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 date])} "+"]]]])
|
||||
:on-click #(re-frame/dispatch [::event/edit-order (time/iso-date date)])} "+"]]]])
|
||||
|
||||
(defn calendar-header []
|
||||
(->> (settings :day-names)
|
||||
(->> (:day-names settings)
|
||||
cycle (drop (:first-day-offset settings))
|
||||
(take 7)
|
||||
(map (fn [day] [:div {:class :day-header} day]))
|
||||
(into [])))
|
||||
|
||||
(defn calendar [days]
|
||||
(->> days
|
||||
(map day)
|
||||
(concat (when-not (settings :always-day-names) (calendar-header)))
|
||||
(concat (when (settings :calendar-heading) (calendar-header)))
|
||||
(into [:div {:class [:calendar :full-height]}])))
|
||||
|
@ -3,7 +3,13 @@
|
||||
(def debug?
|
||||
^boolean goog.DEBUG)
|
||||
|
||||
(def settings {:first-day-offset 1
|
||||
:day-names ["Niedz" "Pon" "Wt" "Śr" "Czw" "Pt" "Sob"]
|
||||
:always-day-names true
|
||||
:show-order-time false})
|
||||
(def settings {:first-day-offset 1 ; which is the first day of the week (add the offset to `day-names`)
|
||||
:day-names ["Niedz" "Pon" "Wt" "Śr" "Czw" "Pt" "Sob"] ; how day should be displayed in the calendar view
|
||||
: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-order-time false ; display the time of each order
|
||||
:editable-number-inputs false ; only allow number modifications in the edit modal
|
||||
:hide-fulfilled-orders false
|
||||
})
|
||||
|
@ -20,6 +20,6 @@
|
||||
|
||||
(defn init []
|
||||
(re-frame/dispatch-sync [::events/initialize-db])
|
||||
(re-frame/dispatch-sync [::events/show-from-date (new js/Date "2020-09-05")])
|
||||
(re-frame/dispatch-sync [::events/show-from-date (new js/Date)])
|
||||
(dev-setup)
|
||||
(mount-root))
|
||||
|
@ -1,31 +1,26 @@
|
||||
(ns chicken-master.db)
|
||||
|
||||
(def default-db
|
||||
{:name "re-frame"
|
||||
:order-edit {:show nil
|
||||
:who "mr. blobby"
|
||||
:when "12:32"
|
||||
:products [{:prod :eggs :amount 2}
|
||||
{:prod :milk :amount 5}
|
||||
{}]}
|
||||
: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-09-05" [1 2 3]
|
||||
"2020-09-06" [1 2 3]
|
||||
"2020-09-07" [1 2 3]
|
||||
"2020-09-08" [1 2 3]
|
||||
"2020-09-09" [1 2 3]
|
||||
"2020-09-10" [1 2 3]
|
||||
"2020-09-11" [1 2 3]
|
||||
"2020-09-12" [1 2 3]
|
||||
"2020-09-13" [1 2 3]
|
||||
"2020-09-14" [1 2 3]
|
||||
"2020-09-15" [1 2 3]
|
||||
"2020-09-16" [1 2 3]
|
||||
"2020-09-17" [1 2 3]
|
||||
"2020-09-18" [1 2 3]}
|
||||
{;; 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]
|
||||
;; "2020-10-08" [1 2 3]
|
||||
;; "2020-10-09" [1 2 3]
|
||||
;; "2020-10-10" [1 2 3]
|
||||
;; "2020-10-11" [1 2 3]
|
||||
;; "2020-10-12" [1 2 3]
|
||||
;; "2020-10-13" [1 2 3]
|
||||
;; "2020-10-14" [1 2 3]
|
||||
;; "2020-10-15" [1 2 3]
|
||||
;; "2020-10-16" [1 2 3]
|
||||
;; "2020-10-17" [1 2 3]
|
||||
;; "2020-10-18" [1 2 3]}
|
||||
:products {:eggs {}
|
||||
:milk {}
|
||||
:cabbage {}
|
||||
:carrots {}}})
|
||||
:carrots {}}
|
||||
})
|
||||
|
@ -2,11 +2,22 @@
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[chicken-master.db :as db]
|
||||
[chicken-master.orders :as orders]
|
||||
[chicken-master.time :as time]))
|
||||
|
||||
(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-fx
|
||||
::remove-order
|
||||
(fn [_ [_ id]]
|
||||
{:http {:method :post
|
||||
:url "delete-order"
|
||||
:params {:id id}
|
||||
:on-success [::process-fetched-days]
|
||||
:on-fail [::failed-blah]}}))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::edit-order
|
||||
(fn [{customers :customers :as db} [_ day id]]
|
||||
@ -16,6 +27,38 @@
|
||||
(update :products (comp vec (partial map (partial zipmap [:prod :amount]))))
|
||||
(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]]]
|
||||
:http {:method :post
|
||||
:url "fulfill-order"
|
||||
:params {:id id}
|
||||
:on-success [::process-fetched-days]
|
||||
:on-fail [::failed-blah]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::reset-order
|
||||
(fn [{db :db} [_ id]]
|
||||
{:db (assoc-in db [:customers id :state] :waiting)
|
||||
:fx [[:dispatch [::set-current-days]]]
|
||||
:http {:method :post
|
||||
:url "reset-order"
|
||||
:params {:id id}
|
||||
:on-success [::process-fetched-days]
|
||||
:on-fail [::failed-blah]}}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::save-order
|
||||
(fn [{{order :order-edit} :db} _]
|
||||
{:fx [[:dispatch [::hide-modal]]]
|
||||
:http {:method :post
|
||||
:url "save-order"
|
||||
:params (orders/clean-order order)
|
||||
: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
|
||||
@ -34,12 +77,66 @@
|
||||
(get days)
|
||||
(map customers))})
|
||||
|
||||
|
||||
(re-frame/reg-event-db
|
||||
::show-from-date
|
||||
(fn [db [_ date]]
|
||||
(->> date
|
||||
::set-current-days
|
||||
(fn [{start-day :start-date :as db} _]
|
||||
(->> start-day
|
||||
time/parse-date
|
||||
time/start-of-week
|
||||
(time/days-range 14)
|
||||
(map (partial get-day db))
|
||||
(assoc db :current-days))))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::process-fetched-days
|
||||
(fn [{db :db} [_ days]]
|
||||
(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))))
|
||||
:fx [[:dispatch [::set-current-days]]]}))
|
||||
|
||||
|
||||
(defn missing-days
|
||||
"Return a map of missing days to be fetched."
|
||||
[db day]
|
||||
(let [missing-days (->> day
|
||||
time/parse-date
|
||||
time/start-of-week
|
||||
(time/days-range 28)
|
||||
(remove (comp (:days db {}) time/iso-date)))]
|
||||
(when (seq missing-days)
|
||||
{:from (->> missing-days (sort time/before?) first time/iso-date)
|
||||
:to (->> missing-days (sort time/before?) last time/iso-date)})))
|
||||
|
||||
(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]]]}]
|
||||
(if-not missing
|
||||
effects
|
||||
(assoc effects :http {:method :get
|
||||
:url "get-days"
|
||||
:params missing
|
||||
:on-success [::process-fetched-days]
|
||||
:on-fail [::failed-blah]})))))
|
||||
|
||||
|
||||
(comment
|
||||
(re-frame/dispatch-sync [::show-from-date "2020-11-11"])
|
||||
)
|
||||
;;;;;;;; Backend mocks
|
||||
|
||||
(re-frame/reg-fx
|
||||
:http
|
||||
(fn [{:keys [method url params on-success on-fail]}]
|
||||
(println params)
|
||||
(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))))
|
||||
)))
|
||||
|
@ -16,7 +16,11 @@
|
||||
|
||||
(defn modal [content on-submit]
|
||||
[:div {:class :popup}
|
||||
[:form {:action "#" :on-submit on-submit}
|
||||
[:form {:action "#"
|
||||
:on-submit (fn [e]
|
||||
(.preventDefault e)
|
||||
(when (on-submit)
|
||||
(re-frame/dispatch [::event/hide-modal])))}
|
||||
content
|
||||
[:div {:class :form-buttons}
|
||||
[:button "add"]
|
||||
|
78
src/cljs/chicken_master/orders.cljs
Normal file
78
src/cljs/chicken_master/orders.cljs
Normal file
@ -0,0 +1,78 @@
|
||||
(ns chicken-master.orders
|
||||
(:require [chicken-master.time :as time]))
|
||||
|
||||
(defn clean-order [order]
|
||||
(-> order
|
||||
(update :products #(->> %
|
||||
(group-by :prod)
|
||||
(reduce-kv (fn [m k v]
|
||||
(assoc m k (->> v
|
||||
(map :amount)
|
||||
(reduce +)))) {})))
|
||||
(select-keys [:id :who :day :hour :products])))
|
||||
|
||||
;;;;;;;; Backend mocks
|
||||
|
||||
(def id-counter (atom -1))
|
||||
(def days (atom
|
||||
(->> (time/date-offset (new js/Date) -50)
|
||||
(time/days-range 90)
|
||||
(map (fn [date]
|
||||
[(time/iso-date date) (repeatedly (rand-int 6) #(swap! id-counter inc))]))
|
||||
(into {}))))
|
||||
(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
|
||||
(atom
|
||||
(->> @days
|
||||
(map (fn [[day ids]]
|
||||
(map (fn [i]
|
||||
{:id i :day day :hour "02:12" :state :waiting
|
||||
:who (rand-nth @customer-names)
|
||||
:products (->> @products
|
||||
(random-sample 0.4)
|
||||
(map #(vector % (rand-int 10)))
|
||||
(into {}))
|
||||
}) ids)
|
||||
))
|
||||
flatten
|
||||
(map #(vector (:id %) %))
|
||||
(into {}))))
|
||||
|
||||
(defn- day-customers [day] [day (->> day (get @days) (map (partial get @customers)))])
|
||||
(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)
|
||||
(map day-customers)
|
||||
(into {})))
|
||||
|
||||
(defn- replace-order [order]
|
||||
(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))
|
||||
{(->> order :day) (->> order :day day-customers second)}))
|
||||
|
||||
(defn- delete-order [{id :id}]
|
||||
(println "deleting order" id)
|
||||
(let [day (-> (get @customers id) :day)]
|
||||
(swap! days (fn [ds] (update ds day (partial remove #{id}))))
|
||||
(swap! customers #(dissoc % id))
|
||||
{day (->> day day-customers second)}))
|
||||
|
||||
(defn- order-state [{id :id state :state}]
|
||||
(println "fulfilling order" id)
|
||||
(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}})
|
||||
)
|
@ -1,6 +1,7 @@
|
||||
(ns chicken-master.products
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[chicken-master.config :refer [settings]]
|
||||
[chicken-master.html :as html]
|
||||
[chicken-master.events :as event]))
|
||||
|
||||
@ -15,9 +16,13 @@
|
||||
[:option {:key (gensym) :value product} (name product)])]]
|
||||
(html/input :amount "ile"
|
||||
{:type :number :default amount :min 0
|
||||
:on-blur #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no])})])
|
||||
;; :on-blur #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no])
|
||||
:on-input #(re-frame/dispatch [::event/changed-amount (-> % .-target .-value) product-no])
|
||||
})])
|
||||
|
||||
(defn format-product [[product amount]]
|
||||
[:li {:key (gensym) :class :product}
|
||||
(if (settings :editable-number-inputs)
|
||||
[:input {:class :product-amount :type :number :min 0 :defaultValue amount}]
|
||||
[:span {:class :product-amount} amount])
|
||||
[:span {:class :product-name} product]])
|
||||
|
@ -1,7 +1,5 @@
|
||||
(ns chicken-master.subs
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[chicken-master.time :as time]))
|
||||
(: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)))
|
||||
@ -11,5 +9,4 @@
|
||||
(re-frame/reg-sub ::order-edit-when (fn [db] (-> db :order-edit :hour)))
|
||||
(re-frame/reg-sub ::order-edit-products (fn [db] (-> db :order-edit :products)))
|
||||
|
||||
|
||||
(re-frame/reg-sub ::current-days (fn [db] (:current-days db)))
|
||||
|
@ -2,6 +2,8 @@
|
||||
(:require [chicken-master.config :refer [settings]])
|
||||
(:import [goog.date DateTime Date Interval]))
|
||||
|
||||
(defn parse-date [date] (new Date (js/Date. date)))
|
||||
|
||||
(defn date-offset
|
||||
"Return the `date` offset by the given number of `days`"
|
||||
[date days]
|
||||
@ -12,15 +14,17 @@
|
||||
(defn start-of-week
|
||||
"Get the start of the week for the given `date"
|
||||
[date]
|
||||
(->> (.getDay date)
|
||||
(- (settings :first-day-offset))
|
||||
(date-offset date)))
|
||||
(let [offset (mod (+ 7 (.getDay date) (- (settings :first-day-offset))) 7)]
|
||||
(date-offset date (- offset))))
|
||||
|
||||
(defn days-range
|
||||
"Return dates starting from `date`"
|
||||
([date] (map (partial date-offset date) (range)))
|
||||
([n date] (take n (days-range date))))
|
||||
|
||||
(defn before? [d1 d2] (< (Date/compare d1 d2) 0))
|
||||
(defn after? [d1 d2] (> (Date/compare d1 d2) 0))
|
||||
|
||||
(defn same-day?
|
||||
"Returns true when both dates are from the same day" [d1 d2]
|
||||
(-> (new Date d1)
|
||||
@ -29,8 +33,24 @@
|
||||
(defn today? "true when `d1` is today" [d1] (same-day? (js/Date.) d1))
|
||||
|
||||
(defn format-date [date]
|
||||
(when (settings :show-date)
|
||||
(if (settings :show-day-name-with-date)
|
||||
(str
|
||||
(->> date .getDay (nth (settings :day-names)))
|
||||
" " (.getMonth date) "/" (.getDate date)))
|
||||
" " (inc (.getMonth date)) "/" (.getDate date))
|
||||
(str (inc (.getMonth date)) "/" (.getDate date)))))
|
||||
|
||||
(defn iso-date [date] (.toIsoString ^js/goog.date.Date date true))
|
||||
|
||||
|
||||
(comment
|
||||
(with-redefs [settings {:first-day-offset 0}]
|
||||
(= (->> (parse-date "2020-11-22") start-of-week iso-date) "2020-11-22")
|
||||
(filter #(= (-> (parse-date %) start-of-week iso-date) "2020-11-22")
|
||||
["2020-11-22" "2020-11-23" "2020-11-24" "2020-11-25" "2020-11-26" "2020-11-27" "2020-11-28"]))
|
||||
|
||||
(with-redefs [settings {:first-day-offset 1}]
|
||||
(= (->> (parse-date "2020-11-22") start-of-week iso-date) "2020-11-16")
|
||||
(filter #(= (-> (parse-date %) start-of-week iso-date) "2020-11-23")
|
||||
["2020-11-23" "2020-11-24" "2020-11-25" "2020-11-26" "2020-11-27" "2020-11-28" "2020-11-29" ]))
|
||||
)
|
||||
|
@ -10,6 +10,6 @@
|
||||
(let [name (re-frame/subscribe [::subs/name])]
|
||||
[:div {:class :full-height}
|
||||
(when @(re-frame/subscribe [::subs/show-edit-modal])
|
||||
(cal/add-order (new js/Date)))
|
||||
(cal/edit-order))
|
||||
(cal/calendar @(re-frame/subscribe [::subs/current-days]))
|
||||
]))
|
||||
|
Loading…
x
Reference in New Issue
Block a user