vendor querying step 1.
This commit is contained in:
@@ -14,8 +14,7 @@
|
||||
(not (get-in accounts [0 :account :id]))))
|
||||
|
||||
(defn default-account [accounts default-account amount locations]
|
||||
[{:id (get-in accounts [0 :id]
|
||||
(str "new-" (random-uuid)))
|
||||
[{:id (str "new-" (random-uuid))
|
||||
:amount (Math/abs amount)
|
||||
:amount-percentage 100
|
||||
:amount-mode "%"
|
||||
|
||||
134
src/cljs/auto_ap/views/components/typeahead/vendor.cljs
Normal file
134
src/cljs/auto_ap/views/components/typeahead/vendor.cljs
Normal file
@@ -0,0 +1,134 @@
|
||||
(ns auto-ap.views.components.typeahead.vendor
|
||||
(:require
|
||||
[downshift :as ds :refer [useCombobox]]
|
||||
[re-frame.core :as re-frame]
|
||||
[auto-ap.views.utils :refer [with-user]]
|
||||
[react]))
|
||||
|
||||
(set! *warn-on-infer* true)
|
||||
|
||||
;; TODO: This avoids the use of inferred externs by using aget. You could just use the ^js tag though
|
||||
(defn state-reducer [^js/FakeStateObject state ^js/FakeActionsAndChanges actions-and-changes]
|
||||
(let [useCombobox ^js/Downshift useCombobox]
|
||||
(cond
|
||||
(= (.-type actions-and-changes) (.-InputChange (.-stateChangeTypes ^js/Downshift useCombobox)))
|
||||
(set! (.-selectedItem (.-changes actions-and-changes)) nil)
|
||||
|
||||
(and (= (.-type actions-and-changes) (.-InputBlur (.-stateChangeTypes ^js/Downshift useCombobox)))
|
||||
(not (.-selectedItem state)))
|
||||
(set! (.-inputValue (.-changes actions-and-changes ))
|
||||
nil)
|
||||
|
||||
:else
|
||||
nil))
|
||||
(.-changes actions-and-changes))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::search-completed
|
||||
(fn [_ [_ set-items set-loading-status result]]
|
||||
(set-loading-status nil)
|
||||
(set-items (:search-results result))
|
||||
{}))
|
||||
(re-frame/reg-event-fx
|
||||
::search-failed
|
||||
(fn [_ _]
|
||||
{}))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::input-value-settled
|
||||
[with-user]
|
||||
(fn [{:keys [user]} [_ input-value search-query set-items set-loading-status]]
|
||||
(when (> (count input-value) 2)
|
||||
(set-loading-status :loading)
|
||||
|
||||
|
||||
{:graphql {:token user
|
||||
:query-obj {:venia/queries [{:query/data (search-query input-value )
|
||||
:query/alias :search-results}]}
|
||||
:on-success [::search-completed set-items set-loading-status]
|
||||
:on-error [::search-failed set-loading-status]}})))
|
||||
|
||||
(re-frame/reg-event-fx
|
||||
::input-value-changed
|
||||
(fn [_ [_ input-value search-query set-items set-loading-status]]
|
||||
(set-items [])
|
||||
(when (> (count input-value) 2)
|
||||
(set-loading-status :loading)
|
||||
{:dispatch-debounce {:event [::input-value-settled input-value search-query set-items set-loading-status]
|
||||
:time 250
|
||||
:key ::input-value-settled}})))
|
||||
|
||||
(defn typeahead-v3-internal [{:keys [class style ^js entity->text on-change disabled value name search-query auto-focus] :or {disabled false} :as i}]
|
||||
(let [[items set-items] (react/useState [])
|
||||
[loading-status set-loading-status] (react/useState false)
|
||||
[getLabelProps getMenuProps getComboboxProps getToggleButtonProps getInputProps getItemProps isOpen highlightedIndex selectItem selectedItem setInputValue]
|
||||
(as-> (useCombobox (clj->js {:items items
|
||||
:defaultHighlightedIndex 0
|
||||
:defaultSelectedItem value
|
||||
:onInputValueChange (fn [input]
|
||||
(re-frame/dispatch [::input-value-changed (aget input "inputValue") search-query set-items set-loading-status])
|
||||
true)
|
||||
:stateReducer state-reducer
|
||||
:onSelectedItemChange (fn [z]
|
||||
(when on-change
|
||||
(on-change (js->clj (aget z "selectedItem") :keywordize-keys true))))})) $
|
||||
(map #(aget $ %) ["getLabelProps" "getMenuProps" "getComboboxProps" "getToggleButtonProps" "getInputProps" "getItemProps" "isOpen" "highlightedIndex" "selectItem" "selectedItem" "setInputValue"]))]
|
||||
#_(println (getInputProps))
|
||||
|
||||
[:<>
|
||||
[:div.typeahead (assoc (js->clj (getComboboxProps))
|
||||
:style style)
|
||||
(cond
|
||||
selectedItem
|
||||
^{:key "typeahead"}
|
||||
[:div.input (assoc (js->clj (getInputProps #js {:disabled (if disabled
|
||||
"disabled"
|
||||
"")}))
|
||||
:on-key-up (fn [e]
|
||||
(when (= 8 (aget e "keyCode" ))
|
||||
(selectItem nil)
|
||||
(setInputValue nil)
|
||||
(when on-change
|
||||
(on-change nil))))
|
||||
:class (if (= :loading loading-status)
|
||||
"is-loading"
|
||||
class)
|
||||
:tab-index "0")
|
||||
[:div.control
|
||||
[:div.tags.has-addons
|
||||
[:span.tag (entity->text (js->clj selectedItem :keywordize-keys true))]
|
||||
(when name
|
||||
[:input {:type "hidden" :name name :value (:id (js->clj selectedItem :keywordize-keys true))}])
|
||||
(when-not disabled
|
||||
[:a.tag.is-delete {:on-click (fn []
|
||||
(setInputValue nil)
|
||||
(selectItem nil)
|
||||
(when on-change
|
||||
(on-change nil)))}])]]]
|
||||
|
||||
:else
|
||||
^{:key "typeahead"} [:div.control {:class (when (= :loading loading-status)
|
||||
"is-loading")}
|
||||
[:input.input (js->clj
|
||||
(getInputProps #js {:disabled (if disabled
|
||||
"disabled"
|
||||
"")
|
||||
:autoFocus (if auto-focus
|
||||
"autoFocus"
|
||||
"")}))]])
|
||||
[:div {:class (when (and isOpen (seq items))
|
||||
"typeahead-menu")}
|
||||
[:ul (js->clj (getMenuProps))
|
||||
(if (and isOpen (seq items))
|
||||
(for [[index item] (map vector (range) (js->clj items :keywordize-keys true))]
|
||||
^{:key item}
|
||||
[:li.typeahead-suggestion (assoc (js->clj (getItemProps #js {:item item :index index}))
|
||||
:class (if (= index highlightedIndex)
|
||||
"typeahead-highlighted"))
|
||||
(entity->text item)]))]]]]))
|
||||
|
||||
(defn search-backed-typeahead [props]
|
||||
[:div
|
||||
[:f> typeahead-v3-internal (assoc props
|
||||
:entity->text :name
|
||||
)]])
|
||||
Reference in New Issue
Block a user