Wallet/Swap Input Component

This commit is contained in:
Ajay Sivan 2024-05-24 13:49:29 +05:30
parent af07205f20
commit bd9782d9b8
No known key found for this signature in database
GPG Key ID: 5F9AC120AE59597A
8 changed files with 300 additions and 5 deletions

View File

@ -1,5 +1,6 @@
(ns quo.components.avatars.token-avatar.view
(:require [quo.components.avatars.token-avatar.style :as style]
[quo.components.utilities.token.view :as token]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.platform :as platform]
@ -12,13 +13,14 @@
[:map {:closed true}
[:type {:optional true} [:enum :asset :collectible]]
[:context? {:optional true} [:maybe :boolean]]
[:image :schema.common/image-source]
[:image {:optional true} [:maybe :schema.common/image-source]]
[:token {:optional true} [:maybe [:or :keyword :string]]]
[:network-image {:optional true} [:maybe :schema.common/image-source]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn- view-internal
[{:keys [type context? image network-image container-style]}]
[{:keys [type context? image token network-image container-style]}]
[rn/view
{:style (merge style/container container-style)
:accessibility-label :token-avatar}
@ -32,9 +34,11 @@
[])
:style style/hole-view}
platform/android? (assoc :key context?))
[rn/image
{:source image
:style (style/image type)}]]
[token/view
{:size :size-32
:token token
:style (style/image type)
:image-source image}]]
(when context?
[rn/image
{:source network-image

View File

@ -0,0 +1,31 @@
(ns quo.components.wallet.swap-input.component-spec
(:require [quo.components.wallet.swap-input.view :as swap-input]
[test-helpers.component :as h]))
(h/describe "Wallet: Swap Input"
(h/test "should render correctly with props"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:error? false
:token "SNT"
:status :default
:currency-symbol "€"
:value "5"
:fait-value "1.50"
:network-tag-props {:title "Max: 200 SNT"}}])
(h/is-truthy (h/get-by-label-text :swap-input))
(h/is-truthy (h/get-by-text "SNT"))
(h/is-truthy (h/get-by-text "€1.50"))
(h/is-truthy (h/get-by-text "Max: 200 SNT")))
(h/test "should render correctly with approval label"
(h/render-with-theme-provider
[swap-input/view
{:type :pay
:show-approval-label? true
:approval-label-props
{:status :approve
:token-value "10"
:token-symbol "SNT"}}])
(h/is-truthy (h/get-by-text "Approve 10 SNT"))))

View File

@ -0,0 +1,69 @@
(ns quo.components.wallet.swap-input.style
(:require [quo.foundations.colors :as colors]
[quo.foundations.typography :as typography]))
(defn- border-color
[theme]
(colors/theme-colors colors/neutral-10 colors/neutral-80 theme))
(defn- loader-color
[theme]
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))
(defn content
[theme]
{:border-width 1
:border-radius 16
:border-color (border-color theme)
:background-color (colors/theme-colors colors/white colors/neutral-95 theme)})
(defn row-1
[loading?]
{:padding 12
:gap 8
:align-items (if loading? :center :flex-end)
:flex-direction :row})
(defn row-1-loader
[theme]
{:width 74
:height 14
:border-radius 6
:background-color (loader-color theme)})
(def input-container
{:flex 1
:flex-direction :row
:gap 5
:align-items :flex-end})
(defn input
[disabled? error? theme]
(merge {:font-size 27
:flex-shrink 1
:color (if error?
(colors/theme-colors colors/danger-50 colors/danger-60 theme)
(if disabled?
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)
(colors/theme-colors colors/neutral-100
colors/white
theme)))
:line-height 32}
typography/font-semi-bold))
(defn row-2
[align-right?]
{:flex-direction :row
:justify-content (if align-right? :flex-end :space-between)
:align-items :center
:padding 12})
(defn row-2-loader
[theme]
{:width 80
:height 10
:border-radius 6
:background-color (loader-color theme)})
(def fiat-amount
{:color colors/neutral-50})

View File

@ -0,0 +1,118 @@
(ns quo.components.wallet.swap-input.view
(:require [quo.components.avatars.token-avatar.view :as token-avatar]
[quo.components.buttons.button.view :as buttons]
[quo.components.dividers.divider-line.view :as divider-line]
[quo.components.markdown.text :as text]
[quo.components.tags.network-tags.view :as network-tag]
[quo.components.wallet.approval-label.schema :as approval-label.schema]
[quo.components.wallet.approval-label.view :as approval-label]
[quo.components.wallet.swap-input.style :as style]
[quo.foundations.colors :as colors]
quo.theme
[react-native.core :as rn]
[schema.core :as schema]))
(def ?schema
[:=>
[:catn
[:props
[:map {:closed true}
[:type {:optional true} [:maybe [:enum :pay :receive]]]
[:status {:optional true} [:maybe [:enum :default :disabled :loading]]]
[:token {:optional true} [:maybe :string]]
[:value {:optional true} [:maybe :string]]
[:default-value {:optional true} [:maybe :string]]
[:currency-symbol {:optional true} [:maybe :string]]
[:fait-value {:optional true} [:maybe :string]]
[:show-approval-label? {:optional true} [:maybe :boolean]]
[:error? {:optional true} [:maybe :boolean]]
[:approval-label-props {:optional true} [:maybe approval-label.schema/?schema]]
[:network-tag-props {:optional true} [:maybe :map]]
[:on-change-text {:optional true} [:maybe fn?]]
[:enable-swap? {:optional true} [:maybe :boolean]]
[:on-swap-press {:optional true} [:maybe fn?]]
[:on-token-press {:optional true} [:maybe fn?]]
[:on-max-press {:optional true} [:maybe fn?]]
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
[:container-style {:optional true} [:maybe :map]]]]]
:any])
(defn view-internal
[{:keys [type status token value fait-value show-approval-label? error? network-tag-props
approval-label-props default-value enable-swap?
currency-symbol on-change-text
container-style on-swap-press on-token-press on-max-press]}]
(let [theme (quo.theme/use-theme)
pay? (= type :pay)
disabled? (= status :disabled)
loading? (= status :loading)
controlled-input? (some? value)
input-ref (rn/use-ref-atom nil)
set-input-ref (rn/use-callback (fn [ref] (reset! input-ref ref)) [])
focus-input (rn/use-callback (fn [] (.focus ^js @input-ref))
[input-ref])]
[rn/view
{:style container-style
:accessibility-label :swap-input}
[rn/view {:style (style/content theme)}
[rn/view
{:style (style/row-1 loading?)}
[rn/pressable {:on-press on-token-press}
[token-avatar/view
{:type :asset
:token token}]]
(when loading? [rn/view {:style (style/row-1-loader theme)}])
(when-not loading?
[:<>
[rn/pressable
{:style style/input-container
:on-press focus-input}
[rn/text-input
(cond-> {:ref set-input-ref
:style (style/input disabled? error? theme)
:placeholder-text-color (colors/theme-colors colors/neutral-40
colors/neutral-50
theme)
:input-mode :decimal
:keyboard-type :decimal-pad
:auto-focus true
:on-change-text on-change-text
:editable (not disabled?)
:default-value default-value
:placeholder "0"}
controlled-input? (assoc :value value))]
[text/text
{:size :paragraph-2
:weight :semi-bold
:style {:margin-bottom 1
:color (colors/theme-colors colors/neutral-50 colors/neutral-40 theme)}}
token]]
(when (and pay? enable-swap?)
[buttons/button
{:type :outline
:size 32
:on-press on-swap-press
:icon-only? true} :i/reorder])])]
[divider-line/view]
[rn/view
{:style (style/row-2 (or (not pay?) loading?))}
(when-not loading?
[:<>
(when pay?
[rn/pressable {:on-press on-max-press}
[network-tag/view
(assoc network-tag-props
:status
(if error? :error :default))]])
[text/text
{:size :paragraph-2
:style style/fiat-amount
:weight :medium}
(str currency-symbol fait-value)]])
(when loading?
[rn/view {:style (style/row-2-loader theme)}])]]
(when (and (not= status :loading) show-approval-label?)
[approval-label/view
approval-label-props])]))
(def view (schema/instrument #'view-internal ?schema))

View File

@ -183,6 +183,7 @@
quo.components.wallet.progress-bar.view
quo.components.wallet.required-tokens.view
quo.components.wallet.summary-info.view
quo.components.wallet.swap-input.view
quo.components.wallet.token-input.view
quo.components.wallet.transaction-progress.view
quo.components.wallet.transaction-summary.view
@ -462,6 +463,7 @@
(def progress-bar quo.components.wallet.progress-bar.view/view)
(def required-tokens quo.components.wallet.required-tokens.view/view)
(def summary-info quo.components.wallet.summary-info.view/view)
(def swap-input quo.components.wallet.swap-input.view/view)
(def network-link quo.components.wallet.network-link.view/view)
(def token-input quo.components.wallet.token-input.view/view)
(def wallet-overview quo.components.wallet.wallet-overview.view/view)

View File

@ -109,6 +109,7 @@
quo.components.wallet.progress-bar.component-spec
quo.components.wallet.required-tokens.component-spec
quo.components.wallet.summary-info.component-spec
quo.components.wallet.swap-input.component-spec
quo.components.wallet.token-input.component-spec
quo.components.wallet.transaction-progress.component-spec
quo.components.wallet.transaction-summary.component-spec

View File

@ -209,6 +209,7 @@
[status-im.contexts.preview.quo.wallet.progress-bar :as progress-bar]
[status-im.contexts.preview.quo.wallet.required-tokens :as required-tokens]
[status-im.contexts.preview.quo.wallet.summary-info :as summary-info]
[status-im.contexts.preview.quo.wallet.swap-input :as swap-input]
[status-im.contexts.preview.quo.wallet.token-input :as token-input]
[status-im.contexts.preview.quo.wallet.transaction-progress :as transaction-progress]
[status-im.contexts.preview.quo.wallet.transaction-summary :as
@ -561,6 +562,7 @@
{:name :required-tokens
:component required-tokens/view}
{:name :summary-info :component summary-info/view}
{:name :swap-input :component swap-input/view}
{:name :token-input :component token-input/view}
{:name :wallet-activity :component wallet-activity/view}
{:name :transaction-progress :component transaction-progress/view}

View File

@ -0,0 +1,68 @@
(ns status-im.contexts.preview.quo.wallet.swap-input
(:require
[quo.core :as quo]
[quo.foundations.resources :as resources]
[react-native.core :as rn]
[status-im.contexts.preview.quo.preview :as preview]))
(def descriptor
[{:type :select
:key :type
:options [{:key :pay}
{:key :receive}]}
{:type :select
:key :status
:options [{:key :default}
{:key :disabled}
{:key :loading}]}
{:type :select
:key :value
:options [{:key :token}
{:key :fiat}]}
{:type :boolean
:key :error?}
{:type :boolean
:key :enable-swap?}
{:type :boolean
:key :show-approval-label?}
(preview/customization-color-option)])
(defn view
[]
(let [[state set-state] (rn/use-state {:type :pay
:error? false
:token "SNT"
:customization-color :blue
:show-approval-label? false
:enable-swap? true
:status :default
:currency-symbol "€"})
[value set-value] (rn/use-state "")
on-press (fn [v] (set-value (str value v)))
delete (fn [] (set-value #(subs % 0 (dec (count %)))))]
[preview/preview-container
{:state state
:set-state set-state
:descriptor descriptor}
[quo/swap-input
(assoc state
:on-swap-press #(js/alert "Swap Pressed")
:on-token-press #(js/alert "Token Pressed")
:on-max-press #(js/alert "Max Pressed")
:value value
:fait-value (str (.toFixed (* value 0.3) 2))
:container-style {:margin-bottom 20}
:network-tag-props {:title "Max: 200 SNT"
:networks [{:source (resources/get-network :ethereum)}]}
:approval-label-props
{:status :approve
:token-value "10"
:button-props {:on-press
#(js/alert "Approve Pressed")}
:customization-color (:customization-color state)
:token-symbol "SNT"})]
[quo/numbered-keyboard
{:left-action :dot
:delete-key? true
:on-press on-press
:on-delete delete}]]))