standardized clients.
This commit is contained in:
@@ -34,7 +34,7 @@
|
|||||||
:headers {"Content-Type" "application/edn"}})
|
:headers {"Content-Type" "application/edn"}})
|
||||||
(do (log/error "GraphQL error" e)
|
(do (log/error "GraphQL error" e)
|
||||||
{:status 500
|
{:status 500
|
||||||
:body (pr-str {:errors [(merge {:message (.getMessage e)} (ex-data e))]})
|
:body (pr-str {:errors [(merge {:message (str "Unhandled error:" (str e))} (ex-data e))]})
|
||||||
:headers {"Content-Type" "application/edn"}}))))))
|
:headers {"Content-Type" "application/edn"}}))))))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::edit
|
::edit
|
||||||
(fn [{:keys [db]} [_ client-id]]
|
(fn [{:keys [db]} [_ client-id]]
|
||||||
(println "EDITING")
|
|
||||||
{:dispatch [::events/modal-status :auto-ap.views.pages.admin.clients/edit {:visible? true}]
|
{:dispatch [::events/modal-status :auto-ap.views.pages.admin.clients/edit {:visible? true}]
|
||||||
:db (assoc-in db [:admin :client]
|
:db (assoc-in db [:admin :client]
|
||||||
(get (:clients db) client-id))}))
|
(get (:clients db) client-id))}))
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
(ns auto-ap.views.pages.admin.clients
|
(ns auto-ap.views.pages.admin.clients
|
||||||
(:require-macros [cljs.core.async.macros :refer [go]]
|
|
||||||
[clojure.string :as str])
|
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
|
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
@@ -17,605 +14,81 @@
|
|||||||
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
[auto-ap.views.components.admin.side-bar :refer [admin-side-bar]]
|
||||||
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field nf]]
|
[auto-ap.views.utils :refer [login-url dispatch-event dispatch-value-change bind-field horizontal-field nf]]
|
||||||
[auto-ap.views.components.modal :refer [action-modal]]
|
[auto-ap.views.components.modal :refer [action-modal]]
|
||||||
|
[auto-ap.views.pages.admin.clients.table :as table]
|
||||||
|
[auto-ap.views.pages.admin.clients.form :as form]
|
||||||
[cljs.reader :as edn]
|
[cljs.reader :as edn]
|
||||||
[auto-ap.routes :as routes]
|
[auto-ap.routes :as routes]
|
||||||
[bidi.bidi :as bidi]))
|
[bidi.bidi :as bidi]
|
||||||
|
[auto-ap.status :as status]
|
||||||
|
[auto-ap.views.components.grid :as grid]
|
||||||
|
[auto-ap.views.pages.admin.clients.side-bar :as side-bar]
|
||||||
|
[vimsical.re-frame.fx.track :as track]))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::mounted
|
||||||
|
(fn [{:keys [db]} _]
|
||||||
|
{::track/register {:id ::params
|
||||||
|
:subscription [::params]
|
||||||
|
:event-fn (fn [params] [::params-change params])}}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::unmounted
|
||||||
|
(fn [{:keys [db]} _]
|
||||||
|
{:db (dissoc db ::table/params ::side-bar/filter-params)
|
||||||
|
::track/dispose {:id ::params}}))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::params
|
||||||
|
:<- [::table/params]
|
||||||
|
:<- [::side-bar/filter-params]
|
||||||
|
(fn [[table-params filter-params]]
|
||||||
|
(cond-> {}
|
||||||
|
(seq filter-params) (merge filter-params)
|
||||||
|
(seq table-params) (merge table-params))))
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
(re-frame/reg-event-db
|
||||||
::new
|
::new
|
||||||
(fn [db [_ client-id]]
|
(fn [db [_ client-id]]
|
||||||
(-> db
|
(-> db
|
||||||
(forms/start-form ::form {:bank-accounts []}))))
|
(forms/start-form ::form/form {:bank-accounts []}))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::edit-client-clicked
|
::params-change
|
||||||
(fn [{:keys [db]} [_ client-id]]
|
(fn [_ [_ params]]
|
||||||
{:db (-> db
|
{:set-uri-params params}))
|
||||||
(forms/stop-form ::form)
|
|
||||||
(forms/start-form ::form (get (:clients db) client-id)))}))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
::can-submit
|
::page
|
||||||
:<- [::forms/form ::form]
|
:<- [::params]
|
||||||
(fn [{:keys [data status]} _]
|
:<- [::subs/clients]
|
||||||
(println (s/explain ::entity/client data))
|
(fn [[params all-clients]]
|
||||||
(s/valid? ::entity/client data)))
|
(let [matching-clients (cond->> all-clients
|
||||||
|
(not-empty (:name params)) (filter #(str/includes? (str/lower-case (or (:name %) ""))
|
||||||
|
(str/lower-case (:name params))))
|
||||||
|
(not-empty (:code params)) (filter #(= (str/lower-case (or (:code %) ""))
|
||||||
|
(str/lower-case (:code params)))))]
|
||||||
|
(assoc (grid/virtual-paginate-controls (:start params ) matching-clients)
|
||||||
|
:data (grid/virtual-paginate (:start params) matching-clients)))))
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(def admin-clients-content
|
||||||
::new-client-request
|
(with-meta
|
||||||
:<- [::forms/form ::form]
|
(fn []
|
||||||
(fn [{new-client-data :data} _]
|
[:div
|
||||||
{:id (:id new-client-data),
|
[:div
|
||||||
:name (:name new-client-data)
|
[:h1.title "Clients"]
|
||||||
:code (:code new-client-data) ;; TODO add validation can't change
|
[:div.is-pulled-right
|
||||||
:email (:email new-client-data)
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::new])} "New client"]]
|
||||||
:locations (:locations new-client-data)
|
[table/clients-table {:page @(re-frame/subscribe [::page])
|
||||||
:matches (vec (:matches new-client-data))
|
:status @(re-frame/subscribe [::status/single ::page])}]]])
|
||||||
:location-matches (:location-matches new-client-data)
|
{:component-did-mount #(re-frame/dispatch [::mounted])
|
||||||
:week-a-credits (:week-a-credits new-client-data)
|
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])}))
|
||||||
:week-a-debits (:week-a-debits new-client-data)
|
|
||||||
:week-b-credits (:week-b-credits new-client-data)
|
|
||||||
:week-b-debits (:week-b-debits new-client-data)
|
|
||||||
:address {:street1 (:street1 (:address new-client-data))
|
|
||||||
:street2 (:street2 (:address new-client-data)),
|
|
||||||
:city (:city (:address new-client-data))
|
|
||||||
:state (:state (:address new-client-data))
|
|
||||||
:zip (:zip (:address new-client-data))}
|
|
||||||
:forecasted-transactions (map (fn [{:keys [id day-of-month identifier amount]}]
|
|
||||||
{:id id
|
|
||||||
:day-of-month day-of-month
|
|
||||||
:identifier identifier
|
|
||||||
:amount amount})
|
|
||||||
(:forecasted-transactions new-client-data))
|
|
||||||
:bank-accounts (map (fn [{:keys [number name check-number include-in-reports type id code bank-name routing bank-code new? sort-order visible yodlee-account-id locations]}]
|
|
||||||
{:number number
|
|
||||||
:name name
|
|
||||||
:check-number check-number
|
|
||||||
:include-in-reports include-in-reports
|
|
||||||
:type type
|
|
||||||
:id id
|
|
||||||
:sort-order sort-order
|
|
||||||
:visible visible
|
|
||||||
:locations (vec locations)
|
|
||||||
:yodlee-account-id (when yodlee-account-id
|
|
||||||
(js/parseInt yodlee-account-id))
|
|
||||||
:code (if new?
|
|
||||||
(str (:code new-client-data) "-" code)
|
|
||||||
code)
|
|
||||||
:bank-name bank-name
|
|
||||||
:routing routing
|
|
||||||
:bank-code bank-code})
|
|
||||||
(:bank-accounts new-client-data))}))
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
|
||||||
::save-new-client
|
|
||||||
[(forms/in-form ::form)]
|
|
||||||
(fn [{{new-client-data :data :as new-client-form} :db} _]
|
|
||||||
|
|
||||||
(let [new-client-req @(re-frame/subscribe [::new-client-request])
|
|
||||||
user @(re-frame/subscribe [::subs/token])]
|
|
||||||
|
|
||||||
(if (s/valid? ::entity/client new-client-req)
|
|
||||||
|
|
||||||
{:db (-> new-client-form
|
|
||||||
(assoc :status :loading)
|
|
||||||
(assoc :error nil))
|
|
||||||
:graphql
|
|
||||||
{:token user
|
|
||||||
:query-obj {:venia/operation {:operation/type :mutation
|
|
||||||
:operation/name "EditClient"}
|
|
||||||
:venia/queries [{:query/data [:edit-client
|
|
||||||
{:edit-client new-client-req}
|
|
||||||
[:id :name :code :email :locations :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits
|
|
||||||
[:location-matches [:location :match]]
|
|
||||||
[:address [:street1 :street2 :city :state :zip]]
|
|
||||||
[:forecasted-transactions [:id :amount :identifier :day-of-month]]
|
|
||||||
[:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order :locations]]]]}]}
|
|
||||||
:on-success [::save-complete]
|
|
||||||
:on-error [::forms/save-error ::new-client]}}
|
|
||||||
{:db new-client-form}))))
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::save-complete
|
|
||||||
(fn [db [_ client]]
|
|
||||||
(-> db
|
|
||||||
(forms/stop-form ::form)
|
|
||||||
|
|
||||||
(assoc-in [:clients (:id (:edit-client client))] (update (:edit-client client) :bank-accounts (fn [bas] (->> bas (sort-by :sort-order) vec)))))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-new-location
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client _]
|
|
||||||
(-> client
|
|
||||||
(update :locations conj (:location client))
|
|
||||||
(dissoc :location))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-location-to-bank-account
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client [_ which-account]]
|
|
||||||
(println client which-account)
|
|
||||||
(-> client
|
|
||||||
(update-in [:bank-accounts which-account :locations] #(conj (or % #{}) (get-in client [:bank-accounts which-account :location-select])))
|
|
||||||
(update-in [:bank-accounts which-account] dissoc :location-select))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-new-match
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client _]
|
|
||||||
(-> client
|
|
||||||
(update :matches conj (:match client))
|
|
||||||
(update :matches set)
|
|
||||||
(dissoc :match))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::remove-match
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client [_ which]]
|
|
||||||
(-> client
|
|
||||||
(update :matches set)
|
|
||||||
(update :matches disj which))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-new-location-match
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client _]
|
|
||||||
(-> client
|
|
||||||
(update :location-matches conj (:location-match client))
|
|
||||||
(dissoc :location-match))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-forecasted-transaction
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client _]
|
|
||||||
(-> client
|
|
||||||
(update :forecasted-transactions conj (assoc (:new-forecasted-transaction client) :temp-id (random-uuid)))
|
|
||||||
(dissoc :new-forecasted-transaction))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::remove-forecasted-transaction
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client [_ which]]
|
|
||||||
|
|
||||||
(-> client
|
|
||||||
(update :forecasted-transactions #(transduce
|
|
||||||
(filter (fn [x] (and (not= (:temp-id x) which)
|
|
||||||
(not= (:id x) which))))
|
|
||||||
|
|
||||||
conj
|
|
||||||
[]
|
|
||||||
%)))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::remove-location-match
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client [_ i]]
|
|
||||||
(-> client
|
|
||||||
(update :location-matches (fn [lm]
|
|
||||||
(->> lm
|
|
||||||
(map vector (range))
|
|
||||||
(filter (fn [[index item]]
|
|
||||||
(not= index i)))
|
|
||||||
(map second)))))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::add-new-bank-account
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data])]
|
|
||||||
(fn [client [_ type]]
|
|
||||||
(update client :bank-accounts conj {:type type :active? true :new? true :visible true :sort-order (count (:bank-accounts client))})))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::bank-account-activated
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
|
||||||
(fn [bank-accounts [_ index]]
|
|
||||||
(update (vec (sort-by :sort-order bank-accounts)) index assoc :active? true)))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::bank-account-deactivated
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
|
||||||
(fn [bank-accounts [_ index]]
|
|
||||||
(update (vec (sort-by :sort-order bank-accounts)) index assoc :active? false)))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::bank-account-removed
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
|
||||||
(fn [bank-accounts [_ index]]
|
|
||||||
(vec (concat (take index bank-accounts)
|
|
||||||
(drop (inc index) bank-accounts)))
|
|
||||||
#_(update db :bank-accounts
|
|
||||||
(fn [bas]
|
|
||||||
(filter #(not= (:code %) code) bas)))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::sort-swapped
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
|
||||||
(fn [bank-accounts [_ source dest]]
|
|
||||||
(->> (-> bank-accounts
|
|
||||||
(assoc-in [source :sort-order] (get-in bank-accounts [dest :sort-order]))
|
|
||||||
(assoc-in [dest :sort-order] (get-in bank-accounts [source :sort-order]))
|
|
||||||
|
|
||||||
)
|
|
||||||
(sort-by :sort-order)
|
|
||||||
vec)))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::toggle-visible
|
|
||||||
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
|
||||||
(fn [bank-accounts [_ account]]
|
|
||||||
(-> (->> bank-accounts
|
|
||||||
(sort-by :sort-order)
|
|
||||||
vec)
|
|
||||||
(update-in [account :visible] #(not %)))))
|
|
||||||
|
|
||||||
(defn clients-table []
|
|
||||||
(let [clients (re-frame/subscribe [::subs/clients])
|
|
||||||
editing-client (:client @(re-frame/subscribe [::subs/admin]))]
|
|
||||||
[:table {:class "table", :style {:width "100%"}}
|
|
||||||
[:thead
|
|
||||||
[:tr
|
|
||||||
[:th {:style {:width "50%"}} "Name"]
|
|
||||||
[:th {:style {:width "10%"}} "Name"]
|
|
||||||
[:th {:style {:width "20%"}} "Locations"]
|
|
||||||
[:th {:style {:width "20%"}} "Email"]]]
|
|
||||||
[:tbody (for [{:keys [id name email code locations] :as c} @clients]
|
|
||||||
^{:key (str name "-" id )}
|
|
||||||
[:tr {:on-click (fn [] (re-frame/dispatch [::edit-client-clicked id]))
|
|
||||||
:style {"cursor" "pointer"}}
|
|
||||||
[:td name]
|
|
||||||
[:td code]
|
|
||||||
[:td (str/join ", " locations)]
|
|
||||||
[:td email]])]]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn admin-clients-content []
|
|
||||||
[:div
|
|
||||||
(let [clients (re-frame/subscribe [::subs/clients])
|
|
||||||
editing-client (:client @(re-frame/subscribe [::subs/admin]))]
|
|
||||||
[:div
|
|
||||||
[:h1.title "Clients"]
|
|
||||||
[:div.is-pulled-right
|
|
||||||
[:a.button.is-primary.is-large {:on-click (dispatch-event [::new])} "New client"]]
|
|
||||||
[clients-table]])])
|
|
||||||
|
|
||||||
(def client-form
|
|
||||||
(forms/vertical-form {:can-submit [::can-submit]
|
|
||||||
:change-event [::forms/change ::form]
|
|
||||||
:submit-event [::save-new-client ]
|
|
||||||
:id ::form}))
|
|
||||||
|
|
||||||
(defn bank-account-card [new-client {:keys [active? new? type visible code name number check-number id sort-order] :as bank-account} first? last?]
|
|
||||||
(let [{:keys [form field raw-field error-notification submit-button ]} client-form]
|
|
||||||
[:div.card {:style {:margin-bottom "1em"}}
|
|
||||||
[:header.card-header
|
|
||||||
[:p.card-header-title {:style {:text-overflow "ellipsis"}}
|
|
||||||
[:span.icon.inline
|
|
||||||
(cond
|
|
||||||
(#{:check ":check"} type) [:span.icon-check-payment-sign]
|
|
||||||
|
|
||||||
(#{:credit ":credit"} type) [:span.icon-credit-card-1]
|
|
||||||
|
|
||||||
:else [:span.icon-accounting-bill])]
|
|
||||||
code ": " name]
|
|
||||||
[:p {:style {:padding "0.75em 0.25em"}}
|
|
||||||
[:a.button.is-outlined {:on-click (dispatch-event [::toggle-visible sort-order])} [:span.icon (if visible
|
|
||||||
[:span.fa.fa-eye]
|
|
||||||
[:span.fa.fa-eye-slash]
|
|
||||||
)]]]
|
|
||||||
(when-not last?
|
|
||||||
[:p {:style {:padding "0.75em 0.25em"}}
|
|
||||||
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (inc sort-order)])} [:span.icon [:span.fa.fa-sort-down]]]])
|
|
||||||
(when-not first?
|
|
||||||
[:p {:style {:padding "0.75em 0.25em"}}
|
|
||||||
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (dec sort-order)])} [:span.icon [:span.fa.fa-sort-up]]]])
|
|
||||||
(if active?
|
|
||||||
[:a.card-header-icon
|
|
||||||
{:on-click (dispatch-event [::bank-account-deactivated sort-order])}
|
|
||||||
[:span.icon
|
|
||||||
[:span.fa.fa-angle-up]]]
|
|
||||||
[:a.card-header-icon
|
|
||||||
{:on-click (dispatch-event [::bank-account-activated sort-order])}
|
|
||||||
[:span.icon
|
|
||||||
[:span.fa.fa-angle-down]]])]
|
|
||||||
(when active?
|
|
||||||
[:div.card-content
|
|
||||||
[:label.label "General"]
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
[:div.control
|
|
||||||
[:p.help "Account Code"]
|
|
||||||
(if new?
|
|
||||||
[:div.field.has-addons.is-extended
|
|
||||||
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
|
||||||
[:p.control
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "code"
|
|
||||||
:field [:bank-accounts sort-order :code]
|
|
||||||
:spec ::entity/code}]]]]
|
|
||||||
[:div.field [:p.control code]])]
|
|
||||||
|
|
||||||
[field "Nickname"
|
|
||||||
[:input.input {:placeholder "BOA Checking #1"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :name]}]]]
|
|
||||||
(when (#{:check ":check"} type )
|
|
||||||
[:div
|
|
||||||
|
|
||||||
[:label.label "Bank"]
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
[field "Bank Name"
|
|
||||||
[:input.input {:placeholder "Bank of America"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :bank-name]}]]
|
|
||||||
[field "Routing #"
|
|
||||||
[:input.input {:placeholder "104819123"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :routing]}]]
|
|
||||||
[field "Bank code"
|
|
||||||
[:input.input {:placeholder "12/10123"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :bank-code]}]]]
|
|
||||||
|
|
||||||
[:label.label "Checking account"]
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
[field "Account #"
|
|
||||||
[:input.input {:placeholder "123456789"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :number]}]]
|
|
||||||
|
|
||||||
[field "Check Number"
|
|
||||||
[:input.input {:placeholder "10000"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :check-number]}]]]
|
|
||||||
[field "Yodlee Account"
|
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :yodlee-account-id]}]]
|
|
||||||
|
|
||||||
])
|
|
||||||
(when (#{:credit ":credit"} type )
|
|
||||||
[:div
|
|
||||||
|
|
||||||
|
|
||||||
[:label.label "Account"]
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
[field "Bank Name"
|
|
||||||
[:input.input {:placeholder "Bank of America"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :bank-name]}]]]
|
|
||||||
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
[field "Account #"
|
|
||||||
[:input.input {:placeholder "123456789"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :number]}]]]
|
|
||||||
|
|
||||||
[field "Yodlee Account"
|
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-accounts sort-order :yodlee-account-id]}]]])
|
|
||||||
[:div.field
|
|
||||||
[:label.label "Locations"]
|
|
||||||
[:div.control
|
|
||||||
[:p.help "If this account is location-specific, add the valid locations"]
|
|
||||||
[:div.field.has-addons
|
|
||||||
[:p.control
|
|
||||||
[:div.select
|
|
||||||
[raw-field
|
|
||||||
[:select {:type "select"
|
|
||||||
:style {:width "7em"}
|
|
||||||
:field [:bank-accounts sort-order :location-select]
|
|
||||||
:allow-nil? true
|
|
||||||
:spec (set (get-in new-client [:locations]))}
|
|
||||||
(map (fn [l] ^{:key l} [:option {:value l} l]) (get-in new-client [:locations]))]]]]
|
|
||||||
[:p.control {:on-click (dispatch-event [::add-location-to-bank-account sort-order]) } [:a.button "Add"]]]]
|
|
||||||
|
|
||||||
(if-let [locations (seq (get-in new-client [:bank-accounts sort-order :locations]))]
|
|
||||||
[:ul
|
|
||||||
(for [location locations]
|
|
||||||
^{:key location} [:li location ])]
|
|
||||||
[:i "This account applies to all locations"])]
|
|
||||||
[:div.field
|
|
||||||
[:label.checkbox
|
|
||||||
[raw-field
|
|
||||||
[:input {:type "checkbox"
|
|
||||||
:field [:bank-accounts sort-order :include-in-reports]}]]
|
|
||||||
" Include in reports"]]])
|
|
||||||
|
|
||||||
(when active?
|
|
||||||
[:footer.card-footer
|
|
||||||
[:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated sort-order])} "Done"]
|
|
||||||
(when new?
|
|
||||||
[:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed sort-order])} "Remove"])])])
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
(def first-week-a (coerce/to-date-time #inst "1999-12-27T00:00:00.000-07:00"))
|
|
||||||
|
|
||||||
(defn is-week-a? [d]
|
|
||||||
(= 0 (mod (t/in-weeks (t/interval first-week-a d)) 2)))
|
|
||||||
|
|
||||||
(defn new-client-form []
|
|
||||||
(let [{new-client :data } @(re-frame/subscribe [::forms/form ::form])
|
|
||||||
{:keys [form field raw-field error-notification submit-button ]} client-form
|
|
||||||
next-week-a (if (is-week-a? (t/now))
|
|
||||||
"This week"
|
|
||||||
"Next week")
|
|
||||||
next-week-b (if (is-week-a? (t/now))
|
|
||||||
"Next week"
|
|
||||||
"This week")]
|
|
||||||
|
|
||||||
[side-bar {:on-close (dispatch-event [::forms/form-closing ::form ])}
|
|
||||||
[form {:title "Add client"}
|
|
||||||
[field "Name"
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:field [:name]
|
|
||||||
:spec ::entity/name
|
|
||||||
}]]
|
|
||||||
|
|
||||||
[:div.field
|
|
||||||
[:p.help "Client code"
|
|
||||||
]
|
|
||||||
(if (:id new-client)
|
|
||||||
[:div.control
|
|
||||||
(:code new-client)]
|
|
||||||
[:div.control
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "code"
|
|
||||||
:field :code
|
|
||||||
:spec ::entity/code}]]])]
|
|
||||||
|
|
||||||
|
|
||||||
[field "Email"
|
|
||||||
[:input.input {:type "email"
|
|
||||||
:field :email
|
|
||||||
:spec ::entity/email}]]
|
|
||||||
|
|
||||||
[:div.field
|
|
||||||
[:p.help "Matches"]
|
|
||||||
[:div.control
|
|
||||||
[:div.field.has-addons
|
|
||||||
[:p.control
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:field :match}]]]
|
|
||||||
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-match])} "Add"]]]]
|
|
||||||
[:ul
|
|
||||||
(for [match (:matches new-client)]
|
|
||||||
^{:key match} [:li match [:a {:on-click (dispatch-event [::remove-match match])} [:span.icon [:span.fa.fa-times]]]])]]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[:div.field
|
|
||||||
[:p.help "Locations"]
|
|
||||||
[:div.control
|
|
||||||
[:div.field.has-addons
|
|
||||||
[:p.control
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:field :location}]]]
|
|
||||||
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-location])} "Add"]]]
|
|
||||||
[:ul
|
|
||||||
(for [location (:locations new-client)]
|
|
||||||
^{:key location} [:li location ])]]]
|
|
||||||
|
|
||||||
[:div.field
|
|
||||||
[:p.help "Location matches"]
|
|
||||||
[:div.control
|
|
||||||
[:div.field.has-addons
|
|
||||||
|
|
||||||
[:p.control
|
|
||||||
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:placeholder "San Jose"
|
|
||||||
:field [:location-match :match]}]]]
|
|
||||||
[:p.control
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:placeholder "DT"
|
|
||||||
:field [:location-match :location]}]]]
|
|
||||||
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-location-match])} "Add"]]]
|
|
||||||
|
|
||||||
[:ul
|
|
||||||
(for [[index {:keys [location match]}] (map vector (range) (:location-matches new-client))]
|
|
||||||
^{:key index} [:li match "->" location [:a {:on-click (dispatch-event [::remove-location-match index])} [:span.icon
|
|
||||||
[:span.fa.fa-times]]]])]]]
|
|
||||||
|
|
||||||
[:div {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
|
||||||
[:h2.subtitle "Address"]
|
|
||||||
[address-field {:field [:address]
|
|
||||||
:event [::forms/change ::form]
|
|
||||||
:subscription new-client}]]
|
|
||||||
|
|
||||||
[:h2.subtitle "Bank accounts"]
|
|
||||||
(for [bank-account (sort-by :sort-order (:bank-accounts new-client))]
|
|
||||||
^{:key (:sort-order bank-account)}
|
|
||||||
[bank-account-card new-client bank-account (= 0 (:sort-order bank-account)) (= (:sort-order bank-account) (dec (count (:bank-accounts new-client))))])
|
|
||||||
|
|
||||||
[:div.columns
|
|
||||||
[:div.column.is-third
|
|
||||||
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :credit])} "Add Credit Account"]]
|
|
||||||
[:div.column.is-third
|
|
||||||
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :check])} "Add Checking Account"]]
|
|
||||||
[:div.column.is-third
|
|
||||||
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :cash])} "Add Cash Account"]]]
|
|
||||||
|
|
||||||
[:h2.subtitle "Cash flow"]
|
|
||||||
[:label.label (str "Week A (" next-week-a ")")]
|
|
||||||
[field "Regular Credits"
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "500.00"
|
|
||||||
:field [:week-a-credits]
|
|
||||||
:step "0.01"}]]
|
|
||||||
[field "Regular Debits"
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "150.00"
|
|
||||||
:field [:week-a-debits]
|
|
||||||
:step "0.01"}]]
|
|
||||||
[:label.label (str "Week B (" next-week-b ")")]
|
|
||||||
[field "Regular Credits"
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "1000.00"
|
|
||||||
:field [:week-b-credits]
|
|
||||||
:step "0.01"}]]
|
|
||||||
[field "Regular Debits"
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "250.00"
|
|
||||||
:field [:week-b-debits]
|
|
||||||
:step "0.01"}]]
|
|
||||||
[:div.field
|
|
||||||
[:label.label "Forecasted transactions"]
|
|
||||||
[:div.control
|
|
||||||
[horizontal-field
|
|
||||||
nil
|
|
||||||
|
|
||||||
[:p.control
|
|
||||||
[:p.help "Identifier"]
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "text"
|
|
||||||
:placeholder "Identifier"
|
|
||||||
:field [:new-forecasted-transaction :identifier]}]]]
|
|
||||||
[:p.control
|
|
||||||
[:p.help "Day of month"]
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "Day of month"
|
|
||||||
:step "1"
|
|
||||||
:field [:new-forecasted-transaction :day-of-month]}]]]
|
|
||||||
[:p.control
|
|
||||||
[:p.help "Amount"]
|
|
||||||
[raw-field
|
|
||||||
[:input.input {:type "number"
|
|
||||||
:placeholder "250.00"
|
|
||||||
:field [:new-forecasted-transaction :amount]
|
|
||||||
:step "0.01"}]]]
|
|
||||||
[:a.button {:on-click (dispatch-event [::add-forecasted-transaction])} "Add"]]]
|
|
||||||
|
|
||||||
[:ul
|
|
||||||
(for [forecasted-transaction (:forecasted-transactions new-client)]
|
|
||||||
^{:key (or (:id forecasted-transaction)
|
|
||||||
(:temp-id forecasted-transaction))}
|
|
||||||
[:li (:identifier forecasted-transaction) ": " (nf (:amount forecasted-transaction)) " on day " (:day-of-month forecasted-transaction) " of the month"
|
|
||||||
[:a {:on-click (dispatch-event [::remove-forecasted-transaction (or (:id forecasted-transaction)
|
|
||||||
(:temp-id forecasted-transaction))])} [:span.icon [:span.fa.fa-times]]]])]]
|
|
||||||
|
|
||||||
[error-notification]
|
|
||||||
[submit-button "Save"]]]))
|
|
||||||
|
|
||||||
(defn admin-clients-page []
|
(defn admin-clients-page []
|
||||||
(let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::form])]
|
(let [{:keys [active?]} @(re-frame/subscribe [::forms/form ::form/form])]
|
||||||
[side-bar-layout {:side-bar [admin-side-bar {}]
|
[side-bar-layout {:side-bar [admin-side-bar {}
|
||||||
|
[side-bar/client-side-bar]]
|
||||||
:main [admin-clients-content]
|
:main [admin-clients-content]
|
||||||
:right-side-bar [appearing-side-bar {:visible? active?} [new-client-form]] }]))
|
:right-side-bar [appearing-side-bar {:visible? active?} [form/new-client-form]] }]))
|
||||||
|
|
||||||
|
|||||||
561
src/cljs/auto_ap/views/pages/admin/clients/form.cljs
Normal file
561
src/cljs/auto_ap/views/pages/admin/clients/form.cljs
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
(ns auto-ap.views.pages.admin.clients.form
|
||||||
|
(:require [auto-ap.entities.clients :as entity]
|
||||||
|
[auto-ap.forms :as forms]
|
||||||
|
[auto-ap.subs :as subs]
|
||||||
|
[auto-ap.views.components.address :refer [address-field]]
|
||||||
|
[auto-ap.views.components.layouts :refer [side-bar]]
|
||||||
|
[auto-ap.views.utils :refer [dispatch-event horizontal-field nf]]
|
||||||
|
[cljs-time.coerce :as coerce]
|
||||||
|
[cljs-time.core :as t]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[re-frame.core :as re-frame]))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::can-submit
|
||||||
|
:<- [::forms/form ::form]
|
||||||
|
(fn [{:keys [data status]} _]
|
||||||
|
(s/valid? ::entity/client data)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::new-client-request
|
||||||
|
:<- [::forms/form ::form]
|
||||||
|
(fn [{new-client-data :data} _]
|
||||||
|
{:id (:id new-client-data),
|
||||||
|
:name (:name new-client-data)
|
||||||
|
:code (:code new-client-data) ;; TODO add validation can't change
|
||||||
|
:email (:email new-client-data)
|
||||||
|
:locations (:locations new-client-data)
|
||||||
|
:matches (vec (:matches new-client-data))
|
||||||
|
:location-matches (:location-matches new-client-data)
|
||||||
|
:week-a-credits (:week-a-credits new-client-data)
|
||||||
|
:week-a-debits (:week-a-debits new-client-data)
|
||||||
|
:week-b-credits (:week-b-credits new-client-data)
|
||||||
|
:week-b-debits (:week-b-debits new-client-data)
|
||||||
|
:address {:street1 (:street1 (:address new-client-data))
|
||||||
|
:street2 (:street2 (:address new-client-data)),
|
||||||
|
:city (:city (:address new-client-data))
|
||||||
|
:state (:state (:address new-client-data))
|
||||||
|
:zip (:zip (:address new-client-data))}
|
||||||
|
:forecasted-transactions (map (fn [{:keys [id day-of-month identifier amount]}]
|
||||||
|
{:id id
|
||||||
|
:day-of-month day-of-month
|
||||||
|
:identifier identifier
|
||||||
|
:amount amount})
|
||||||
|
(:forecasted-transactions new-client-data))
|
||||||
|
:bank-accounts (map (fn [{:keys [number name check-number include-in-reports type id code bank-name routing bank-code new? sort-order visible yodlee-account-id locations]}]
|
||||||
|
{:number number
|
||||||
|
:name name
|
||||||
|
:check-number check-number
|
||||||
|
:include-in-reports include-in-reports
|
||||||
|
:type type
|
||||||
|
:id id
|
||||||
|
:sort-order sort-order
|
||||||
|
:visible visible
|
||||||
|
:locations (vec locations)
|
||||||
|
:yodlee-account-id (when yodlee-account-id
|
||||||
|
(js/parseInt yodlee-account-id))
|
||||||
|
:code (if new?
|
||||||
|
(str (:code new-client-data) "-" code)
|
||||||
|
code)
|
||||||
|
:bank-name bank-name
|
||||||
|
:routing routing
|
||||||
|
:bank-code bank-code})
|
||||||
|
(:bank-accounts new-client-data))}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::editing
|
||||||
|
(fn [{:keys [db]} [_ client-id]]
|
||||||
|
{:db (-> db
|
||||||
|
(forms/stop-form ::form)
|
||||||
|
(forms/start-form ::form (get (:clients db) client-id)))}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::save-new-client
|
||||||
|
[(forms/in-form ::form)]
|
||||||
|
(fn [{{new-client-data :data :as new-client-form} :db} _]
|
||||||
|
|
||||||
|
(let [new-client-req @(re-frame/subscribe [::new-client-request])
|
||||||
|
user @(re-frame/subscribe [::subs/token])]
|
||||||
|
|
||||||
|
(if (s/valid? ::entity/client new-client-req)
|
||||||
|
|
||||||
|
{:db (-> new-client-form
|
||||||
|
(assoc :status :loading)
|
||||||
|
(assoc :error nil))
|
||||||
|
:graphql
|
||||||
|
{:token user
|
||||||
|
:query-obj {:venia/operation {:operation/type :mutation
|
||||||
|
:operation/name "EditClient"}
|
||||||
|
:venia/queries [{:query/data [:edit-client
|
||||||
|
{:edit-client new-client-req}
|
||||||
|
[:id :name :code :email :locations :matches :week-a-debits :week-a-credits :week-b-debits :week-b-credits
|
||||||
|
[:location-matches [:location :match]]
|
||||||
|
[:address [:street1 :street2 :city :state :zip]]
|
||||||
|
[:forecasted-transactions [:id :amount :identifier :day-of-month]]
|
||||||
|
[:bank-accounts [:id :number :check-number :name :code :bank-code :bank-name :routing :type :visible :yodlee-account-id :sort-order :locations]]]]}]}
|
||||||
|
:on-success [::save-complete]
|
||||||
|
:on-error [::forms/save-error ::new-client]}}
|
||||||
|
{:db new-client-form}))))
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::save-complete
|
||||||
|
(fn [db [_ client]]
|
||||||
|
(-> db
|
||||||
|
(forms/stop-form ::form)
|
||||||
|
|
||||||
|
(assoc-in [:clients (:id (:edit-client client))] (update (:edit-client client) :bank-accounts (fn [bas] (->> bas (sort-by :sort-order) vec)))))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-new-location
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client _]
|
||||||
|
(-> client
|
||||||
|
(update :locations conj (:location client))
|
||||||
|
(dissoc :location))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-location-to-bank-account
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client [_ which-account]]
|
||||||
|
(println client which-account)
|
||||||
|
(-> client
|
||||||
|
(update-in [:bank-accounts which-account :locations] #(conj (or % #{}) (get-in client [:bank-accounts which-account :location-select])))
|
||||||
|
(update-in [:bank-accounts which-account] dissoc :location-select))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-new-match
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client _]
|
||||||
|
(-> client
|
||||||
|
(update :matches conj (:match client))
|
||||||
|
(update :matches set)
|
||||||
|
(dissoc :match))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::remove-match
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client [_ which]]
|
||||||
|
(-> client
|
||||||
|
(update :matches set)
|
||||||
|
(update :matches disj which))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-new-location-match
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client _]
|
||||||
|
(-> client
|
||||||
|
(update :location-matches conj (:location-match client))
|
||||||
|
(dissoc :location-match))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-forecasted-transaction
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client _]
|
||||||
|
(-> client
|
||||||
|
(update :forecasted-transactions conj (assoc (:new-forecasted-transaction client) :temp-id (random-uuid)))
|
||||||
|
(dissoc :new-forecasted-transaction))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::remove-forecasted-transaction
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client [_ which]]
|
||||||
|
|
||||||
|
(-> client
|
||||||
|
(update :forecasted-transactions #(transduce
|
||||||
|
(filter (fn [x] (and (not= (:temp-id x) which)
|
||||||
|
(not= (:id x) which))))
|
||||||
|
|
||||||
|
conj
|
||||||
|
[]
|
||||||
|
%)))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::remove-location-match
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client [_ i]]
|
||||||
|
(-> client
|
||||||
|
(update :location-matches (fn [lm]
|
||||||
|
(->> lm
|
||||||
|
(map vector (range))
|
||||||
|
(filter (fn [[index item]]
|
||||||
|
(not= index i)))
|
||||||
|
(map second)))))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::add-new-bank-account
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data])]
|
||||||
|
(fn [client [_ type]]
|
||||||
|
(update client :bank-accounts conj {:type type :active? true :new? true :visible true :sort-order (count (:bank-accounts client))})))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::bank-account-activated
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
||||||
|
(fn [bank-accounts [_ index]]
|
||||||
|
(update (vec (sort-by :sort-order bank-accounts)) index assoc :active? true)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::bank-account-deactivated
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
||||||
|
(fn [bank-accounts [_ index]]
|
||||||
|
(update (vec (sort-by :sort-order bank-accounts)) index assoc :active? false)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::bank-account-removed
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
||||||
|
(fn [bank-accounts [_ index]]
|
||||||
|
(vec (concat (take index bank-accounts)
|
||||||
|
(drop (inc index) bank-accounts)))
|
||||||
|
#_(update db :bank-accounts
|
||||||
|
(fn [bas]
|
||||||
|
(filter #(not= (:code %) code) bas)))))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::sort-swapped
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
||||||
|
(fn [bank-accounts [_ source dest]]
|
||||||
|
(->> (-> bank-accounts
|
||||||
|
(assoc-in [source :sort-order] (get-in bank-accounts [dest :sort-order]))
|
||||||
|
(assoc-in [dest :sort-order] (get-in bank-accounts [source :sort-order]))
|
||||||
|
|
||||||
|
)
|
||||||
|
(sort-by :sort-order)
|
||||||
|
vec)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-db
|
||||||
|
::toggle-visible
|
||||||
|
[(forms/in-form ::form) (re-frame/path [:data :bank-accounts])]
|
||||||
|
(fn [bank-accounts [_ account]]
|
||||||
|
(-> (->> bank-accounts
|
||||||
|
(sort-by :sort-order)
|
||||||
|
vec)
|
||||||
|
(update-in [account :visible] #(not %)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(def client-form
|
||||||
|
(forms/vertical-form {:can-submit [::can-submit]
|
||||||
|
:change-event [::forms/change ::form]
|
||||||
|
:submit-event [::save-new-client ]
|
||||||
|
:id ::form}))
|
||||||
|
|
||||||
|
(def first-week-a (coerce/to-date-time #inst "1999-12-27T00:00:00.000-07:00"))
|
||||||
|
|
||||||
|
(defn is-week-a? [d]
|
||||||
|
(= 0 (mod (t/in-weeks (t/interval first-week-a d)) 2)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn bank-account-card [new-client {:keys [active? new? type visible code name number check-number id sort-order] :as bank-account} first? last?]
|
||||||
|
(let [{:keys [form field raw-field error-notification submit-button ]} client-form]
|
||||||
|
[:div.card {:style {:margin-bottom "1em"}}
|
||||||
|
[:header.card-header
|
||||||
|
[:p.card-header-title {:style {:text-overflow "ellipsis"}}
|
||||||
|
[:span.icon.inline
|
||||||
|
(cond
|
||||||
|
(#{:check ":check"} type) [:span.icon-check-payment-sign]
|
||||||
|
|
||||||
|
(#{:credit ":credit"} type) [:span.icon-credit-card-1]
|
||||||
|
|
||||||
|
:else [:span.icon-accounting-bill])]
|
||||||
|
code ": " name]
|
||||||
|
[:p {:style {:padding "0.75em 0.25em"}}
|
||||||
|
[:a.button.is-outlined {:on-click (dispatch-event [::toggle-visible sort-order])} [:span.icon (if visible
|
||||||
|
[:span.fa.fa-eye]
|
||||||
|
[:span.fa.fa-eye-slash]
|
||||||
|
)]]]
|
||||||
|
(when-not last?
|
||||||
|
[:p {:style {:padding "0.75em 0.25em"}}
|
||||||
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (inc sort-order)])} [:span.icon [:span.fa.fa-sort-down]]]])
|
||||||
|
(when-not first?
|
||||||
|
[:p {:style {:padding "0.75em 0.25em"}}
|
||||||
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::sort-swapped sort-order (dec sort-order)])} [:span.icon [:span.fa.fa-sort-up]]]])
|
||||||
|
(if active?
|
||||||
|
[:a.card-header-icon
|
||||||
|
{:on-click (dispatch-event [::bank-account-deactivated sort-order])}
|
||||||
|
[:span.icon
|
||||||
|
[:span.fa.fa-angle-up]]]
|
||||||
|
[:a.card-header-icon
|
||||||
|
{:on-click (dispatch-event [::bank-account-activated sort-order])}
|
||||||
|
[:span.icon
|
||||||
|
[:span.fa.fa-angle-down]]])]
|
||||||
|
(when active?
|
||||||
|
[:div.card-content
|
||||||
|
[:label.label "General"]
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[:div.control
|
||||||
|
[:p.help "Account Code"]
|
||||||
|
(if new?
|
||||||
|
[:div.field.has-addons.is-extended
|
||||||
|
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
||||||
|
[:p.control
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "code"
|
||||||
|
:field [:bank-accounts sort-order :code]
|
||||||
|
:spec ::entity/code}]]]]
|
||||||
|
[:div.field [:p.control code]])]
|
||||||
|
|
||||||
|
[field "Nickname"
|
||||||
|
[:input.input {:placeholder "BOA Checking #1"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :name]}]]]
|
||||||
|
(when (#{:check ":check"} type )
|
||||||
|
[:div
|
||||||
|
|
||||||
|
[:label.label "Bank"]
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[field "Bank Name"
|
||||||
|
[:input.input {:placeholder "Bank of America"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :bank-name]}]]
|
||||||
|
[field "Routing #"
|
||||||
|
[:input.input {:placeholder "104819123"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :routing]}]]
|
||||||
|
[field "Bank code"
|
||||||
|
[:input.input {:placeholder "12/10123"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :bank-code]}]]]
|
||||||
|
|
||||||
|
[:label.label "Checking account"]
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[field "Account #"
|
||||||
|
[:input.input {:placeholder "123456789"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :number]}]]
|
||||||
|
|
||||||
|
[field "Check Number"
|
||||||
|
[:input.input {:placeholder "10000"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :check-number]}]]]
|
||||||
|
[field "Yodlee Account"
|
||||||
|
[:input.input {:placeholder "Yodlee Account #"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :yodlee-account-id]}]]
|
||||||
|
|
||||||
|
])
|
||||||
|
(when (#{:credit ":credit"} type )
|
||||||
|
[:div
|
||||||
|
|
||||||
|
|
||||||
|
[:label.label "Account"]
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[field "Bank Name"
|
||||||
|
[:input.input {:placeholder "Bank of America"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :bank-name]}]]]
|
||||||
|
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[field "Account #"
|
||||||
|
[:input.input {:placeholder "123456789"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :number]}]]]
|
||||||
|
|
||||||
|
[field "Yodlee Account"
|
||||||
|
[:input.input {:placeholder "Yodlee Account #"
|
||||||
|
:type "text"
|
||||||
|
:field [:bank-accounts sort-order :yodlee-account-id]}]]])
|
||||||
|
[:div.field
|
||||||
|
[:label.label "Locations"]
|
||||||
|
[:div.control
|
||||||
|
[:p.help "If this account is location-specific, add the valid locations"]
|
||||||
|
[:div.field.has-addons
|
||||||
|
[:p.control
|
||||||
|
[:div.select
|
||||||
|
[raw-field
|
||||||
|
[:select {:type "select"
|
||||||
|
:style {:width "7em"}
|
||||||
|
:field [:bank-accounts sort-order :location-select]
|
||||||
|
:allow-nil? true
|
||||||
|
:spec (set (get-in new-client [:locations]))}
|
||||||
|
(map (fn [l] ^{:key l} [:option {:value l} l]) (get-in new-client [:locations]))]]]]
|
||||||
|
[:p.control {:on-click (dispatch-event [::add-location-to-bank-account sort-order]) } [:a.button "Add"]]]]
|
||||||
|
|
||||||
|
(if-let [locations (seq (get-in new-client [:bank-accounts sort-order :locations]))]
|
||||||
|
[:ul
|
||||||
|
(for [location locations]
|
||||||
|
^{:key location} [:li location ])]
|
||||||
|
[:i "This account applies to all locations"])]
|
||||||
|
[:div.field
|
||||||
|
[:label.checkbox
|
||||||
|
[raw-field
|
||||||
|
[:input {:type "checkbox"
|
||||||
|
:field [:bank-accounts sort-order :include-in-reports]}]]
|
||||||
|
" Include in reports"]]])
|
||||||
|
|
||||||
|
(when active?
|
||||||
|
[:footer.card-footer
|
||||||
|
[:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated sort-order])} "Done"]
|
||||||
|
(when new?
|
||||||
|
[:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed sort-order])} "Remove"])])]))
|
||||||
|
|
||||||
|
(defn new-client-form []
|
||||||
|
(let [{new-client :data } @(re-frame/subscribe [::forms/form ::form])
|
||||||
|
{:keys [form field raw-field error-notification submit-button ]} client-form
|
||||||
|
next-week-a (if (is-week-a? (t/now))
|
||||||
|
"This week"
|
||||||
|
"Next week")
|
||||||
|
next-week-b (if (is-week-a? (t/now))
|
||||||
|
"Next week"
|
||||||
|
"This week")]
|
||||||
|
|
||||||
|
[side-bar {:on-close (dispatch-event [::forms/form-closing ::form ])}
|
||||||
|
[form {:title "Add client"}
|
||||||
|
[field "Name"
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:field [:name]
|
||||||
|
:spec ::entity/name
|
||||||
|
}]]
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:p.help "Client code"
|
||||||
|
]
|
||||||
|
(if (:id new-client)
|
||||||
|
[:div.control
|
||||||
|
(:code new-client)]
|
||||||
|
[:div.control
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "code"
|
||||||
|
:field :code
|
||||||
|
:spec ::entity/code}]]])]
|
||||||
|
|
||||||
|
|
||||||
|
[field "Email"
|
||||||
|
[:input.input {:type "email"
|
||||||
|
:field :email
|
||||||
|
:spec ::entity/email}]]
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:p.help "Matches"]
|
||||||
|
[:div.control
|
||||||
|
[:div.field.has-addons
|
||||||
|
[:p.control
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:field :match}]]]
|
||||||
|
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-match])} "Add"]]]]
|
||||||
|
[:ul
|
||||||
|
(for [match (:matches new-client)]
|
||||||
|
^{:key match} [:li match [:a {:on-click (dispatch-event [::remove-match match])} [:span.icon [:span.fa.fa-times]]]])]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:p.help "Locations"]
|
||||||
|
[:div.control
|
||||||
|
[:div.field.has-addons
|
||||||
|
[:p.control
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:field :location}]]]
|
||||||
|
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-location])} "Add"]]]
|
||||||
|
[:ul
|
||||||
|
(for [location (:locations new-client)]
|
||||||
|
^{:key location} [:li location ])]]]
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:p.help "Location matches"]
|
||||||
|
[:div.control
|
||||||
|
[:div.field.has-addons
|
||||||
|
|
||||||
|
[:p.control
|
||||||
|
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:placeholder "San Jose"
|
||||||
|
:field [:location-match :match]}]]]
|
||||||
|
[:p.control
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:placeholder "DT"
|
||||||
|
:field [:location-match :location]}]]]
|
||||||
|
[:p.control [:button.button.is-primary {:on-click (dispatch-event [::add-new-location-match])} "Add"]]]
|
||||||
|
|
||||||
|
[:ul
|
||||||
|
(for [[index {:keys [location match]}] (map vector (range) (:location-matches new-client))]
|
||||||
|
^{:key index} [:li match "->" location [:a {:on-click (dispatch-event [::remove-location-match index])} [:span.icon
|
||||||
|
[:span.fa.fa-times]]]])]]]
|
||||||
|
|
||||||
|
[:div {:style {:padding-bottom "0.75em" :padding-top "0.75em"}}
|
||||||
|
[:h2.subtitle "Address"]
|
||||||
|
[address-field {:field [:address]
|
||||||
|
:event [::forms/change ::form]
|
||||||
|
:subscription new-client}]]
|
||||||
|
|
||||||
|
[:h2.subtitle "Bank accounts"]
|
||||||
|
(for [bank-account (sort-by :sort-order (:bank-accounts new-client))]
|
||||||
|
^{:key (:sort-order bank-account)}
|
||||||
|
[bank-account-card new-client bank-account (= 0 (:sort-order bank-account)) (= (:sort-order bank-account) (dec (count (:bank-accounts new-client))))])
|
||||||
|
|
||||||
|
[:div.columns
|
||||||
|
[:div.column.is-third
|
||||||
|
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :credit])} "Add Credit Account"]]
|
||||||
|
[:div.column.is-third
|
||||||
|
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :check])} "Add Checking Account"]]
|
||||||
|
[:div.column.is-third
|
||||||
|
[:a.button.is-primary.is-outlined.is-fullwidth {:on-click (dispatch-event [::add-new-bank-account :cash])} "Add Cash Account"]]]
|
||||||
|
|
||||||
|
[:h2.subtitle "Cash flow"]
|
||||||
|
[:label.label (str "Week A (" next-week-a ")")]
|
||||||
|
[field "Regular Credits"
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "500.00"
|
||||||
|
:field [:week-a-credits]
|
||||||
|
:step "0.01"}]]
|
||||||
|
[field "Regular Debits"
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "150.00"
|
||||||
|
:field [:week-a-debits]
|
||||||
|
:step "0.01"}]]
|
||||||
|
[:label.label (str "Week B (" next-week-b ")")]
|
||||||
|
[field "Regular Credits"
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "1000.00"
|
||||||
|
:field [:week-b-credits]
|
||||||
|
:step "0.01"}]]
|
||||||
|
[field "Regular Debits"
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "250.00"
|
||||||
|
:field [:week-b-debits]
|
||||||
|
:step "0.01"}]]
|
||||||
|
[:div.field
|
||||||
|
[:label.label "Forecasted transactions"]
|
||||||
|
[:div.control
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
|
||||||
|
[:p.control
|
||||||
|
[:p.help "Identifier"]
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:placeholder "Identifier"
|
||||||
|
:field [:new-forecasted-transaction :identifier]}]]]
|
||||||
|
[:p.control
|
||||||
|
[:p.help "Day of month"]
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "Day of month"
|
||||||
|
:step "1"
|
||||||
|
:field [:new-forecasted-transaction :day-of-month]}]]]
|
||||||
|
[:p.control
|
||||||
|
[:p.help "Amount"]
|
||||||
|
[raw-field
|
||||||
|
[:input.input {:type "number"
|
||||||
|
:placeholder "250.00"
|
||||||
|
:field [:new-forecasted-transaction :amount]
|
||||||
|
:step "0.01"}]]]
|
||||||
|
[:a.button {:on-click (dispatch-event [::add-forecasted-transaction])} "Add"]]]
|
||||||
|
|
||||||
|
[:ul
|
||||||
|
(for [forecasted-transaction (:forecasted-transactions new-client)]
|
||||||
|
^{:key (or (:id forecasted-transaction)
|
||||||
|
(:temp-id forecasted-transaction))}
|
||||||
|
[:li (:identifier forecasted-transaction) ": " (nf (:amount forecasted-transaction)) " on day " (:day-of-month forecasted-transaction) " of the month"
|
||||||
|
[:a {:on-click (dispatch-event [::remove-forecasted-transaction (or (:id forecasted-transaction)
|
||||||
|
(:temp-id forecasted-transaction))])} [:span.icon [:span.fa.fa-times]]]])]]
|
||||||
|
|
||||||
|
[error-notification]
|
||||||
|
[submit-button "Save"]]]))
|
||||||
79
src/cljs/auto_ap/views/pages/admin/clients/side_bar.cljs
Normal file
79
src/cljs/auto_ap/views/pages/admin/clients/side_bar.cljs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
(ns auto-ap.views.pages.admin.clients.side-bar
|
||||||
|
(:require
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[auto-ap.views.utils :refer [dispatch-value-change]]
|
||||||
|
[auto-ap.subs :as subs]))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::specific-filters
|
||||||
|
(fn [db ]
|
||||||
|
(::filters db nil)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::filters
|
||||||
|
:<- [::specific-filters]
|
||||||
|
:<- [::subs/query-params]
|
||||||
|
(fn [[specific-filters vendors-by-id query-params] ]
|
||||||
|
(let [url-filters (-> query-params
|
||||||
|
(select-keys #{:name
|
||||||
|
:code}))
|
||||||
|
url-filters {:name (str (:name url-filters))
|
||||||
|
:code (str (:code url-filters))}]
|
||||||
|
(merge url-filters specific-filters ))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::filter
|
||||||
|
:<- [::filters]
|
||||||
|
(fn [filters [_ which]]
|
||||||
|
(get filters which)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::filter-params
|
||||||
|
:<- [::settled-filters]
|
||||||
|
:<- [::filters]
|
||||||
|
:<- [::subs/active-page]
|
||||||
|
(fn [[settled-filters filters ap ]]
|
||||||
|
(let [filters (or settled-filters filters)]
|
||||||
|
{:name (:name filters)
|
||||||
|
:code (:code filters)})))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::settled-filters
|
||||||
|
(fn [db ]
|
||||||
|
(::settled-filters db)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::filters-settled
|
||||||
|
(fn [{:keys [db]} [_ & params]]
|
||||||
|
{:db (assoc db ::settled-filters @(re-frame/subscribe [::filters]))}))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::filter-changed
|
||||||
|
(fn [{:keys [db]} [_ & params]]
|
||||||
|
(let [[a b c] params
|
||||||
|
[which val] (if (= 3 (count params))
|
||||||
|
[(into [a] b) c]
|
||||||
|
[[a] b])]
|
||||||
|
{:db (assoc-in db (into [::filters] which) val)
|
||||||
|
:dispatch-debounce {:event [::filters-settled]
|
||||||
|
:time 800
|
||||||
|
:key ::filters}})))
|
||||||
|
|
||||||
|
|
||||||
|
(defn client-side-bar []
|
||||||
|
[:div
|
||||||
|
[:p.menu-label "Name"]
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:div.control [:input.input {:placeholder "Harry's Food Products"
|
||||||
|
:value @(re-frame/subscribe [::filter :name])
|
||||||
|
:on-change (dispatch-value-change [::filter-changed :name])} ]]]
|
||||||
|
|
||||||
|
[:p.menu-label "Code"]
|
||||||
|
|
||||||
|
[:div.field
|
||||||
|
[:div.control [:input.input {:placeholder "CBC"
|
||||||
|
:value @(re-frame/subscribe [::filter :code])
|
||||||
|
:on-change (dispatch-value-change [::filter-changed :code])} ]]]])
|
||||||
|
|
||||||
|
|
||||||
53
src/cljs/auto_ap/views/pages/admin/clients/table.cljs
Normal file
53
src/cljs/auto_ap/views/pages/admin/clients/table.cljs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
(ns auto-ap.views.pages.admin.clients.table
|
||||||
|
(:require [auto-ap.subs :as subs]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[auto-ap.views.pages.admin.clients.form :as form]
|
||||||
|
[auto-ap.views.utils :refer [action-cell-width]]
|
||||||
|
[auto-ap.views.components.grid :as grid]
|
||||||
|
[auto-ap.views.components.buttons :as buttons]))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::specific-params
|
||||||
|
(fn [db]
|
||||||
|
(::params db)))
|
||||||
|
|
||||||
|
(re-frame/reg-event-fx
|
||||||
|
::params-changed
|
||||||
|
(fn [{:keys [db]} [_ p]]
|
||||||
|
{:db (assoc db ::params p)}))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::params
|
||||||
|
:<- [::specific-params]
|
||||||
|
:<- [::subs/query-params]
|
||||||
|
(fn [[specific-params query-params]]
|
||||||
|
(merge (select-keys query-params #{:start :sort}) specific-params )))
|
||||||
|
|
||||||
|
|
||||||
|
(defn clients-table [{:keys [page status]}]
|
||||||
|
[grid/grid {:on-params-change (fn [p]
|
||||||
|
(re-frame/dispatch [::params-changed p]))
|
||||||
|
:status status
|
||||||
|
:params @(re-frame/subscribe [::params])
|
||||||
|
:column-count 5}
|
||||||
|
[grid/controls page]
|
||||||
|
[grid/table {:fullwidth true}
|
||||||
|
[grid/header
|
||||||
|
[grid/row {}
|
||||||
|
[grid/header-cell {} "Name"]
|
||||||
|
[grid/header-cell {:style {:width "20em"}} "Code"]
|
||||||
|
[grid/header-cell {} "Locations"]
|
||||||
|
[grid/header-cell {} "Email"]
|
||||||
|
[grid/header-cell {:style {:width (action-cell-width 1)}}]]
|
||||||
|
]
|
||||||
|
[grid/body
|
||||||
|
(for [{:keys [id name email code locations] :as c} (:data page)]
|
||||||
|
^{:key (str name "-" id )}
|
||||||
|
[grid/row
|
||||||
|
[grid/cell {} name]
|
||||||
|
[grid/cell {} code]
|
||||||
|
[grid/cell {} (str/join ", " locations)]
|
||||||
|
[grid/cell {} email]
|
||||||
|
[grid/cell {} [buttons/fa-icon {:event [::form/editing id]
|
||||||
|
:icon :fa-pencil}]]])]]])
|
||||||
@@ -106,59 +106,58 @@
|
|||||||
opc (fn [p]
|
opc (fn [p]
|
||||||
(re-frame/dispatch [::params-changed p]))
|
(re-frame/dispatch [::params-changed p]))
|
||||||
states @(re-frame/subscribe [::status/multi ::run])]
|
states @(re-frame/subscribe [::status/multi ::run])]
|
||||||
[:div
|
[grid/grid {:on-params-change opc
|
||||||
[grid/grid {:on-params-change opc
|
:params @(re-frame/subscribe [::table-params])
|
||||||
:params @(re-frame/subscribe [::table-params])
|
:status status
|
||||||
:status status
|
:column-count 6}
|
||||||
:column-count 6}
|
[grid/controls {:start start :end end :count count :total total}]
|
||||||
[grid/controls {:start start :end end :count count :total total}]
|
[grid/table {:fullwidth true }
|
||||||
[grid/table {:fullwidth true }
|
[grid/header
|
||||||
[grid/header
|
[grid/row {}
|
||||||
[grid/row {}
|
[grid/sortable-header-cell {:sort-key "client"
|
||||||
[grid/sortable-header-cell {:sort-key "client"
|
:sort-name "Client"}
|
||||||
:sort-name "Client"}
|
"Client"]
|
||||||
"Client"]
|
|
||||||
|
|
||||||
[grid/sortable-header-cell {:sort-key "bank-account"
|
[grid/sortable-header-cell {:sort-key "bank-account"
|
||||||
:sort-name "Bank Account"}
|
:sort-name "Bank Account"}
|
||||||
"Bank Account"]
|
"Bank Account"]
|
||||||
|
|
||||||
[grid/sortable-header-cell {:sort-key "description"
|
[grid/sortable-header-cell {:sort-key "description"
|
||||||
:sort-name "Description"}
|
:sort-name "Description"}
|
||||||
"Description"]
|
"Description"]
|
||||||
|
|
||||||
[grid/header-cell {:style {:width "12em"}} "Amount"]
|
[grid/header-cell {:style {:width "12em"}} "Amount"]
|
||||||
|
|
||||||
[grid/sortable-header-cell {:sort-key "note"
|
[grid/sortable-header-cell {:sort-key "note"
|
||||||
:sort-name "Note"}
|
:sort-name "Note"}
|
||||||
"Note"]
|
"Note"]
|
||||||
|
|
||||||
[grid/header-cell {:style {:width (action-cell-width 3)}}]]]
|
[grid/header-cell {:style {:width (action-cell-width 3)}}]]]
|
||||||
[grid/body
|
[grid/body
|
||||||
(for [{:keys [client bank-account description amount-lte amount-gte note id] :as r} transaction-rules]
|
(for [{:keys [client bank-account description amount-lte amount-gte note id] :as r} transaction-rules]
|
||||||
^{:key id}
|
^{:key id}
|
||||||
[grid/row {:class (:class r)}
|
[grid/row {:class (:class r)}
|
||||||
[grid/cell {} (:name client)]
|
[grid/cell {} (:name client)]
|
||||||
[grid/cell {} (:name bank-account)]
|
[grid/cell {} (:name bank-account)]
|
||||||
[grid/cell {} description]
|
[grid/cell {} description]
|
||||||
[grid/cell {:class "has-text-right"}
|
[grid/cell {:class "has-text-right"}
|
||||||
(cond (and amount-gte amount-lte)
|
(cond (and amount-gte amount-lte)
|
||||||
(str (->$ amount-gte) " - " (->$ amount-lte))
|
(str (->$ amount-gte) " - " (->$ amount-lte))
|
||||||
|
|
||||||
amount-gte
|
amount-gte
|
||||||
(str ">=" (->$ amount-gte))
|
(str ">=" (->$ amount-gte))
|
||||||
|
|
||||||
amount-lte
|
amount-lte
|
||||||
(str "<=" (->$ amount-lte))
|
(str "<=" (->$ amount-lte))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
"")]
|
"")]
|
||||||
[grid/cell {} note]
|
[grid/cell {} note]
|
||||||
[grid/cell {}
|
[grid/cell {}
|
||||||
[:div.buttons
|
[:div.buttons
|
||||||
[buttons/fa-icon {:event [::run-clicked r] :icon :fa-play :class (status/class-for (get states (:id r)))}]
|
[buttons/fa-icon {:event [::run-clicked r] :icon :fa-play :class (status/class-for (get states (:id r)))}]
|
||||||
[buttons/sl-icon {:event [::request-delete r] :icon :icon-bin-2}]
|
[buttons/sl-icon {:event [::request-delete r] :icon :icon-bin-2}]
|
||||||
[buttons/fa-icon {:event [::form/editing r] :icon :fa-pencil}]]]])]]]]))
|
[buttons/fa-icon {:event [::form/editing r] :icon :fa-pencil}]]]])]]]))
|
||||||
|
|
||||||
(defn table [params]
|
(defn table [params]
|
||||||
(r/create-class {:component-will-unmount (dispatch-event [::unmounted])
|
(r/create-class {:component-will-unmount (dispatch-event [::unmounted])
|
||||||
|
|||||||
@@ -89,8 +89,7 @@
|
|||||||
(defn admin-users-content []
|
(defn admin-users-content []
|
||||||
[:div
|
[:div
|
||||||
[:h1.title "Users"]
|
[:h1.title "Users"]
|
||||||
[users-table]
|
[users-table]])
|
||||||
[form/form]])
|
|
||||||
|
|
||||||
|
|
||||||
(defn admin-users-page []
|
(defn admin-users-page []
|
||||||
|
|||||||
Reference in New Issue
Block a user