made client form great
This commit is contained in:
@@ -55,7 +55,7 @@
|
|||||||
;; TODO ONLY validate on blur
|
;; TODO ONLY validate on blur
|
||||||
problems (when schema
|
problems (when schema
|
||||||
|
|
||||||
(m/explain schema data))]
|
(m/explain schema data))]
|
||||||
(r/create-element Provider #js {:value #js {:can-submit can-submit
|
(r/create-element Provider #js {:value #js {:can-submit can-submit
|
||||||
:error-messages (or error-messages
|
:error-messages (or error-messages
|
||||||
nil)
|
nil)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
(ns auto-ap.views.components
|
(ns auto-ap.views.components
|
||||||
(:require [reagent.core :as r]
|
(:require [reagent.core :as r]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[auto-ap.views.components.multi :as multi]))
|
[auto-ap.views.components.multi :as multi]
|
||||||
|
[auto-ap.views.components.number :as number]))
|
||||||
|
|
||||||
|
|
||||||
(defn checkbox [{:keys [on-change
|
(defn checkbox [{:keys [on-change
|
||||||
@@ -35,3 +36,5 @@
|
|||||||
^{:key k} [:option {:value k} v])]]])
|
^{:key k} [:option {:value k} v])]]])
|
||||||
|
|
||||||
(def multi-field-v2 multi/multi-field-v2)
|
(def multi-field-v2 multi/multi-field-v2)
|
||||||
|
|
||||||
|
(def number-input number/number-input)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
(let [prop-value (if (seq prop-value)
|
(let [prop-value (if (seq prop-value)
|
||||||
prop-value
|
prop-value
|
||||||
[])]
|
[])]
|
||||||
|
(println "PROP VALUE IS")
|
||||||
[form-builder/virtual-builder {:value prop-value
|
[form-builder/virtual-builder {:value prop-value
|
||||||
:schema schema
|
:schema schema
|
||||||
:on-change on-change}
|
:on-change on-change}
|
||||||
@@ -60,7 +61,7 @@
|
|||||||
[:button.button.is-outline
|
[:button.button.is-outline
|
||||||
{:type "button"
|
{:type "button"
|
||||||
:on-click (fn [e]
|
:on-click (fn [e]
|
||||||
(on-change (conj prop-value {::key next-key}))
|
(on-change (conj prop-value {::key (random-uuid)}))
|
||||||
(.stopPropagation e)
|
(.stopPropagation e)
|
||||||
(.preventDefault e))}
|
(.preventDefault e))}
|
||||||
[:span.icon [:i.fa.fa-plus]]
|
[:span.icon [:i.fa.fa-plus]]
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
:value text
|
:value text
|
||||||
:type "number"
|
:type "number"
|
||||||
:step "1"
|
:step "1"
|
||||||
:style {:width "5em"}
|
:style (or (:style props)
|
||||||
|
{:width "5em"})
|
||||||
:size 3)]]]))
|
:size 3)]]]))
|
||||||
|
|
||||||
(defn number-input []
|
(defn number-input []
|
||||||
|
|||||||
@@ -27,13 +27,18 @@
|
|||||||
[react-signature-canvas]
|
[react-signature-canvas]
|
||||||
[vimsical.re-frame.cofx.inject :as inject]
|
[vimsical.re-frame.cofx.inject :as inject]
|
||||||
[auto-ap.schema :as schema]
|
[auto-ap.schema :as schema]
|
||||||
[auto-ap.views.components :as com]
|
|
||||||
[malli.core :as m]))
|
[malli.core :as m]))
|
||||||
|
|
||||||
(def signature-canvas (r/adapt-react-class (.-default react-signature-canvas)))
|
(def signature-canvas (r/adapt-react-class (.-default react-signature-canvas)))
|
||||||
|
|
||||||
(def location-schema (m/schema [:map
|
(def location-schema (m/schema [:map
|
||||||
[:location schema/not-empty-string]]))
|
[:location schema/not-empty-string]]))
|
||||||
|
|
||||||
|
(def name-match-schema (m/schema [:map
|
||||||
|
[:match schema/not-empty-string]]))
|
||||||
|
(def location-match-schema (m/schema [:map
|
||||||
|
[:match schema/not-empty-string]
|
||||||
|
[:location schema/not-empty-string]]))
|
||||||
(def email-schema [:map
|
(def email-schema [:map
|
||||||
[:email schema/not-empty-string]
|
[:email schema/not-empty-string]
|
||||||
[:description schema/not-empty-string]])
|
[:description schema/not-empty-string]])
|
||||||
@@ -42,7 +47,12 @@
|
|||||||
[:name schema/not-empty-string]
|
[:name schema/not-empty-string]
|
||||||
[:code schema/code-string]
|
[:code schema/code-string]
|
||||||
[:locations [:sequential location-schema]]
|
[:locations [:sequential location-schema]]
|
||||||
[:emails [:sequential email-schema]]])
|
[:emails {:optional true}
|
||||||
|
[:maybe [:sequential email-schema]]]
|
||||||
|
[:matches {:optional true}
|
||||||
|
[:maybe [:sequential name-match-schema]]]
|
||||||
|
[:location-matches {:optional true}
|
||||||
|
[:maybe [:sequential location-match-schema]]]])
|
||||||
|
|
||||||
(defn upload-replacement-button [{:keys [on-change]} text]
|
(defn upload-replacement-button [{:keys [on-change]} text]
|
||||||
(let [button (atom nil)]
|
(let [button (atom nil)]
|
||||||
@@ -164,10 +174,8 @@
|
|||||||
:bank-accounts (map-indexed (fn [i {:keys [number name check-number plaid-account intuit-bank-account include-in-reports type id code numeric-code start-date bank-name routing bank-code new? sort-order visible yodlee-account-id locations yodlee-account use-date-instead-of-post-date]}]
|
:bank-accounts (map-indexed (fn [i {:keys [number name check-number plaid-account intuit-bank-account include-in-reports type id code numeric-code start-date bank-name routing bank-code new? sort-order visible yodlee-account-id locations yodlee-account use-date-instead-of-post-date]}]
|
||||||
{:number number
|
{:number number
|
||||||
:name name
|
:name name
|
||||||
:check-number (when-not (str/blank? check-number)
|
:check-number check-number
|
||||||
(js/parseInt check-number))
|
:numeric-code numeric-code
|
||||||
:numeric-code (when-not (str/blank? numeric-code)
|
|
||||||
(js/parseInt numeric-code))
|
|
||||||
:include-in-reports include-in-reports
|
:include-in-reports include-in-reports
|
||||||
:start-date start-date
|
:start-date start-date
|
||||||
:type type
|
:type type
|
||||||
@@ -176,8 +184,6 @@
|
|||||||
:visible visible
|
:visible visible
|
||||||
:locations (mapv :location locations)
|
:locations (mapv :location locations)
|
||||||
:use-date-instead-of-post-date use-date-instead-of-post-date
|
:use-date-instead-of-post-date use-date-instead-of-post-date
|
||||||
:yodlee-account-id (when-not (str/blank? yodlee-account-id)
|
|
||||||
(js/parseInt yodlee-account-id))
|
|
||||||
:yodlee-account (:id yodlee-account)
|
:yodlee-account (:id yodlee-account)
|
||||||
:plaid-account (:id plaid-account)
|
:plaid-account (:id plaid-account)
|
||||||
:intuit-bank-account (:id intuit-bank-account)
|
:intuit-bank-account (:id intuit-bank-account)
|
||||||
@@ -212,7 +218,8 @@
|
|||||||
:client-location (:client-location sl)}))))
|
:client-location (:client-location sl)}))))
|
||||||
(update :locations #(mapv (fn [l] {:location l
|
(update :locations #(mapv (fn [l] {:location l
|
||||||
:id (random-uuid)}) %))
|
:id (random-uuid)}) %))
|
||||||
(update :matches #(mapv (fn [l] {:match l}) %))
|
(update :matches #(mapv (fn [l] {:match l
|
||||||
|
:id (random-uuid)}) %))
|
||||||
(update :bank-accounts
|
(update :bank-accounts
|
||||||
(fn [bas]
|
(fn [bas]
|
||||||
(mapv (fn [ba]
|
(mapv (fn [ba]
|
||||||
@@ -367,182 +374,132 @@
|
|||||||
(when active?
|
(when active?
|
||||||
[:div.card-content
|
[:div.card-content
|
||||||
[:label.label "General"]
|
[:label.label "General"]
|
||||||
[horizontal-field
|
[level/left-stack
|
||||||
nil
|
|
||||||
[:div.control
|
[:div.control
|
||||||
[:p.help "Account Code"]
|
[:p.help "Account Code"]
|
||||||
(if new?
|
(if new?
|
||||||
[:div.field.has-addons.is-extended
|
[:div.field.has-addons
|
||||||
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
[:p.control [:a.button.is-static (:code new-client) "-" ]]
|
||||||
[:p.control
|
[:p.control
|
||||||
[form-builder/raw-field
|
[form-builder/raw-field-v2 {:field :code}
|
||||||
[:input.input {:type "code"
|
[:input.input {:type "text"}]]]]
|
||||||
:field [:code]
|
|
||||||
:spec ::entity/code}]]]]
|
|
||||||
[:div.field [:p.control code]])]
|
[:div.field [:p.control code]])]
|
||||||
|
|
||||||
|
[form-builder/field-v2 {:field :name}
|
||||||
|
|
||||||
[form-builder/field
|
|
||||||
"Nickname"
|
"Nickname"
|
||||||
[:input.input {:placeholder "BOA Checking #1"
|
[:input.input {:placeholder "BOA Checking #1"
|
||||||
:type "text"
|
:type "text"}]]
|
||||||
:field [:name]}]]
|
[form-builder/field-v2 {:field :numeric-code}
|
||||||
[horizontal-field
|
"Numeric Code"
|
||||||
nil
|
[com/number-input {:placeholder "20101"
|
||||||
[form-builder/field
|
:style {:width "8em"}}]]
|
||||||
"Numeric Code"
|
[form-builder/field-v2 {:field :start-date}
|
||||||
[:input.input {:placeholder "20101"
|
|
||||||
:type "text"
|
|
||||||
:field [:numeric-code]}]]]
|
|
||||||
[form-builder/field
|
|
||||||
"Start date"
|
"Start date"
|
||||||
[date-picker {:type "date"
|
[date-picker {:output :cljs-date}]]]
|
||||||
:output :cljs-date
|
|
||||||
:field [:start-date]}]]]
|
|
||||||
(when (#{:check ":check"} type )
|
(when (#{:check ":check"} type )
|
||||||
[:div
|
[:div
|
||||||
|
|
||||||
[:label.label "Bank"]
|
[:label.label "Bank"]
|
||||||
[horizontal-field
|
[level/left-stack
|
||||||
nil
|
[form-builder/field-v2 {:field :bank-name}
|
||||||
[form-builder/field
|
|
||||||
"Bank Name"
|
"Bank Name"
|
||||||
[:input.input {:placeholder "Bank of America"
|
[:input.input {:placeholder "Bank of America"
|
||||||
:type "text"
|
:type "text"}]]
|
||||||
:field [:bank-name]}]]
|
[form-builder/field-v2 {:field [:routing]}
|
||||||
[form-builder/field
|
|
||||||
"Routing #"
|
"Routing #"
|
||||||
[:input.input {:placeholder "104819123"
|
[:input.input {:placeholder "104819123"
|
||||||
:style {:width "9em"}
|
:style {:width "9em"}
|
||||||
:type "text"
|
:type "text"}]]
|
||||||
:field [:routing]}]]
|
[form-builder/field-v2 {:field :bank-code}
|
||||||
[form-builder/field
|
|
||||||
"Bank code"
|
"Bank code"
|
||||||
[:input.input {:placeholder "12/10123"
|
[:input.input {:placeholder "12/10123"
|
||||||
:type "text"
|
:type "text"}]]]
|
||||||
:field [:bank-code]}]]]
|
|
||||||
|
|
||||||
[horizontal-field
|
[level/left-stack
|
||||||
nil
|
[form-builder/field-v2 {:field :number}
|
||||||
[form-builder/field
|
|
||||||
"Account #"
|
"Account #"
|
||||||
[:input.input {:placeholder "123456789"
|
[:input.input {:placeholder "123456789"
|
||||||
:type "text"
|
:type "text"
|
||||||
:style {:width "20em"}
|
:style {:width "20em"}}]]
|
||||||
:field [:number]}]]
|
|
||||||
|
|
||||||
[form-builder/field
|
[form-builder/field-v2 {:field :check-number}
|
||||||
"Check Number"
|
"Check Number"
|
||||||
[:input.input {:placeholder "10000"
|
[com/number-input {:style {:width "8em"}
|
||||||
:style {:width "6em"}
|
:placeholder "10000"}]]]
|
||||||
:type "text"
|
|
||||||
:field [:check-number]}]]]
|
[form-builder/field-v2 {:field :yodlee-account}
|
||||||
[form-builder/field
|
|
||||||
"Yodlee Account"
|
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
|
||||||
:type "text"
|
|
||||||
:field [:yodlee-account-id]}]]
|
|
||||||
[form-builder/field
|
|
||||||
"Yodlee Account (new)"
|
"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"
|
|
||||||
:field [:yodlee-account]}]]
|
|
||||||
[:div.field
|
|
||||||
[:label.checkbox
|
|
||||||
[form-builder/raw-field
|
|
||||||
[:input {:type "checkbox"
|
|
||||||
:field [:use-date-instead-of-post-date]}]]
|
|
||||||
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
|
||||||
|
|
||||||
[form-builder/field
|
|
||||||
|
[form-builder/raw-field-v2 {:field :use-date-instead-of-post-date}
|
||||||
|
[com/checkbox {:label " (Yodlee only) Use 'date' instead of 'postDate'"}]]
|
||||||
|
|
||||||
|
[form-builder/field-v2 {:field :intuit-bank-account}
|
||||||
"Intuit Bank Account"
|
"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"
|
[form-builder/field-v2 {:field :plaid-accounti}
|
||||||
:field [:intuit-bank-account]}]]
|
|
||||||
[form-builder/field
|
|
||||||
"Plaid Account"
|
"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"
|
|
||||||
:field [:plaid-account]}]]])
|
|
||||||
|
|
||||||
(when (#{:credit ":credit"} type )
|
(when (#{:credit ":credit"} type )
|
||||||
[:div
|
[:div
|
||||||
|
|
||||||
|
|
||||||
[:label.label "Account"]
|
[:label.label "Account"]
|
||||||
[horizontal-field
|
[form-builder/field-v2 {:field :bank-name}
|
||||||
nil
|
"Bank Name"
|
||||||
[form-builder/field
|
[:input.input {:placeholder "Bank of America"
|
||||||
"Bank Name"
|
:type "text"}]]
|
||||||
[:input.input {:placeholder "Bank of America"
|
|
||||||
:type "text"
|
|
||||||
:field [:bank-name]}]]]
|
|
||||||
|
|
||||||
|
|
||||||
[horizontal-field
|
[form-builder/field-v2 {:field :number}
|
||||||
nil
|
"Account #"
|
||||||
[form-builder/field
|
[:input.input {:placeholder "123456789"
|
||||||
"Account #"
|
|
||||||
[:input.input {:placeholder "123456789"
|
|
||||||
:type "text"
|
|
||||||
:field [:number]}]]]
|
|
||||||
|
|
||||||
[form-builder/field
|
|
||||||
"Yodlee Account"
|
|
||||||
[:input.input {:placeholder "Yodlee Account #"
|
|
||||||
:type "text"
|
:type "text"
|
||||||
:field [:yodlee-account-id]}]]
|
:style {:width "20em"}}]]
|
||||||
[form-builder/field
|
|
||||||
|
[form-builder/field-v2 {:field :yodlee-account}
|
||||||
"Yodlee Account (new)"
|
"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"
|
|
||||||
:field [:yodlee-account]}]]
|
[form-builder/raw-field-v2 {:field :use-date-instead-of-post-date}
|
||||||
[:div.field
|
[com/checkbox {:label "(Yodlee only) Use 'date' instead of 'postDate'"}]
|
||||||
[:label.checkbox
|
[:input {:type "checkbox"
|
||||||
[form-builder/raw-field
|
:field [:use-date-instead-of-post-date]}]]
|
||||||
[:input {:type "checkbox"
|
|
||||||
:field [:use-date-instead-of-post-date]}]]
|
[form-builder/field-v2 {:field :intuit-bank-account}
|
||||||
" (Yodlee only) Use 'date' instead of 'postDate'"]]
|
|
||||||
[form-builder/field
|
|
||||||
"Intuit Bank Account"
|
"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"
|
|
||||||
:field [:intuit-bank-account]}]]
|
[form-builder/field-v2 {:field :plaid-account}
|
||||||
[form-builder/field
|
|
||||||
"Plaid Account"
|
"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"
|
|
||||||
: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"]
|
||||||
[form-builder/raw-field
|
[form-builder/raw-field-v2 {:field :locations}
|
||||||
[multi-field {:type "multi-field"
|
[com/multi-field-v2 {:template [[form-builder/raw-field {:key :location}
|
||||||
:field [:locations]
|
[com/select-field {:options (map (fn [l]
|
||||||
:template [[:select.select {:type "select"
|
[(:location l) (:location l)])
|
||||||
:style {:width "7em"}
|
(get-in new-client [:locations]))
|
||||||
:allow-nil? true
|
:allow-nil? true
|
||||||
:field [:location]
|
:style {:width "7em"}
|
||||||
:spec (set (map :location (get-in new-client [:locations])))}
|
}]]]
|
||||||
[:<>
|
:schema [:sequential location-schema]
|
||||||
[:option ""]
|
:key-fn :id}]]]]
|
||||||
[:<> (map (fn [l] ^{:key (:location l)}
|
|
||||||
[:option {:value (:location l)} (:location l)])
|
[form-builder/raw-field-v2 {:field :include-in-reports}
|
||||||
(get-in new-client [:locations]))]]]]}]]]]
|
[com/checkbox {:label "Include in reports"}]
|
||||||
[:div.field
|
]
|
||||||
[:label.checkbox
|
])
|
||||||
[form-builder/raw-field
|
|
||||||
[:input {:type "checkbox"
|
|
||||||
:field [:include-in-reports]}]]
|
|
||||||
" Include in reports"]]])
|
|
||||||
|
|
||||||
(when active?
|
(when active?
|
||||||
[:footer.card-footer
|
[:footer.card-footer
|
||||||
@@ -609,28 +566,32 @@
|
|||||||
[form-builder/raw-field-v2 {:field :address}
|
[form-builder/raw-field-v2 {:field :address}
|
||||||
[address2-field]]]]])
|
[address2-field]]]]])
|
||||||
|
|
||||||
|
;; TODO Name matches, locations, bank account locations are all "single field multis", and require weird mounting and
|
||||||
|
;; unmounting. A new field could sort that out easily
|
||||||
(defn matching-section []
|
(defn matching-section []
|
||||||
[form-builder/section {:title "Matching"}
|
[form-builder/section {:title "Matching"}
|
||||||
[form-builder/field
|
[form-builder/field-v2 {:field :matches}
|
||||||
"Name matches"
|
"Name matches"
|
||||||
[multi-field {:type "multi-field"
|
[com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field [:match]}
|
||||||
:field :matches
|
[:input.input {:placeholder "Harry's burger joint"
|
||||||
:template [[:input.input {:field [:match]
|
:style { :width "15em"}}]]]
|
||||||
:placeholder "Harry's burger joint"
|
:key-fn :id
|
||||||
:style { :width "15em"}}]]}]]
|
:next-key (random-uuid)
|
||||||
|
:schema [:sequential name-match-schema]}]]
|
||||||
|
|
||||||
|
|
||||||
[form-builder/field
|
[form-builder/field-v2 {:field :location-matches}
|
||||||
"Location Matches"
|
"Location Matches"
|
||||||
[multi-field {:type "multi-field"
|
[com/multi-field-v2 {:template [[form-builder/raw-field-v2 {:field :match}
|
||||||
:field :location-matches
|
[:input.input {:placeholder "Downtown"
|
||||||
:template [[:input.input {:field [:match]
|
:style { :width "15em"}}]]
|
||||||
:placeholder "Downtown"
|
[form-builder/raw-field-v2 {:field :location}
|
||||||
:style { :width "15em"}}]
|
[:input.input {:placeholder "DT"
|
||||||
[:input.input {:field [:location]
|
:max-length 2
|
||||||
:placeholder "DT"
|
:style { :width "4em"}}]]]
|
||||||
:max-length 2
|
:schema [:sequential location-match-schema]
|
||||||
:style { :width "4em"}}]]}]]])
|
:next-key (random-uuid)
|
||||||
|
:key-fn :id}]]])
|
||||||
|
|
||||||
(defn bank-accounts-section []
|
(defn bank-accounts-section []
|
||||||
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
(let [{new-client :data} @(re-frame/subscribe [::forms/form ::form])]
|
||||||
|
|||||||
Reference in New Issue
Block a user