2021-02-07 19:54:41 +01:00

255 lines
8.6 KiB
Clojure

(ns chicken-master.events
(:require
[re-frame.core :as re-frame]
[chicken-master.db :as db]
[chicken-master.time :as time]
[chicken-master.config :refer [settings default-settings]]
[day8.re-frame.http-fx]
[ajax.edn :as edn]
;; required for http mocks
[chicken-master.backend-mocks :as mocks]))
(defn http-request [method endpoint & {:keys [params body on-success on-failure]
:or {on-success ::process-fetched-days
on-failure ::failed-request}}]
{:method method
:uri (str (settings :backend-url) endpoint)
:headers {"Content-Type" "application/edn"
"authorization" "Basic c2lsb2E6a3JhY2g="}
:format (edn/edn-request-format)
:body (some-> body pr-str)
:params params
:response-format (edn/edn-response-format)
:on-success [on-success]
:on-failure [on-failure]})
(defn http-get [endpoint params on-success]
(http-request :get endpoint :params params :on-success on-success))
(defn http-post [endpoint body]
(http-request :post endpoint :body body))
(re-frame/reg-event-fx
::initialize-db
(fn [_ _]
(time/update-settings default-settings)
{:db (assoc db/default-db :settings default-settings)
:fx [[:dispatch [::show-from-date (time/iso-date (time/today))]]
[:dispatch [::start-loading]]
[:dispatch [::fetch-stock]]
[:dispatch [::fetch-orders]]]}))
(re-frame/reg-event-db ::hide-modal (fn [db [_ modal]] (assoc-in db [modal :show] nil)))
(re-frame/reg-event-db ::start-loading (fn [db _] (assoc db :loading? true)))
(re-frame/reg-event-db ::stop-loading (fn [db _] (assoc db :loading? nil)))
(re-frame/reg-event-fx
::confirm-action
(fn [_ [_ msg on-confirm-event & params]]
(when (js/confirm msg)
{:fx [[:dispatch (into [on-confirm-event] params)]]})))
(re-frame/reg-event-fx
::remove-order
(fn [_ [_ id]]
{(settings :http-dispatch) (http-request :delete (str "orders/" id))}))
(re-frame/reg-event-db
::failed-request
(fn [db [_ response]]
(.error js/console (str response))
(js/alert "Wystąpił błąd")
(assoc db :loading false)))
(re-frame/reg-event-fx
::move-order
(fn [{{orders :orders start-date :start-date} :db} [_ id day]]
{(settings :http-dispatch)
(http-request :put (str "orders/" id)
:body (-> id orders (assoc :day day :start-from start-date)))}))
(re-frame/reg-event-db
::edit-order
(fn [{orders :orders :as db} [_ day id]]
(assoc db :order-edit
(-> orders
(get id {:state :waiting})
(merge {:show true :day day})))))
(re-frame/reg-event-fx
::fulfill-order
(fn [{db :db} [_ id]]
{:db (assoc-in db [:orders id :state] :pending)
(settings :http-dispatch) (http-request :post (str "orders/" id "/fulfilled"))}))
(re-frame/reg-event-fx
::reset-order
(fn [{db :db} [_ id]]
{:db (assoc-in db [:orders id :state] :waiting)
(settings :http-dispatch) (http-request :post (str "orders/" id "/waiting"))}))
(re-frame/reg-event-fx
::save-order
(fn [{{order :order-edit} :db} [_ form]]
{:dispatch [::hide-modal :order-edit]
(settings :http-dispatch) (http-post (str "orders")
(merge
(select-keys order [:id :day :hour :state])
(select-keys form [:id :day :hour :state :who :notes :products])))}))
(re-frame/reg-event-db
::process-fetched-days
(fn [db [_ days]]
(-> db
(assoc :loading? nil)
(update :current-days #(map (fn [[day orders]]
[day (if (contains? days day)
(days day) orders)]) %))
(update :orders #(reduce (fn [m cust] (assoc m (:id cust) cust)) % (-> days vals flatten))))))
(re-frame/reg-event-fx
::scroll-weeks
(fn [{db :db} [_ offset]]
{:fx [;[:dispatch [::fetch-stock]]
[:dispatch [::start-loading]]
[:dispatch [::show-from-date (-> db
:start-date
time/parse-date
(time/date-offset (* 7 offset))
time/iso-date)]]]}))
(re-frame/reg-event-db
::show-from-date
(fn [{:keys [start-date orders] :as db} [_ day]]
(let [day (or day start-date)
days (into #{} (time/get-weeks day 2))
filtered-orders (->> orders vals (filter (comp days :day)) (group-by :day))]
(assoc db
:loading? nil
:start-date day
:current-days (map #(vector % (get filtered-orders %)) (sort days))))))
(re-frame/reg-event-fx
::fetch-orders
(fn [_ [_ from to]]
{:dispatch [::start-loading]
(settings :http-dispatch) (http-get "orders" {} ::process-stock)}))
;; 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]]
{(settings :http-dispatch) (http-request :post "customers"
:body {:name customer-name}
:on-success ::process-stock)}))
(re-frame/reg-event-fx
::remove-customer
(fn [_ [_ id]]
{:dispatch [::start-loading]
(settings :http-dispatch) (http-request :delete (str "customers/" id)
:on-success ::process-stock)}))
;;; Storage events
(re-frame/reg-event-fx
::show-stock
(fn [{db :db} _]
{:db (assoc-in db [:stock :show] true)
:dispatch [::fetch-stock]}))
(re-frame/reg-event-fx
::fetch-stock
(fn [_ _]
{:dispatch [::start-loading]
(settings :http-dispatch) (http-get "stock" {} ::process-stock)}))
(defn assoc-if [coll key val] (if val (assoc coll key val) coll))
(re-frame/reg-event-fx
::process-stock
(fn [{db :db} [_ {:keys [products customers orders]}]]
{:db (-> db
(assoc-if :products products)
(assoc-if :customers customers)
(assoc-if :orders orders))
:dispatch [::scroll-weeks 0]
}))
(re-frame/reg-event-fx
::save-stock
(fn [_ [_ products]]
{:fx [[:dispatch [::hide-modal :stock]]
[:dispatch [::start-loading]]]
(settings :http-dispatch) (http-request :post "products" :body products :on-sucess ::process-stock)}))
;; Settings
(re-frame/reg-event-db
::show-settings
(fn [db _]
(assoc-in db [:settings :show] true)))
(comment
(re-frame/dispatch-sync [::show-stock])
(re-frame/dispatch-sync [::update-product-stock :eggs 2])
)
;;;;;;;; Backend mocks
(re-frame/reg-event-fx
::clear-database
(fn [_ _]
(mocks/purge-items)
(.reload js/location)))
(re-frame/reg-event-fx
::generate-database
(fn [_ _]
(mocks/generate-items)
{:fx [[:dispatch [::start-loading]]
[:dispatch [::fetch-stock]]
[:dispatch [::fetch-orders]]]}))
(re-frame/reg-fx
:http
(fn [{:keys [method uri params body on-success on-fail]}]
(condp = uri
"http://localhost:3000/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)))
"save-stock" (re-frame/dispatch (conj on-success (mocks/save-stocks body)))
(let [parts (clojure.string/split uri "/")]
(cond
(and (= method :get) (= uri "http://localhost:3000/orders"))
(re-frame/dispatch (conj on-success (mocks/fetch-orders params)))
(and (= method :post) (= uri "http://localhost:3000/orders"))
(re-frame/dispatch (conj on-success (mocks/replace-order nil (cljs.reader/read-string body))))
(and (= method :post) (= uri "http://localhost:3000/products"))
(re-frame/dispatch (conj on-success (mocks/save-stocks (cljs.reader/read-string body))))
(and (= method :delete) (= (nth parts 3) "orders"))
(re-frame/dispatch (conj on-success (mocks/delete-order (-> parts (nth 4) (js/parseInt)))))
(and (= method :delete) (= (nth parts 3) "customers"))
(re-frame/dispatch (conj on-success (mocks/delete-customer (-> parts (nth 4) (js/parseInt)))))
(and (= method :post) (= uri "http://localhost:3000/customers"))
(re-frame/dispatch (conj on-success (mocks/add-customer (cljs.reader/read-string body))))
(-> parts last #{"fulfilled" "waiting"})
(re-frame/dispatch (conj on-success (mocks/order-state {:id (-> parts (nth 4) (js/parseInt)) :state (keyword (last parts))})))
true (prn "unhandled" method uri)
))
)))