78 lines
3.8 KiB
Clojure
78 lines
3.8 KiB
Clojure
(ns auto-ap.views.components.money-field
|
|
(:require [reagent.core :as r]
|
|
[auto-ap.views.utils :refer [->short$]]
|
|
[clojure.string :as str]
|
|
[react :as react]))
|
|
(def good-$ #"^\-?[0-9]+(\.[0-9][0-9])?$")
|
|
|
|
(defn -money-field [{:keys [min max disabled on-blur on-change value class style placeholder]}]
|
|
(let [[ parsed-amount set-parsed-amount] (react/useState {:parsed value
|
|
:raw (cond
|
|
(str/blank? value)
|
|
""
|
|
|
|
(js/Number.isNaN (js/parseFloat value))
|
|
""
|
|
|
|
:else
|
|
(->short$ (js/parseFloat value)))})]
|
|
(react/useEffect (fn []
|
|
;; allow the controlling field to change the raw representation
|
|
;; when the raw amount is a valid representation, so that 33.
|
|
;; doesn't get unset
|
|
(when (or
|
|
(and (:raw parsed-amount)
|
|
(re-find good-$ (:raw parsed-amount)))
|
|
(str/blank? (:raw parsed-amount)))
|
|
(set-parsed-amount
|
|
(assoc parsed-amount
|
|
:parsed value
|
|
:raw (cond
|
|
(str/blank? value)
|
|
""
|
|
|
|
(js/Number.isNaN (js/parseFloat value))
|
|
""
|
|
|
|
:else
|
|
(->short$ (js/parseFloat value))))))
|
|
nil))
|
|
[:div.control.has-icons-left
|
|
[:input.input {:type "text"
|
|
:disabled disabled
|
|
:placeholder placeholder
|
|
:class class
|
|
:on-change (fn [e]
|
|
(let [raw (.. e -target -value)
|
|
new-value (when (and raw
|
|
(not (str/blank? raw))
|
|
(re-find good-$ raw))
|
|
(js/parseFloat raw))]
|
|
(set-parsed-amount {:raw raw
|
|
:parsed new-value})
|
|
(when (not= value new-value)
|
|
(on-change new-value))))
|
|
:value (or (:raw parsed-amount)
|
|
"")
|
|
:on-blur (fn []
|
|
(when-not (re-find good-$ (:raw parsed-amount))
|
|
|
|
(set-parsed-amount {:raw ""
|
|
:parsed nil})
|
|
(on-change nil))
|
|
(when on-blur
|
|
(on-blur)))
|
|
:min min
|
|
:max max
|
|
:step "0.01"
|
|
:style (or style
|
|
{:width "8em"})}]
|
|
[:span.icon.is-left
|
|
[:i.fa.fa-usd]]]))
|
|
|
|
(defn money-field []
|
|
[:f> -money-field (r/props (r/current-component))])
|
|
|
|
(defn field []
|
|
[:f> -money-field (r/props (r/current-component))])
|