made client form great

This commit is contained in:
2022-07-21 06:04:09 -07:00
parent 899efe0efa
commit 746787df79
5 changed files with 119 additions and 153 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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]]

View File

@@ -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 []

View File

@@ -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])]