From 30175f5d8bd893b2712d69f8a3cfbe8ec69f0c0c Mon Sep 17 00:00:00 2001 From: Ibrahem Khalil Date: Thu, 10 Aug 2023 09:19:47 +0300 Subject: [PATCH] feat: Account overview component (#16742) --- .../account_overview/component_spec.cljs | 65 ++++++++ .../wallet/account_overview/style.cljs | 106 +++++++++++++ .../wallet/account_overview/view.cljs | 139 ++++++++++++++++++ src/quo2/core.cljs | 4 +- src/quo2/core_spec.cljs | 1 + src/status_im2/contexts/quo_preview/main.cljs | 4 + .../quo_preview/wallet/account_overview.cljs | 104 +++++++++++++ 7 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 src/quo2/components/wallet/account_overview/component_spec.cljs create mode 100644 src/quo2/components/wallet/account_overview/style.cljs create mode 100644 src/quo2/components/wallet/account_overview/view.cljs create mode 100644 src/status_im2/contexts/quo_preview/wallet/account_overview.cljs diff --git a/src/quo2/components/wallet/account_overview/component_spec.cljs b/src/quo2/components/wallet/account_overview/component_spec.cljs new file mode 100644 index 0000000000..e37fff4f74 --- /dev/null +++ b/src/quo2/components/wallet/account_overview/component_spec.cljs @@ -0,0 +1,65 @@ +(ns quo2.components.wallet.account-overview.component-spec + (:require [quo2.components.wallet.account-overview.view :as account-overview] + [test-helpers.component :as h])) + +(h/describe "Account overview test" + (h/test "renders correct account name" + (h/render [account-overview/view + {:state :default + :account-name "Diamond Hand"}]) + (h/is-truthy (h/get-by-text "Diamond Hand"))) + + (h/test "renders correct account value" + (h/render [account-overview/view + {:current-value "20.0$"}]) + (h/is-truthy (h/get-by-text "20.0$"))) + + (h/test "renders correct account changes" + (h/render [account-overview/view + {:currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-text "0.00%")) + (h/is-truthy (h/get-by-text "€0.00"))) + + (h/test "renders correct timeframe" + (h/render [account-overview/view + {:time-frame :custom + :time-frame-string "15 May" + :time-frame-to-string "19 May"}]) + (h/is-truthy (h/get-by-text "15 May")) + (h/is-truthy (h/get-by-text "19 May"))) + + (h/test "renders correct account timeframe" + (h/render [account-overview/view + {:time-frame :one-week + :currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-translation-text :t/one-week-int))) + + (h/test "renders correct account timeframe" + (h/render [account-overview/view + {:time-frame :one-month + :currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-translation-text :t/one-month-int))) + + (h/test "renders correct account timeframe" + (h/render [account-overview/view + {:time-frame :three-months + :currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-translation-text :t/three-months-int))) + + (h/test "renders correct account timeframe" + (h/render [account-overview/view + {:time-frame :one-year + :currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-translation-text :t/one-year))) + + (h/test "renders correct account timeframe" + (h/render [account-overview/view + {:time-frame :all-time + :currency-change "€0.00" + :percentage-change "0.00%"}]) + (h/is-truthy (h/get-by-translation-text :t/all-time)))) diff --git a/src/quo2/components/wallet/account_overview/style.cljs b/src/quo2/components/wallet/account_overview/style.cljs new file mode 100644 index 0000000000..35d5a32bfc --- /dev/null +++ b/src/quo2/components/wallet/account_overview/style.cljs @@ -0,0 +1,106 @@ +(ns quo2.components.wallet.account-overview.style + (:require [quo2.foundations.colors :as colors])) + +(def account-overview-wrapper + {:padding-top 24 + :padding-horizontal 20 + :padding-bottom 20 + :height 78 + :align-items :center + :justify-content :center}) + +(defn account-name + [color] + {:margin-bottom 4 + :color color}) + +(def reveal-icon + {:margin-left 4 + :margin-top 2}) + +(def current-value + {:margin-bottom 2}) + +(def row-centered + {:flex-direction :row + :justify-content :center}) + +(defn bottom-time-text + [margin-right?] + {:margin-right (when margin-right? 8) + :color colors/neutral-80-opa-40}) + +(def right-arrow + {:margin-top 1 + :margin-right 1}) + +(def bottom-time-to-text + {:margin-right 8 + :color colors/neutral-80-opa-40}) + +(defn percentage-change + [customization-color theme] + {:color (colors/theme-colors + (colors/custom-color customization-color 50) + (colors/custom-color customization-color 60) + theme) + :margin-right 4}) + +(defn dot-separator + [customization-color theme] + {:background-color (colors/theme-colors + (colors/custom-color customization-color 60 40) + (colors/custom-color customization-color 50 40) + theme) + :margin-right 4 + :margin-top 8 + :width 2 + :height 2}) + +(defn currency-change + [customization-color theme] + {:color (colors/theme-colors + (colors/custom-color customization-color 50) + (colors/custom-color customization-color 60) + theme) + :margin-right 4}) + +(defn loading-bar-margin-bottom + [{:keys [width height color margin-bottom]}] + {:style {:width width + :height height + :border-radius 6 + :background-color color + :margin-bottom margin-bottom}}) + +(defn loading-bar-margin-right + [color] + {:width 32 + :height 10 + :border-radius 6 + :background-color color + :margin-right 2}) + +(defn loading-bar-margin-right-extra + [{:keys [color width height margin-right]}] + {:width width + :height height + :border-radius 6 + :background-color color + :margin-right margin-right}) + +(defn loading-bar-tiny + [color] + {:width 10 + :height 10 + :border-radius 6 + :background-color color + :margin-right 8}) + +(defn icon-props + [customization-color theme] + {:color (colors/theme-colors + (colors/custom-color customization-color 50) + (colors/custom-color customization-color 60) + theme) + :size 16}) diff --git a/src/quo2/components/wallet/account_overview/view.cljs b/src/quo2/components/wallet/account_overview/view.cljs new file mode 100644 index 0000000000..f4f4f9cf53 --- /dev/null +++ b/src/quo2/components/wallet/account_overview/view.cljs @@ -0,0 +1,139 @@ +(ns quo2.components.wallet.account-overview.view + (:require [quo2.components.icon :as icons] + [quo2.components.markdown.text :as text] + [quo2.foundations.colors :as colors] + [react-native.core :as rn] + [utils.i18n :as i18n] + [quo2.components.wallet.account-overview.style :as style] + [quo2.theme :as quo.theme])) + +(defn- loading-state + [color] + [:<> + [rn/view + (style/loading-bar-margin-bottom {:color color + :width 104 + :height 14 + :margin-bottom 14})] + [rn/view + (style/loading-bar-margin-bottom {:color color + :width 152 + :height 20 + :margin-bottom 12})] + [rn/view {:style {:flex-direction :row}} + [rn/view {:style (style/loading-bar-margin-right color)}] + [rn/view {:style (style/loading-bar-margin-right color)}] + [rn/view + {:style (style/loading-bar-margin-right-extra {:color color + :width 62 + :height 10 + :margin-right 4})}] + [rn/view {:style (style/loading-bar-tiny color)}]]]) + +(defn- time-string + [time-frame time-frame-string] + (case time-frame + :one-week (i18n/label :t/one-week-int) + :one-month (i18n/label :t/one-month-int) + :three-months (i18n/label :t/three-months-int) + :one-year (i18n/label :t/one-year) + :all-time (i18n/label :t/all-time) + time-frame-string)) + +(defn- custom-time-frame + [time-frame-to-string] + [:<> + [icons/icon :i/positive-right + {:size 16 + :container-style style/right-arrow + :color colors/neutral-80-opa-90}] + [text/text + {:weight :medium + :size :paragraph-2 + :style style/bottom-time-to-text} + time-frame-to-string]]) + +(defn- numeric-changes + [percentage-change currency-change customization-color theme up?] + [:<> + [text/text + {:weight :medium + :size :paragraph-2 + :style (style/percentage-change customization-color theme)} + percentage-change] + [rn/view + {:style (style/dot-separator customization-color theme)}] + [text/text + {:weight :medium + :size :paragraph-2 + :style (style/currency-change customization-color theme)} + currency-change] + [icons/icon + (if up? + :i/positive + :i/negative) + (style/icon-props customization-color theme)]]) + +(defn- account-details + [account-name account theme] + [rn/view {:style {:flex-direction :row}} + [text/text + {:weight :medium + :size :paragraph-1 + :style (style/account-name (colors/theme-colors colors/neutral-100 colors/white theme))} + account-name] + (when (= account :watched-address) + [icons/icon :i/reveal + {:container-style style/reveal-icon + :color (colors/theme-colors colors/neutral-80-opa-40 + colors/white-opa-40 + theme)}])]) + +(defn- view-internal + [{:keys [state account time-frame time-frame-string time-frame-to-string account-name current-value + percentage-change currency-change theme metrics customization-color] + :or {customization-color :blue}}] + (let [time-frame-string (time-string time-frame time-frame-string) + up? (= metrics :positive)] + [rn/view + {:style style/account-overview-wrapper} + (if (= :loading state) + [loading-state (colors/theme-colors colors/neutral-5 colors/neutral-90 theme)] + [:<> + [account-details account-name account theme] + [text/text + {:weight :semi-bold + :size :heading-1 + :style style/current-value} + current-value] + [rn/view + {:style style/row-centered} + [:<> + (when (seq time-frame-string) + [text/text + {:weight :medium + :size :paragraph-2 + :style (style/bottom-time-text (and (not= :custom time-frame) + (seq time-frame-to-string)))} + time-frame-string]) + (when (and (= :custom time-frame) + (seq time-frame-to-string)) + [custom-time-frame time-frame-to-string])] + (when (and (seq percentage-change) + (seq currency-change)) + [numeric-changes percentage-change currency-change customization-color theme up?])]])])) + +(def view + "Create a account-overview UI component. + | key | description | + | -------------|-------------| + | `:account-name` | A value representing the account name (default `nil`) + | `:account` | A value that represents if the account is a `:watched-account` or a `:default` account. (default `nil`) + | `:time-frame` | A value that represents the type of the timeframe, Can be from a preset of time frames. `[:1-week :1-month :3-months :1-year :custom]` (default `nil`) if custom is set, We expect a start time and if there's a space between two times that are in `time-frame-string` we'll split them with an arrow to the right icon + | `:loading?` | A value that indicates that component is loading data. (default `nil`) + | `:metrics` | A value that indicates if the account value have increased can be `:positive` or `:negative` (default `nil`) + | `:time-frame-string` | A value representing time frame string. (default `nil`) + | `:current-value` | A value representing the current value of the selected account. (default `nil`) + | `:currency-change` | A value representing the change of the value of the selected account in the selected currency. (default `nil`) + | `:percentage-change` | A value representing the change of the value of the selected account in percentage relative to it's previous value. (default `nil`)" + (quo.theme/with-theme view-internal)) diff --git a/src/quo2/core.cljs b/src/quo2/core.cljs index 0342554689..4308e0fa29 100644 --- a/src/quo2/core.cljs +++ b/src/quo2/core.cljs @@ -105,6 +105,7 @@ quo2.components.tags.tags quo2.components.tags.token-tag quo2.components.text-combinations.title.view + quo2.components.wallet.account-overview.view quo2.components.wallet.account-card.view quo2.components.wallet.network-amount.view quo2.components.wallet.network-bridge.view @@ -306,9 +307,10 @@ (def gradient-cover quo2.components.gradient.gradient-cover.view/view) ;;;; WALLET +(def account-card quo2.components.wallet.account-card.view/view) +(def account-overview quo2.components.wallet.account-overview.view/view) (def network-amount quo2.components.wallet.network-amount.view/view) (def network-bridge quo2.components.wallet.network-bridge.view/view) -(def account-card quo2.components.wallet.account-card.view/view) (def progress-bar quo2.components.wallet.progress-bar.view/view) (def summary-info quo2.components.wallet.summary-info.view/view) (def token-input quo2.components.wallet.token-input.view/view) diff --git a/src/quo2/core_spec.cljs b/src/quo2/core_spec.cljs index 7449b0ab8b..ebb579e572 100644 --- a/src/quo2/core_spec.cljs +++ b/src/quo2/core_spec.cljs @@ -51,6 +51,7 @@ [quo2.components.settings.category.component-spec] [quo2.components.share.share-qr-code.component-spec] [quo2.components.tags.status-tags-component-spec] + [quo2.components.wallet.account-overview.component-spec] [quo2.components.wallet.account-card.component-spec] [quo2.components.wallet.network-amount.component-spec] [quo2.components.wallet.network-bridge.component-spec] diff --git a/src/status_im2/contexts/quo_preview/main.cljs b/src/status_im2/contexts/quo_preview/main.cljs index c1d5d72011..c9638e4450 100644 --- a/src/status_im2/contexts/quo_preview/main.cljs +++ b/src/status_im2/contexts/quo_preview/main.cljs @@ -106,6 +106,7 @@ [status-im2.contexts.quo-preview.loaders.skeleton :as skeleton] [status-im2.contexts.quo-preview.community.channel-actions :as channel-actions] [status-im2.contexts.quo-preview.gradient.gradient-cover :as gradient-cover] + [status-im2.contexts.quo-preview.wallet.account-overview :as account-overview] [status-im2.contexts.quo-preview.wallet.account-card :as account-card] [status-im2.contexts.quo-preview.wallet.network-amount :as network-amount] [status-im2.contexts.quo-preview.wallet.network-bridge :as network-bridge] @@ -421,6 +422,9 @@ :wallet [{:name :account-card :options {:topBar {:visible true}} :component account-card/preview-account-card} + {:name :account-overview + :options {:topBar {:visible true}} + :component account-overview/preview-account-overview} {:name :network-amount :options {:topBar {:visible true}} :component network-amount/preview} diff --git a/src/status_im2/contexts/quo_preview/wallet/account_overview.cljs b/src/status_im2/contexts/quo_preview/wallet/account_overview.cljs new file mode 100644 index 0000000000..67ab368ee4 --- /dev/null +++ b/src/status_im2/contexts/quo_preview/wallet/account_overview.cljs @@ -0,0 +1,104 @@ +(ns status-im2.contexts.quo-preview.wallet.account-overview + (:require [quo2.core :as quo] + [quo2.foundations.colors :as colors] + [react-native.core :as rn] + [reagent.core :as reagent] + [status-im2.contexts.quo-preview.preview :as preview])) + +(def descriptor + [{:label "Time frame string" + :key :time-frame-string + :type :text} + {:label "Time frame to string" + :key :time-frame-to-string + :type :text} + {:label "Percentage change" + :key :percentage-change + :type :text} + {:label "Currency change" + :key :currency-change + :type :text} + {:label "Current value" + :key :current-value + :type :text} + {:label "State" + :key :state + :type :select + :options [{:key :default + :value "Default"} + {:key :loading + :value "Loading"}]} + {:label "Metrics" + :key :metrics + :type :select + :options [{:key "Positive" + :value :positive} + {:key "Negative" + :value :negative}]} + {:label "Account name" + :key :account-name + :type :text} + {:label "Customization color:" + :key :customization-color + :type :select + :options (map (fn [color] + (let [k (get color :name)] + {:key k :value k})) + (quo/picker-colors))} + {:label "Account" + :key :account + :type :select + :options [{:key :watched-address + :value "Watched address"} + {:key :default + :value "Default"}]} + {:label "Time frame" + :key :time-frame + :type :select + :options [{:key :one-week + :value "1 Week"} + {:key :one-month + :value "1 Month"} + {:key :three-months + :value "3 Months"} + {:key :one-year + :value "1 Year"} + {:key :all-time + :value "All time"} + {:key :custom + :value "Custom"}]}]) + +(defn cool-preview + [] + (let [state (reagent/atom {:metrics :positive + :currency-change "€0.00" + :percentage-change "0.00%" + :current-value "€0.00" + :account-name "Diamond Hand" + :time-frame :custom + :time-frame-string "16 May" + :time-frame-to-string "25 May" + :account :default + :customization-color :blue})] + (fn [] + [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} + [rn/view {:style {:padding-bottom 150}} + [rn/view {:style {:flex 1}} + [preview/customizer state descriptor]] + [rn/view + {:style {:padding-vertical 60 + :flex-direction :row + :justify-content :center}} + [quo/account-overview @state]]]]))) + +(defn preview-account-overview + [] + [rn/view + {:style {:background-color (colors/theme-colors colors/white + colors/neutral-95) + :flex 1}} + [rn/flat-list + {:flex 1 + :keyboard-should-persist-taps :always + :header [cool-preview] + :key-fn str}]])