Files
integreat/src/cljs/auto_ap/views/components/money_field.cljs

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