Form builder as a way to simplify some things
This commit is contained in:
@@ -17,14 +17,6 @@
|
|||||||
:data
|
:data
|
||||||
(get-in f))))
|
(get-in f))))
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
|
||||||
::is-loading?
|
|
||||||
(fn [db [_ x]]
|
|
||||||
(if (#{"loading" :loading} (get-in db [::forms x :status]) )
|
|
||||||
true
|
|
||||||
false)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
::loading-class
|
::loading-class
|
||||||
(fn [db [_ x]]
|
(fn [db [_ x]]
|
||||||
@@ -43,10 +35,6 @@
|
|||||||
:data data
|
:data data
|
||||||
:complete-listener complete-listener})))
|
:complete-listener complete-listener})))
|
||||||
|
|
||||||
(defn ^:depracated saved-form [db form data]
|
|
||||||
(update-in db [::forms form]
|
|
||||||
assoc :error nil :status nil :data data))
|
|
||||||
|
|
||||||
(defn triggers-saved [form data-key]
|
(defn triggers-saved [form data-key]
|
||||||
(i/->interceptor
|
(i/->interceptor
|
||||||
:id :triggers-saved
|
:id :triggers-saved
|
||||||
@@ -55,7 +43,6 @@
|
|||||||
:after (fn [context]
|
:after (fn [context]
|
||||||
(let [db (i/get-coeffect context :db)
|
(let [db (i/get-coeffect context :db)
|
||||||
result (get-in (i/get-coeffect context :event) [1 data-key])]
|
result (get-in (i/get-coeffect context :event) [1 data-key])]
|
||||||
|
|
||||||
(cond-> context
|
(cond-> context
|
||||||
true
|
true
|
||||||
(i/assoc-effect :db (update-in db
|
(i/assoc-effect :db (update-in db
|
||||||
|
|||||||
106
src/cljs/auto_ap/forms/builder.cljs
Normal file
106
src/cljs/auto_ap/forms/builder.cljs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
(ns auto-ap.forms.builder
|
||||||
|
(:require
|
||||||
|
[auto-ap.views.utils :refer [bind-field]]
|
||||||
|
[re-frame.core :as re-frame]
|
||||||
|
[react :as react]
|
||||||
|
[reagent.core :as r]
|
||||||
|
[auto-ap.forms :as forms]
|
||||||
|
[auto-ap.status :as status]))
|
||||||
|
|
||||||
|
(defonce ^js/React.Context form-context (react/createContext "default"))
|
||||||
|
(def ^js/React.Provider Provider (. form-context -Provider))
|
||||||
|
(def ^js/React.Consumer Consumer (. form-context -Consumer))
|
||||||
|
|
||||||
|
(defonce ^js/React.Context form-scope-context (react/createContext []))
|
||||||
|
(def ^js/React.Provider FormScopeProvider (. form-scope-context -Provider))
|
||||||
|
(def ^js/React.Consumer FormScopeConsumer (. form-scope-context -Consumer))
|
||||||
|
|
||||||
|
(defn builder [{:keys [can-submit data-sub change-event submit-event id fullwidth?] :as z}]
|
||||||
|
(let [data-sub (or data-sub [::forms/form id])
|
||||||
|
change-event (or change-event [::forms/change id])
|
||||||
|
{:keys [data error]} @(re-frame/subscribe data-sub)]
|
||||||
|
(r/create-element Provider #js {:value #js {:can-submit @(re-frame/subscribe can-submit)
|
||||||
|
:change-event change-event
|
||||||
|
:submit-event submit-event
|
||||||
|
:error error
|
||||||
|
:status @(re-frame/subscribe [::status/single id])
|
||||||
|
:id id
|
||||||
|
:data data
|
||||||
|
:fullwidth? fullwidth?}}
|
||||||
|
(r/as-element
|
||||||
|
(into [:form {:on-submit (fn [e]
|
||||||
|
(when (.-stopPropagation e)
|
||||||
|
(.stopPropagation e)
|
||||||
|
(.preventDefault e))
|
||||||
|
(when can-submit
|
||||||
|
(re-frame/dispatch-sync (vec (conj submit-event {})))))}]
|
||||||
|
(r/children (r/current-component)))))))
|
||||||
|
|
||||||
|
(defn raw-field []
|
||||||
|
(let [[child] (r/children (r/current-component))]
|
||||||
|
[:> Consumer {}
|
||||||
|
(fn [consume-form]
|
||||||
|
(r/as-element
|
||||||
|
[:> FormScopeConsumer {}
|
||||||
|
(fn [form-scope]
|
||||||
|
(r/as-element
|
||||||
|
[bind-field (-> child
|
||||||
|
(update-in [1 :field] (fn [f]
|
||||||
|
(cond
|
||||||
|
(sequential? f)
|
||||||
|
(into form-scope f)
|
||||||
|
|
||||||
|
f
|
||||||
|
(conj form-scope f)
|
||||||
|
|
||||||
|
:else
|
||||||
|
nil)))
|
||||||
|
(assoc-in [1 :subscription] (aget consume-form "data"))
|
||||||
|
(assoc-in [1 :event] (aget consume-form "change-event")))]))]))]))
|
||||||
|
|
||||||
|
(defn with-scope [{:keys [scope]}]
|
||||||
|
(r/create-element FormScopeProvider #js {:value scope}
|
||||||
|
(r/as-element (into [:<>]
|
||||||
|
(r/children (r/current-component))))))
|
||||||
|
|
||||||
|
(defn field []
|
||||||
|
(let [[label child] (r/children (r/current-component))]
|
||||||
|
[:> Consumer {}
|
||||||
|
(fn [consume]
|
||||||
|
(r/as-element
|
||||||
|
[:div.field
|
||||||
|
(when label (if (aget consume "fullwidth?") [:p.help label]
|
||||||
|
[:label.label label]))
|
||||||
|
[:div.control [raw-field {} child]]]))]))
|
||||||
|
|
||||||
|
(defn section [{:keys [title]}]
|
||||||
|
[:<>
|
||||||
|
[:h4.is-4.title title]
|
||||||
|
[:hr]
|
||||||
|
(into [:div {:style {:margin-bottom "5em"}}]
|
||||||
|
(r/children (r/current-component)))])
|
||||||
|
|
||||||
|
(defn submit-button []
|
||||||
|
(let [[child] (r/children (r/current-component))]
|
||||||
|
[:> Consumer {}
|
||||||
|
(fn [consume]
|
||||||
|
(let [status (aget consume "status")
|
||||||
|
can-submit (aget consume "can-submit")
|
||||||
|
fullwidth? (aget consume "fullwidth?")]
|
||||||
|
(r/as-element
|
||||||
|
[:button.button.is-medium.is-primary {:disabled (or (status/disabled-for status)
|
||||||
|
(not can-submit))
|
||||||
|
:class (cond-> (status/class-for status)
|
||||||
|
fullwidth? (conj "is-fullwidth")) }
|
||||||
|
child])))]))
|
||||||
|
|
||||||
|
(defn error-notification []
|
||||||
|
(let [[child] (r/children (r/current-component))]
|
||||||
|
[:> Consumer {}
|
||||||
|
(fn [consume]
|
||||||
|
(r/as-element
|
||||||
|
(when-let [error (aget consume "error")]
|
||||||
|
^{:key error}
|
||||||
|
[:div.has-text-danger.animated.fadeInUp {} error])))]))
|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
(ns auto-ap.views.components.address
|
(ns auto-ap.views.components.address
|
||||||
(:require [auto-ap.entities.address :as address]
|
(:require [auto-ap.entities.address :as address]
|
||||||
[auto-ap.views.utils :refer [dispatch-value-change dispatch-event bind-field horizontal-field]]))
|
[auto-ap.views.utils :refer [dispatch-value-change dispatch-event bind-field horizontal-field]]
|
||||||
|
[auto-ap.forms.builder :as form-builder]))
|
||||||
|
|
||||||
(defn address-field [{:keys [event field subscription]}]
|
(defn address-field [{:keys [event field subscription]}]
|
||||||
[:span
|
[:span
|
||||||
@@ -58,3 +59,50 @@
|
|||||||
:event event
|
:event event
|
||||||
:subscription subscription
|
:subscription subscription
|
||||||
:placeholder "95014"}]]]]])
|
:placeholder "95014"}]]]]])
|
||||||
|
|
||||||
|
(defn address2-field []
|
||||||
|
[:span
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[:div.control
|
||||||
|
[:p.help "Address"]
|
||||||
|
[form-builder/raw-field
|
||||||
|
[:input.input.is-expanded {:type "text"
|
||||||
|
:placeholder "1700 Pennsylvania Ave"
|
||||||
|
:field [:street1]
|
||||||
|
:spec ::address/street1}]]]]
|
||||||
|
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[:div.control
|
||||||
|
[form-builder/raw-field
|
||||||
|
[:input.input.is-expanded {:type "text"
|
||||||
|
:placeholder "Suite 400"
|
||||||
|
:field [:street2]
|
||||||
|
:spec ::address/street2}]]]]
|
||||||
|
|
||||||
|
[horizontal-field
|
||||||
|
nil
|
||||||
|
[:div.control
|
||||||
|
[:p.help "City"]
|
||||||
|
[form-builder/raw-field
|
||||||
|
[:input.input.is-expanded {:type "text"
|
||||||
|
:placeholder "Cupertino"
|
||||||
|
:field [:city]
|
||||||
|
:spec ::address/city}]]]
|
||||||
|
[:div.control
|
||||||
|
[:p.help "State"]
|
||||||
|
[form-builder/raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:placeholder "CA"
|
||||||
|
:field [:state]
|
||||||
|
:spec ::address/state
|
||||||
|
:size 2
|
||||||
|
:max-length "2"}]]]
|
||||||
|
[:div.control
|
||||||
|
[:p.help "Zip"]
|
||||||
|
[form-builder/raw-field
|
||||||
|
[:input.input {:type "text"
|
||||||
|
:field [:zip]
|
||||||
|
:spec ::address/zip
|
||||||
|
:placeholder "95014"}]]]]])
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
(ns auto-ap.views.pages.admin.clients
|
(ns auto-ap.views.pages.admin.clients
|
||||||
(:require
|
(:require
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.routes :as routes]
|
||||||
[auto-ap.subs :as subs]
|
|
||||||
[auto-ap.status :as status]
|
[auto-ap.status :as status]
|
||||||
|
[auto-ap.subs :as subs]
|
||||||
[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.components.grid :as grid]
|
[auto-ap.views.components.grid :as grid]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
[auto-ap.views.components.layouts :refer [side-bar-layout]]
|
||||||
[auto-ap.views.pages.admin.clients.form :as form]
|
[auto-ap.views.pages.admin.clients.form :as form]
|
||||||
[auto-ap.views.pages.admin.clients.side-bar :as side-bar]
|
[auto-ap.views.pages.admin.clients.side-bar :as side-bar]
|
||||||
[auto-ap.views.pages.admin.clients.table :as table]
|
[auto-ap.views.pages.admin.clients.table :as table]
|
||||||
[auto-ap.views.utils :refer [dispatch-event transition switch-transition with-user transition-group]]
|
[auto-ap.views.pages.page-stack :as page-stack]
|
||||||
|
[auto-ap.views.utils :refer [with-user]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as r]
|
[vimsical.re-frame.fx.track :as track]))
|
||||||
[vimsical.re-frame.fx.track :as track]
|
|
||||||
[bidi.bidi :as bidi]
|
|
||||||
[auto-ap.routes :as routes]))
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
(re-frame/reg-event-db
|
||||||
::received-intuit-bank-accounts
|
::received-intuit-bank-accounts
|
||||||
@@ -25,7 +24,7 @@
|
|||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::mounted
|
::mounted
|
||||||
[with-user]
|
[with-user]
|
||||||
(fn [{:keys [db user]} _]
|
(fn [{:keys [user]} _]
|
||||||
{::track/register {:id ::params
|
{::track/register {:id ::params
|
||||||
:subscription [::params]
|
:subscription [::params]
|
||||||
:event-fn (fn [params] [::params-change params])}
|
:event-fn (fn [params] [::params-change params])}
|
||||||
@@ -49,14 +48,6 @@
|
|||||||
(seq filter-params) (merge filter-params)
|
(seq filter-params) (merge filter-params)
|
||||||
(seq table-params) (merge table-params))))
|
(seq table-params) (merge table-params))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(re-frame/reg-event-db
|
|
||||||
::new
|
|
||||||
(fn [db [_ client-id]]
|
|
||||||
(-> db
|
|
||||||
(forms/start-form ::form/form {:bank-accounts []}))))
|
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::params-change
|
::params-change
|
||||||
(fn [_ [_ params]]
|
(fn [_ [_ params]]
|
||||||
@@ -75,125 +66,28 @@
|
|||||||
(assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) matching-clients)
|
(assoc (grid/virtual-paginate-controls (:start params ) (:per-page params) matching-clients)
|
||||||
:data (grid/virtual-paginate (:start params) (:per-page params) matching-clients)))))
|
:data (grid/virtual-paginate (:start params) (:per-page params) matching-clients)))))
|
||||||
|
|
||||||
|
|
||||||
(defn stacked-page [& children]
|
|
||||||
[:div
|
|
||||||
(->> children
|
|
||||||
(reverse)
|
|
||||||
(filter identity)
|
|
||||||
first)])
|
|
||||||
|
|
||||||
(defn hierachy []
|
|
||||||
(let [last-stack-size (r/atom (->> (r/current-component)
|
|
||||||
r/children
|
|
||||||
(filter identity) count))
|
|
||||||
forward? (r/atom false)]
|
|
||||||
(fn []
|
|
||||||
(let [stack (filter identity (r/children (r/current-component)))
|
|
||||||
current-stack-size (count stack)
|
|
||||||
current-child (last stack)]
|
|
||||||
(when (not= current-stack-size @last-stack-size)
|
|
||||||
(reset! forward? (> current-stack-size @last-stack-size))
|
|
||||||
(reset! last-stack-size current-stack-size))
|
|
||||||
[:div
|
|
||||||
[switch-transition {:mode "in-out"}
|
|
||||||
|
|
||||||
^{:key current-stack-size}
|
|
||||||
[transition
|
|
||||||
{:timeout 100
|
|
||||||
:exit true
|
|
||||||
:in true #_(= current-stack- (:key (meta child)))
|
|
||||||
:appear (> current-stack-size 1)}
|
|
||||||
(clj->js (fn [state]
|
|
||||||
(r/as-element
|
|
||||||
[:div {:style {
|
|
||||||
:position (cond
|
|
||||||
(= "entered" state)
|
|
||||||
""
|
|
||||||
|
|
||||||
(= "entering" state)
|
|
||||||
"absolute"
|
|
||||||
|
|
||||||
(= "exiting" state)
|
|
||||||
"absolute"
|
|
||||||
|
|
||||||
(= "exited" state)
|
|
||||||
"")
|
|
||||||
|
|
||||||
:transition "opacity 300ms ease-in-out, transform 300ms ease-in-out"
|
|
||||||
|
|
||||||
:opacity (cond
|
|
||||||
(= "entered" state)
|
|
||||||
""
|
|
||||||
|
|
||||||
(= "entering" state)
|
|
||||||
0.0
|
|
||||||
|
|
||||||
(= "exiting" state)
|
|
||||||
1.0
|
|
||||||
|
|
||||||
(= "exited" state)
|
|
||||||
0.0)
|
|
||||||
:transform (if @forward?
|
|
||||||
(cond
|
|
||||||
(= "entered" state)
|
|
||||||
""
|
|
||||||
|
|
||||||
(= "entering" state)
|
|
||||||
"translateX(100%)"
|
|
||||||
|
|
||||||
(= "exiting" state)
|
|
||||||
"translateX(-100%)"
|
|
||||||
|
|
||||||
(= "exited" state)
|
|
||||||
"translateX(0%)")
|
|
||||||
(cond
|
|
||||||
(= "entered" state)
|
|
||||||
""
|
|
||||||
|
|
||||||
(= "entering" state)
|
|
||||||
"translateX(-100%)"
|
|
||||||
|
|
||||||
(= "exiting" state)
|
|
||||||
"translateX(100%)"
|
|
||||||
|
|
||||||
(= "exited" state)
|
|
||||||
"translateX(0%)"))}}
|
|
||||||
current-child])))]]
|
|
||||||
]))))
|
|
||||||
|
|
||||||
(defn test-appear []
|
|
||||||
[:div
|
|
||||||
[hierachy
|
|
||||||
[table/clients-table {:page @(re-frame/subscribe [::page])
|
|
||||||
:status @(re-frame/subscribe [::status/single ::page])}]
|
|
||||||
(when (#{:admin-specific-bank-account :admin-specific-client} @(re-frame/subscribe [::subs/active-route]))
|
|
||||||
[form/new-client-form])
|
|
||||||
(when (= :admin-specific-bank-account @(re-frame/subscribe [::subs/active-route]))
|
|
||||||
[:div "This is a bank account!"])]])
|
|
||||||
|
|
||||||
(defn breadcrumbs []
|
|
||||||
[:h1.title.is-1
|
|
||||||
(cond (= :admin-clients @(re-frame/subscribe [::subs/active-route]))
|
|
||||||
"Clients"
|
|
||||||
|
|
||||||
:else
|
|
||||||
[:span [:a {:href (bidi/path-for routes/routes :admin-clients)}
|
|
||||||
"Clients"]
|
|
||||||
" / "
|
|
||||||
(or (:name (:data @(re-frame/subscribe [::forms/form ::form/form])))
|
|
||||||
[:i "New client"])])
|
|
||||||
])
|
|
||||||
(def admin-clients-content
|
(def admin-clients-content
|
||||||
(with-meta
|
(with-meta
|
||||||
(fn []
|
(fn []
|
||||||
[:div
|
[:div
|
||||||
[breadcrumbs]
|
[page-stack/page-stack
|
||||||
|
{:active @(re-frame/subscribe [::subs/active-route])
|
||||||
|
:pages [{:key :admin-clients
|
||||||
|
:breadcrumb "Clients"
|
||||||
|
:content [:<>
|
||||||
[:div.is-pulled-right
|
[:div.is-pulled-right
|
||||||
(when (= :admin-clients @(re-frame/subscribe [::subs/active-route]))
|
[:a.button.is-primary.is-outlined {:href (bidi/path-for routes/routes :admin-specific-client :id "new")} "New client"]]
|
||||||
[:a.button.is-primary.is-outlined {:href (bidi/path-for routes/routes :admin-specific-client :id "new")} "New client"])]
|
[table/clients-table {:page @(re-frame/subscribe [::page])
|
||||||
[test-appear]
|
:status @(re-frame/subscribe [::status/single ::page])}]]}
|
||||||
])
|
|
||||||
|
{:key :admin-specific-client
|
||||||
|
:breadcrumb [:span [:a {:href (bidi/path-for routes/routes :admin-clients)}
|
||||||
|
"Clients"]
|
||||||
|
" / "
|
||||||
|
(or (:name @(re-frame/subscribe [::form/client]))
|
||||||
|
[:i "New client"])]
|
||||||
|
:content [form/new-client-form]}
|
||||||
|
]}]])
|
||||||
{:component-did-mount #(re-frame/dispatch [::mounted])
|
{:component-did-mount #(re-frame/dispatch [::mounted])
|
||||||
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])}))
|
:component-will-unmount #(re-frame/dispatch-sync [::unmounted])}))
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
(ns auto-ap.views.pages.admin.clients.form
|
(ns auto-ap.views.pages.admin.clients.form
|
||||||
(:require [auto-ap.entities.clients :as entity]
|
(:require
|
||||||
[auto-ap.forms :as forms]
|
[auto-ap.entities.clients :as entity]
|
||||||
[auto-ap.subs :as subs]
|
|
||||||
[auto-ap.events :as events]
|
[auto-ap.events :as events]
|
||||||
[auto-ap.views.components.address :refer [address-field]]
|
[auto-ap.forms :as forms]
|
||||||
|
[auto-ap.forms.builder :as form-builder]
|
||||||
|
[auto-ap.routes :as routes]
|
||||||
|
[auto-ap.subs :as subs]
|
||||||
|
[auto-ap.views.components.address :refer [address2-field]]
|
||||||
|
[react-signature-canvas]
|
||||||
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
[auto-ap.views.components.typeahead :refer [typeahead-v3]]
|
||||||
[auto-ap.views.components.typeahead.vendor
|
[auto-ap.views.components.typeahead.vendor
|
||||||
:refer [search-backed-typeahead]]
|
:refer [search-backed-typeahead]]
|
||||||
[auto-ap.views.components.layouts :refer [side-bar]]
|
|
||||||
[auto-ap.views.utils
|
[auto-ap.views.utils
|
||||||
:refer
|
:refer [date->str
|
||||||
[date->str
|
|
||||||
date-picker
|
date-picker
|
||||||
|
date-picker-friendly
|
||||||
dispatch-event
|
dispatch-event
|
||||||
horizontal-field
|
horizontal-field
|
||||||
multi-field
|
multi-field
|
||||||
standard]]
|
standard]]
|
||||||
|
[bidi.bidi :as bidi]
|
||||||
[cljs-time.coerce :as coerce]
|
[cljs-time.coerce :as coerce]
|
||||||
[cljs-time.core :as t]
|
[cljs-time.core :as t]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[vimsical.re-frame.cofx.inject :as inject]
|
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as r]
|
[reagent.core :as r]
|
||||||
[react-signature-canvas]
|
[react-signature-canvas]
|
||||||
[bidi.bidi :as bidi]
|
[vimsical.re-frame.cofx.inject :as inject]))
|
||||||
[auto-ap.routes :as routes]))
|
|
||||||
|
|
||||||
(def signature-canvas (r/adapt-react-class (.-default react-signature-canvas)))
|
(def signature-canvas (r/adapt-react-class (.-default react-signature-canvas)))
|
||||||
|
|
||||||
@@ -196,13 +198,18 @@
|
|||||||
:bank-code bank-code})
|
:bank-code bank-code})
|
||||||
(:bank-accounts new-client-data))})))
|
(:bank-accounts new-client-data))})))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
::client
|
||||||
|
:<- [::subs/route-params]
|
||||||
|
:<- [::subs/clients-by-id]
|
||||||
|
(fn [[rp clients-by-id]]
|
||||||
|
(or (clients-by-id (:id rp))
|
||||||
|
{})))
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::mounted
|
::mounted
|
||||||
[(re-frame/inject-cofx ::inject/sub [::subs/route-params])
|
[(re-frame/inject-cofx ::inject/sub [::client])]
|
||||||
(re-frame/inject-cofx ::inject/sub [::subs/clients-by-id])]
|
(fn [{:keys [db] ::keys [client]} _]
|
||||||
(fn [{:keys [db]
|
|
||||||
::subs/keys [clients-by-id route-params]} [_ client-id]]
|
|
||||||
(let [client (get clients-by-id (:id route-params))]
|
|
||||||
{:db (-> db
|
{:db (-> db
|
||||||
(forms/stop-form ::form)
|
(forms/stop-form ::form)
|
||||||
(forms/start-form ::form (-> client
|
(forms/start-form ::form (-> client
|
||||||
@@ -220,7 +227,7 @@
|
|||||||
(update ba :locations (fn [ls]
|
(update ba :locations (fn [ls]
|
||||||
(map (fn [l] {:location l})
|
(map (fn [l] {:location l})
|
||||||
ls))))
|
ls))))
|
||||||
bas))))))})))
|
bas))))))}))
|
||||||
|
|
||||||
(re-frame/reg-event-fx
|
(re-frame/reg-event-fx
|
||||||
::save-new-client
|
::save-new-client
|
||||||
@@ -302,12 +309,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
(def client-form
|
|
||||||
(forms/vertical-form {:can-submit [::can-submit]
|
|
||||||
:change-event [::forms/change ::form]
|
|
||||||
:submit-event [::save-new-client ]
|
|
||||||
:id ::form
|
|
||||||
:fullwidth? false}))
|
|
||||||
|
|
||||||
(def first-week-a (coerce/to-date-time #inst "1999-12-27T00:00:00.000-07:00"))
|
(def first-week-a (coerce/to-date-time #inst "1999-12-27T00:00:00.000-07:00"))
|
||||||
|
|
||||||
@@ -335,7 +336,6 @@
|
|||||||
|
|
||||||
|
|
||||||
(defn bank-account-card [new-client {:keys [active? new? type visible code name sort-order]} first? last?]
|
(defn bank-account-card [new-client {:keys [active? new? type visible code name sort-order]} first? last?]
|
||||||
(let [{:keys [field raw-field]} client-form]
|
|
||||||
[:div.card {:style {:margin-bottom "1em"
|
[:div.card {:style {:margin-bottom "1em"
|
||||||
:width "600px"}}
|
:width "600px"}}
|
||||||
[:header.card-header.has-background-primary-light
|
[:header.card-header.has-background-primary-light
|
||||||
@@ -384,25 +384,28 @@
|
|||||||
[:div.field.has-addons.is-extended
|
[:div.field.has-addons.is-extended
|
||||||
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
||||||
[:p.control
|
[:p.control
|
||||||
[raw-field
|
[form-builder/raw-field
|
||||||
[:input.input {:type "code"
|
[:input.input {:type "code"
|
||||||
:field [:bank-accounts sort-order :code]
|
:field [:code]
|
||||||
:spec ::entity/code}]]]]
|
:spec ::entity/code}]]]]
|
||||||
[:div.field [:p.control code]])]
|
[:div.field [:p.control code]])]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[field "Nickname"
|
[form-builder/field
|
||||||
|
"Nickname"
|
||||||
[:input.input {:placeholder "BOA Checking #1"
|
[:input.input {:placeholder "BOA Checking #1"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :name]}]]
|
:field [:name]}]]
|
||||||
[horizontal-field
|
[horizontal-field
|
||||||
nil
|
nil
|
||||||
[field "Numeric Code"
|
[form-builder/field
|
||||||
|
"Numeric Code"
|
||||||
[:input.input {:placeholder "20101"
|
[:input.input {:placeholder "20101"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :numeric-code]}]]]
|
:field [:numeric-code]}]]]
|
||||||
[field "Start date"
|
[form-builder/field
|
||||||
|
"Start date"
|
||||||
[date-picker {:class-name "input"
|
[date-picker {:class-name "input"
|
||||||
:class "input"
|
:class "input"
|
||||||
:format-week-number (fn [] "")
|
:format-week-number (fn [] "")
|
||||||
@@ -411,65 +414,75 @@
|
|||||||
:next-month-button-label ""
|
:next-month-button-label ""
|
||||||
:next-month-label ""
|
:next-month-label ""
|
||||||
:type "date"
|
:type "date"
|
||||||
:field [:bank-accounts sort-order :start-date]}]]]
|
:field [:start-date]}]]]
|
||||||
(when (#{:check ":check"} type )
|
(when (#{:check ":check"} type )
|
||||||
[:div
|
[:div
|
||||||
|
|
||||||
[:label.label "Bank"]
|
[:label.label "Bank"]
|
||||||
[horizontal-field
|
[horizontal-field
|
||||||
nil
|
nil
|
||||||
[field "Bank Name"
|
[form-builder/field
|
||||||
|
"Bank Name"
|
||||||
[:input.input {:placeholder "Bank of America"
|
[:input.input {:placeholder "Bank of America"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :bank-name]}]]
|
:field [:bank-name]}]]
|
||||||
[field "Routing #"
|
[form-builder/field
|
||||||
|
"Routing #"
|
||||||
[:input.input {:placeholder "104819123"
|
[:input.input {:placeholder "104819123"
|
||||||
:style {:width "9em"}
|
:style {:width "9em"}
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :routing]}]]
|
:field [:routing]}]]
|
||||||
[field "Bank code"
|
[form-builder/field
|
||||||
|
"Bank code"
|
||||||
[:input.input {:placeholder "12/10123"
|
[:input.input {:placeholder "12/10123"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :bank-code]}]]]
|
:field [:bank-code]}]]]
|
||||||
|
|
||||||
[horizontal-field
|
[horizontal-field
|
||||||
nil
|
nil
|
||||||
[field "Account #"
|
[form-builder/field
|
||||||
|
"Account #"
|
||||||
[:input.input {:placeholder "123456789"
|
[:input.input {:placeholder "123456789"
|
||||||
:type "text"
|
:type "text"
|
||||||
:style {:width "20em"}
|
:style {:width "20em"}
|
||||||
:field [:bank-accounts sort-order :number]}]]
|
:field [:number]}]]
|
||||||
|
|
||||||
[field "Check Number"
|
[form-builder/field
|
||||||
|
"Check Number"
|
||||||
[:input.input {:placeholder "10000"
|
[:input.input {:placeholder "10000"
|
||||||
:style {:width "6em"}
|
:style {:width "6em"}
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :check-number]}]]]
|
:field [:check-number]}]]]
|
||||||
[field "Yodlee Account"
|
[form-builder/field
|
||||||
|
"Yodlee Account"
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
[:input.input {:placeholder "Yodlee Account #"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :yodlee-account-id]}]]
|
:field [:yodlee-account-id]}]]
|
||||||
[field "Yodlee Account (new)"
|
[form-builder/field
|
||||||
|
"Yodlee Account (new)"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::yodlee-accounts (:id new-client)])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::yodlee-accounts (:id new-client)])
|
||||||
:entity->text (fn [m] (str (:name m) " - " (:number m)))
|
:entity->text (fn [m] (str (:name m) " - " (:number m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :yodlee-account]}]]
|
:field [:yodlee-account]}]]
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.checkbox
|
[:label.checkbox
|
||||||
[raw-field
|
[form-builder/raw-field
|
||||||
[:input {:type "checkbox"
|
[:input {:type "checkbox"
|
||||||
:field [:bank-accounts sort-order :use-date-instead-of-post-date]}]]
|
:field [:use-date-instead-of-post-date]}]]
|
||||||
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
||||||
[field "Intuit Bank Account"
|
|
||||||
|
[form-builder/field
|
||||||
|
"Intuit Bank Account"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/intuit-bank-accounts])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/intuit-bank-accounts])
|
||||||
:entity->text (fn [m] (str (:name m)))
|
:entity->text (fn [m] (str (:name m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :intuit-bank-account]}]]
|
:field [:intuit-bank-account]}]]
|
||||||
[field "Plaid Account"
|
[form-builder/field
|
||||||
|
"Plaid Account"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::plaid-accounts (:id new-client)])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::plaid-accounts (:id new-client)])
|
||||||
:entity->text (fn [m] (str (:name m)))
|
:entity->text (fn [m] (str (:name m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :plaid-account]}]]])
|
:field [:plaid-account]}]]])
|
||||||
|
|
||||||
(when (#{:credit ":credit"} type )
|
(when (#{:credit ":credit"} type )
|
||||||
[:div
|
[:div
|
||||||
@@ -478,52 +491,57 @@
|
|||||||
[:label.label "Account"]
|
[:label.label "Account"]
|
||||||
[horizontal-field
|
[horizontal-field
|
||||||
nil
|
nil
|
||||||
[field "Bank Name"
|
[form-builder/field
|
||||||
|
"Bank Name"
|
||||||
[:input.input {:placeholder "Bank of America"
|
[:input.input {:placeholder "Bank of America"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :bank-name]}]]]
|
:field [:bank-name]}]]]
|
||||||
|
|
||||||
|
|
||||||
[horizontal-field
|
[horizontal-field
|
||||||
nil
|
nil
|
||||||
[field "Account #"
|
[form-builder/field
|
||||||
|
"Account #"
|
||||||
[:input.input {:placeholder "123456789"
|
[:input.input {:placeholder "123456789"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :number]}]]]
|
:field [:number]}]]]
|
||||||
|
|
||||||
[field "Yodlee Account"
|
[form-builder/field
|
||||||
|
"Yodlee Account"
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
[:input.input {:placeholder "Yodlee Account #"
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:bank-accounts sort-order :yodlee-account-id]}]]
|
:field [:yodlee-account-id]}]]
|
||||||
[field "Yodlee Account (new)"
|
[form-builder/field
|
||||||
|
"Yodlee Account (new)"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::yodlee-accounts (:id new-client)])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::yodlee-accounts (:id new-client)])
|
||||||
:entity->text (fn [m] (str (:name m) " - " (:number m)))
|
:entity->text (fn [m] (str (:name m) " - " (:number m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :yodlee-account]}]]
|
:field [:yodlee-account]}]]
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.checkbox
|
[:label.checkbox
|
||||||
[raw-field
|
[form-builder/raw-field
|
||||||
[:input {:type "checkbox"
|
[:input {:type "checkbox"
|
||||||
:field [:bank-accounts sort-order :use-date-instead-of-post-date]}]]
|
:field [:use-date-instead-of-post-date]}]]
|
||||||
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
||||||
[field "Intuit Bank Account"
|
[form-builder/field
|
||||||
|
"Intuit Bank Account"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/intuit-bank-accounts])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::subs/intuit-bank-accounts])
|
||||||
:entity->text (fn [m] (str (:name m)))
|
:entity->text (fn [m] (str (:name m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :intuit-bank-account]}]]
|
:field [:intuit-bank-account]}]]
|
||||||
[field "Plaid Account"
|
[form-builder/field
|
||||||
|
"Plaid Account"
|
||||||
[typeahead-v3 {:entities @(re-frame/subscribe [::plaid-accounts (:id new-client)])
|
[typeahead-v3 {:entities @(re-frame/subscribe [::plaid-accounts (:id new-client)])
|
||||||
:entity->text (fn [m] (str (:name m)))
|
:entity->text (fn [m] (str (:name m)))
|
||||||
:type "typeahead-v3"
|
:type "typeahead-v3"
|
||||||
:field [:bank-accounts sort-order :plaid-account]}]]
|
:field [:plaid-account]}]]])
|
||||||
])
|
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.label "Locations"]
|
[:label.label "Locations"]
|
||||||
[:div.control
|
[:div.control
|
||||||
[:p.help "If this account is location-specific, add the valid locations"]
|
[:p.help "If this account is location-specific, add the valid locations"]
|
||||||
[raw-field
|
[form-builder/raw-field
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field [:bank-accounts sort-order :locations]
|
:field [:locations]
|
||||||
:template [[:select.select {:type "select"
|
:template [[:select.select {:type "select"
|
||||||
:style {:width "7em"}
|
:style {:width "7em"}
|
||||||
:allow-nil? true
|
:allow-nil? true
|
||||||
@@ -536,77 +554,43 @@
|
|||||||
(get-in new-client [:locations]))]]]]}]]]]
|
(get-in new-client [:locations]))]]]]}]]]]
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.checkbox
|
[:label.checkbox
|
||||||
[raw-field
|
[form-builder/raw-field
|
||||||
[:input {:type "checkbox"
|
[:input {:type "checkbox"
|
||||||
:field [:bank-accounts sort-order :include-in-reports]}]]
|
:field [:include-in-reports]}]]
|
||||||
" Include in reports"]]])
|
" Include in reports"]]])
|
||||||
|
|
||||||
(when active?
|
(when active?
|
||||||
[:footer.card-footer
|
[:footer.card-footer
|
||||||
[:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated sort-order])} "Done"]
|
[:a.card-footer-item {:href "#" :on-click (dispatch-event [::bank-account-deactivated sort-order])} "Done"]
|
||||||
(when new?
|
(when new?
|
||||||
[:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed sort-order])} "Remove"])])]))
|
[:a.card-footer-item.is-warning {:href "#" :on-click (dispatch-event [::bank-account-removed sort-order])} "Remove"])])])
|
||||||
|
|
||||||
(defn form-section [{:keys [title]}]
|
|
||||||
[:<>
|
|
||||||
[:h4.is-4.title title]
|
|
||||||
[:hr]
|
|
||||||
(into [:div {:style {:margin-bottom "5em"}}]
|
|
||||||
(r/children (r/current-component)))])
|
|
||||||
|
|
||||||
(defn form-content []
|
|
||||||
(let [{new-client :data :as f} @(re-frame/subscribe [::forms/form ::form])
|
|
||||||
{:keys [form-inline 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")]
|
|
||||||
^{:key (or (:id new-client)
|
|
||||||
"new")}
|
|
||||||
[:div ;; div is important for actually unmounting for now
|
|
||||||
|
|
||||||
|
|
||||||
(form-inline {:title ""}
|
(defn general-section []
|
||||||
[:<>
|
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
[form-builder/section {:title "General"}
|
||||||
|
[form-builder/field
|
||||||
[form-section {:title "General"}
|
"Name"
|
||||||
(field "Name"
|
|
||||||
[:input.input {:type "text"
|
[:input.input {:type "text"
|
||||||
:style {:width "20em"}
|
:style {:width "20em"}
|
||||||
:field [:name]
|
:field [:name]
|
||||||
:spec ::entity/name
|
:spec ::entity/name}]]
|
||||||
}])
|
[form-builder/field
|
||||||
[:div.field
|
"Client code"
|
||||||
[:label.label "Client code"]
|
|
||||||
(if (:id new-client)
|
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[:input.input {:type "code"
|
[:input.input {:type "code"
|
||||||
:style {:width "5em"}
|
:style {:width "5em"}
|
||||||
:field :code
|
:field :code
|
||||||
:spec ::entity/code
|
:disabled (boolean (:id new-client))
|
||||||
:disabled true}])
|
:spec ::entity/code}]]
|
||||||
]
|
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[:input.input {:type "code"
|
|
||||||
:style {:width "5em"}
|
|
||||||
:field :code
|
|
||||||
:spec ::entity/code}])])]
|
|
||||||
|
|
||||||
[:div.field
|
[form-builder/field
|
||||||
[:label.label "Locations"]
|
"Locations"
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :locations
|
:field :locations
|
||||||
:allow-change? false
|
:allow-change? false
|
||||||
:template [[:input.input {:field [:location]
|
:template [[:input.input {:field [:location]
|
||||||
:maxlength 2
|
:max-length 2
|
||||||
:style { :width "4em"}}]]}])]]
|
:style { :width "4em"}}]]}]]
|
||||||
|
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.label "Signature"]
|
[:label.label "Signature"]
|
||||||
@@ -615,26 +599,17 @@
|
|||||||
:on-change (fn [uri]
|
:on-change (fn [uri]
|
||||||
(re-frame/dispatch [::forms/change ::form [:signature-data] uri]))}]]
|
(re-frame/dispatch [::forms/change ::form [:signature-data] uri]))}]]
|
||||||
|
|
||||||
|
[form-builder/field
|
||||||
|
"Locked Until"
|
||||||
(field "Locked Until"
|
[date-picker-friendly {:type "date"
|
||||||
[date-picker {:class-name "input"
|
|
||||||
:class "input"
|
|
||||||
:format-week-number (fn [] "")
|
|
||||||
:previous-month-button-label ""
|
|
||||||
:placeholder "mm/dd/yyyy"
|
|
||||||
:next-month-button-label ""
|
|
||||||
:next-month-label ""
|
|
||||||
:type "date"
|
|
||||||
:field [:locked-until]
|
:field [:locked-until]
|
||||||
:style {:width "15em"}}])]
|
:style {:width "15em"}}]]]))
|
||||||
|
|
||||||
[form-section {:title "Contacts"}
|
(defn contacts-section []
|
||||||
|
[form-builder/section {:title "Contacts"}
|
||||||
|
|
||||||
[:div.field
|
[form-builder/field
|
||||||
[:label.label "Emails (address/description)"]
|
"Emails (address/description)"
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :emails
|
:field :emails
|
||||||
:template [[:input.input {:type "email"
|
:template [[:input.input {:type "email"
|
||||||
@@ -643,30 +618,28 @@
|
|||||||
:spec ::entity/email}]
|
:spec ::entity/email}]
|
||||||
[:input.input {:type "text"
|
[:input.input {:type "text"
|
||||||
:placeholder "Manager"
|
:placeholder "Manager"
|
||||||
:field [:description]}]]}])]]
|
:field [:description]}]]}]]
|
||||||
[:label.label "Address"]
|
|
||||||
[:div {:style {:width "30em"}}
|
|
||||||
[address-field {:field [:address]
|
|
||||||
:event [::forms/change ::form]
|
|
||||||
:subscription new-client}]]]
|
|
||||||
|
|
||||||
|
[form-builder/with-scope {:scope [:address ]}
|
||||||
[form-section {:title "Matching"}
|
|
||||||
[:div.field
|
[:div.field
|
||||||
[:label.label "Name matches"]
|
[:label.label "Address"]
|
||||||
[:div.control
|
[:div.control
|
||||||
(raw-field
|
[:div {:style {:width "30em"}}
|
||||||
|
[address2-field]]]]]])
|
||||||
|
|
||||||
|
(defn matching-section []
|
||||||
|
[form-builder/section {:title "Matching"}
|
||||||
|
[form-builder/field
|
||||||
|
"Name matches"
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :matches
|
:field :matches
|
||||||
:template [[:input.input {:field [:match]
|
:template [[:input.input {:field [:match]
|
||||||
:placeholder "Harry's burger joint"
|
:placeholder "Harry's burger joint"
|
||||||
:style { :width "15em"}}]]}])]]
|
:style { :width "15em"}}]]}]]
|
||||||
|
|
||||||
|
|
||||||
[:div.field
|
[form-builder/field
|
||||||
[:label.label "Location Matches"]
|
"Location Matches"
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :location-matches
|
:field :location-matches
|
||||||
:template [[:input.input {:field [:match]
|
:template [[:input.input {:field [:match]
|
||||||
@@ -675,34 +648,45 @@
|
|||||||
[:input.input {:field [:location]
|
[:input.input {:field [:location]
|
||||||
:placeholder "DT"
|
:placeholder "DT"
|
||||||
:maxlength 2
|
:maxlength 2
|
||||||
:style { :width "4em"}}]]}])]]]
|
:style { :width "4em"}}]]}]]])
|
||||||
|
|
||||||
|
(defn bank-accounts-section []
|
||||||
|
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
[form-builder/section {:title "Bank Accounts"}
|
||||||
[form-section {:title "Bank Accounts"}
|
|
||||||
(for [bank-account (sort-by :sort-order (:bank-accounts new-client))]
|
(for [bank-account (sort-by :sort-order (:bank-accounts new-client))]
|
||||||
^{:key (:sort-order bank-account)}
|
^{: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))))])
|
[form-builder/with-scope {:scope [:bank-accounts (: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.buttons
|
[:div.buttons
|
||||||
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :credit])} "Add Credit Account"]
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :credit])} "Add Credit Account"]
|
||||||
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :check])} "Add Checking Account"]
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :check])} "Add Checking Account"]
|
||||||
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :cash])} "Add Cash Account"]]]
|
[:a.button.is-primary.is-outlined {:on-click (dispatch-event [::add-new-bank-account :cash])} "Add Cash Account"]]]))
|
||||||
|
|
||||||
[form-section {:title "Cash flow"}
|
(defn cash-flow-section []
|
||||||
|
(let [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")]
|
||||||
|
|
||||||
|
|
||||||
|
[form-builder/section {:title "Cash Flow"}
|
||||||
[:label.label (str "Week A (" next-week-a ")")]
|
[:label.label (str "Week A (" next-week-a ")")]
|
||||||
[:div.level
|
[:div.level
|
||||||
[:div.level-left
|
[:div.level-left
|
||||||
[:div.level-item
|
[:div.level-item
|
||||||
[field "Regular Credits"
|
[form-builder/field
|
||||||
|
"Regular Credits"
|
||||||
[:input.input {:type "number"
|
[:input.input {:type "number"
|
||||||
:style {:width "10em"}
|
:style {:width "10em"}
|
||||||
:placeholder "500.00"
|
:placeholder "500.00"
|
||||||
:field [:week-a-credits]
|
:field [:week-a-credits]
|
||||||
:step "0.01"}]]]
|
:step "0.01"}]]]
|
||||||
[:div.level-item
|
[:div.level-item
|
||||||
[field "Regular Debits"
|
[form-builder/field
|
||||||
|
"Regular Debits"
|
||||||
[:input.input {:type "number"
|
[:input.input {:type "number"
|
||||||
:style {:width "10em"}
|
:style {:width "10em"}
|
||||||
:placeholder "150.00"
|
:placeholder "150.00"
|
||||||
@@ -712,14 +696,14 @@
|
|||||||
[:div.level
|
[:div.level
|
||||||
[:div.level-left
|
[:div.level-left
|
||||||
[:div.level-item
|
[:div.level-item
|
||||||
[field "Regular Credits"
|
[form-builder/field "Regular Credits"
|
||||||
[:input.input {:type "number"
|
[:input.input {:type "number"
|
||||||
:style {:width "10em"}
|
:style {:width "10em"}
|
||||||
:placeholder "1000.00"
|
:placeholder "1000.00"
|
||||||
:field [:week-b-credits]
|
:field [:week-b-credits]
|
||||||
:step "0.01"}]]]
|
:step "0.01"}]]]
|
||||||
[:div.level-item
|
[:div.level-item
|
||||||
[field "Regular Debits"
|
[form-builder/field "Regular Debits"
|
||||||
[:input.input {:type "number"
|
[:input.input {:type "number"
|
||||||
:style {:width "10em"}
|
:style {:width "10em"}
|
||||||
:placeholder "250.00"
|
:placeholder "250.00"
|
||||||
@@ -729,7 +713,7 @@
|
|||||||
[:label.label "Forecasted transactions"]
|
[:label.label "Forecasted transactions"]
|
||||||
|
|
||||||
[:div.control
|
[:div.control
|
||||||
(raw-field
|
[form-builder/raw-field
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :forecasted-transactions
|
:field :forecasted-transactions
|
||||||
:template [[:input.input {:type "text"
|
:template [[:input.input {:type "text"
|
||||||
@@ -746,17 +730,17 @@
|
|||||||
:class "has-text-right"
|
:class "has-text-right"
|
||||||
:style {:width "7em"}
|
:style {:width "7em"}
|
||||||
:field [:amount]
|
:field [:amount]
|
||||||
:step "0.01"}]]}])]]]
|
:step "0.01"}]]}]]]]]))
|
||||||
|
|
||||||
[form-section {:title "Square Integration"}
|
(defn square-section []
|
||||||
(field "Square Authentication Token"
|
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
[form-builder/section {:title "Square Integration"}
|
||||||
|
[form-builder/field "Square Authentication Token"
|
||||||
[:input.input {:type "text"
|
[:input.input {:type "text"
|
||||||
:style {:width "40em"}
|
:style {:width "40em"}
|
||||||
:field [:square-auth-token]}])
|
:field [:square-auth-token]}]]
|
||||||
[:div.field
|
[form-builder/field
|
||||||
[:label.label "Square Locations"]
|
"Square Locations"
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :selected-square-locations
|
:field :selected-square-locations
|
||||||
:template [[typeahead-v3 {:entities (:square-locations new-client)
|
:template [[typeahead-v3 {:entities (:square-locations new-client)
|
||||||
@@ -768,18 +752,16 @@
|
|||||||
:style {:width "4em"}
|
:style {:width "4em"}
|
||||||
:field [:client-location]
|
:field [:client-location]
|
||||||
:step "0.01"}]]
|
:step "0.01"}]]
|
||||||
:disable-remove? true}])]]]
|
:disable-remove? true}]]]))
|
||||||
|
|
||||||
[form-section {:title "EZCater integration"}
|
(defn ezcater-section []
|
||||||
|
[form-builder/section {:title "EZCater integration"}
|
||||||
|
|
||||||
[:div.field
|
[form-builder/field
|
||||||
[:label.label "EZCater Locations"]
|
"EZCater Locations"
|
||||||
[:div.control
|
|
||||||
(raw-field
|
|
||||||
[multi-field {:type "multi-field"
|
[multi-field {:type "multi-field"
|
||||||
:field :ezcater-locations
|
:field :ezcater-locations
|
||||||
:template [
|
:template [[search-backed-typeahead {:search-query (fn [i]
|
||||||
[search-backed-typeahead {:search-query (fn [i]
|
|
||||||
[:search_ezcater_caterer
|
[:search_ezcater_caterer
|
||||||
{:query i}
|
{:query i}
|
||||||
[:name :id]])
|
[:name :id]])
|
||||||
@@ -791,10 +773,28 @@
|
|||||||
:style {:width "4em"}
|
:style {:width "4em"}
|
||||||
:field [:location]
|
:field [:location]
|
||||||
:step "0.01"}]]
|
:step "0.01"}]]
|
||||||
:disable-remove? true}])]]]
|
:disable-remove? true}]]])
|
||||||
|
|
||||||
(error-notification)
|
(defn form-content []
|
||||||
(submit-button "Save")])]))
|
(let [_ @(re-frame/subscribe [::client])
|
||||||
|
{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
|
||||||
|
^{:key (or (:id new-client)
|
||||||
|
"new")}
|
||||||
|
[form-builder/builder {:can-submit [::can-submit]
|
||||||
|
:submit-event [::save-new-client ]
|
||||||
|
:id ::form
|
||||||
|
:fullwidth? false}
|
||||||
|
|
||||||
|
[general-section]
|
||||||
|
[contacts-section]
|
||||||
|
[matching-section]
|
||||||
|
[bank-accounts-section]
|
||||||
|
[cash-flow-section]
|
||||||
|
[square-section]
|
||||||
|
[ezcater-section]
|
||||||
|
[form-builder/error-notification]
|
||||||
|
[form-builder/submit-button "Save"]]))
|
||||||
|
|
||||||
(def new-client-form
|
(def new-client-form
|
||||||
(with-meta
|
(with-meta
|
||||||
|
|||||||
85
src/cljs/auto_ap/views/pages/page_stack.cljs
Normal file
85
src/cljs/auto_ap/views/pages/page_stack.cljs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
(ns auto-ap.views.pages.page-stack
|
||||||
|
(:require
|
||||||
|
[auto-ap.views.utils :refer [switch-transition transition]]
|
||||||
|
[reagent.core :as r]))
|
||||||
|
|
||||||
|
(defn page-stack []
|
||||||
|
(let [last-stack-size (r/atom (->> (r/current-component)
|
||||||
|
r/children
|
||||||
|
(filter identity) count))
|
||||||
|
forward? (r/atom false)]
|
||||||
|
(fn [{:keys [pages active]}]
|
||||||
|
(let [current-stack-size (->> pages
|
||||||
|
(take-while #(not= (:key %)
|
||||||
|
active))
|
||||||
|
count)
|
||||||
|
current-child (->> pages
|
||||||
|
(filter #(= (:key %)
|
||||||
|
active))
|
||||||
|
first)]
|
||||||
|
(when (not= current-stack-size @last-stack-size)
|
||||||
|
(reset! forward? (> current-stack-size @last-stack-size))
|
||||||
|
(reset! last-stack-size current-stack-size))
|
||||||
|
[:div
|
||||||
|
[:h1.title (:breadcrumb current-child)]
|
||||||
|
[switch-transition {:mode "in-out"}
|
||||||
|
^{:key current-stack-size}
|
||||||
|
[transition
|
||||||
|
{:timeout 100
|
||||||
|
:exit true
|
||||||
|
:in true #_(= current-stack- (:key (meta child)))
|
||||||
|
:appear (> current-stack-size 1)}
|
||||||
|
(clj->js (fn [state]
|
||||||
|
(r/as-element
|
||||||
|
[:div {:style {
|
||||||
|
:position (cond
|
||||||
|
(= "entered" state)
|
||||||
|
""
|
||||||
|
|
||||||
|
(= "entering" state)
|
||||||
|
"absolute"
|
||||||
|
|
||||||
|
(= "exiting" state)
|
||||||
|
"absolute"
|
||||||
|
|
||||||
|
(= "exited" state)
|
||||||
|
"")
|
||||||
|
:transition "opacity 300ms ease-in-out, transform 300ms ease-in-out"
|
||||||
|
:opacity (cond
|
||||||
|
(= "entered" state)
|
||||||
|
""
|
||||||
|
|
||||||
|
(= "entering" state)
|
||||||
|
0.0
|
||||||
|
|
||||||
|
(= "exiting" state)
|
||||||
|
1.0
|
||||||
|
|
||||||
|
(= "exited" state)
|
||||||
|
0.0)
|
||||||
|
:transform (if @forward?
|
||||||
|
(cond
|
||||||
|
(= "entered" state)
|
||||||
|
""
|
||||||
|
|
||||||
|
(= "entering" state)
|
||||||
|
"translateX(100%)"
|
||||||
|
|
||||||
|
(= "exiting" state)
|
||||||
|
"translateX(-100%)"
|
||||||
|
|
||||||
|
(= "exited" state)
|
||||||
|
"translateX(0%)")
|
||||||
|
(cond
|
||||||
|
(= "entered" state)
|
||||||
|
""
|
||||||
|
|
||||||
|
(= "entering" state)
|
||||||
|
"translateX(-100%)"
|
||||||
|
|
||||||
|
(= "exiting" state)
|
||||||
|
"translateX(100%)"
|
||||||
|
|
||||||
|
(= "exited" state)
|
||||||
|
"translateX(0%)"))}}
|
||||||
|
(:content current-child)])))]]]))))
|
||||||
Reference in New Issue
Block a user