1
- import { Button , Card , Paragraph , Spinner , Theme , XStack , YStack } from '@my/ui'
1
+ import {
2
+ Card ,
3
+ type CardProps ,
4
+ H1 ,
5
+ Paragraph ,
6
+ Spinner ,
7
+ Theme ,
8
+ ThemeableStack ,
9
+ useMedia ,
10
+ XStack ,
11
+ type XStackProps ,
12
+ } from '@my/ui'
2
13
import formatAmount from 'app/utils/formatAmount'
3
14
4
15
import { ChevronLeft , ChevronRight } from '@tamagui/lucide-icons'
5
16
6
17
import { useIsPriceHidden } from './utils/useIsPriceHidden'
7
18
8
19
import { useSendAccountBalances } from 'app/utils/useSendAccountBalances'
9
- import { investmentCoins } from 'app/data/coins'
20
+ import { type CoinWithBalance , investmentCoins } from 'app/data/coins'
10
21
11
22
import { useRootScreenParams } from 'app/routers/params'
12
23
import { useMultipleTokensMarketData } from 'app/utils/coin-gecko'
13
24
import { useMemo } from 'react'
14
- import { IconError } from 'app/components/icons'
25
+ import { IconCoin , IconError } from 'app/components/icons'
15
26
import { useCoins } from 'app/provider/coins'
27
+ import { investmentCoins as investmentCoinsList } from 'app/data/coins'
16
28
17
- export const InvestmentsBalanceCard = ( ) => {
29
+ export const InvestmentsBalanceCard = ( props : CardProps ) => {
30
+ const media = useMedia ( )
18
31
const [ queryParams , setParams ] = useRootScreenParams ( )
19
32
const isInvestmentCoin = investmentCoins . some (
20
- ( coin ) => coin . token . toLowerCase ( ) === queryParams . token
33
+ ( coin ) => coin . token . toLowerCase ( ) === queryParams . token ?. toLowerCase ( )
21
34
)
22
35
const isInvestmentsScreen = queryParams . token === 'investments'
23
36
@@ -39,62 +52,107 @@ export const InvestmentsBalanceCard = () => {
39
52
const formattedBalance = formatAmount ( dollarTotal , 9 , 0 )
40
53
41
54
return (
42
- < Card py = "$5" px = "$4" w = { '100%' } jc = "space-between" onPress = { toggleSubScreen } >
43
- < YStack jc = { 'center' } gap = { '$5' } w = { '100%' } >
44
- < YStack w = { '100%' } gap = { '$2.5' } jc = "space-between" >
45
- < XStack ai = { 'center' } jc = { 'space-between' } gap = "$2.5" width = { '100%' } >
46
- < Paragraph fontSize = { '$7' } fontWeight = "400" >
47
- Invest
48
- </ Paragraph >
49
- < Button
50
- chromeless
51
- backgroundColor = "transparent"
52
- hoverStyle = { { backgroundColor : 'transparent' } }
53
- pressStyle = { {
54
- backgroundColor : 'transparent' ,
55
- borderColor : 'transparent' ,
56
- } }
57
- focusStyle = { { backgroundColor : 'transparent' } }
58
- p = { 0 }
59
- height = { 'auto' }
60
- >
61
- < Button . Icon >
62
- { isInvestmentCoin || isInvestmentsScreen ? (
63
- < ChevronLeft
64
- size = { '$1.5' }
65
- color = { '$lightGrayTextField' }
66
- $theme-light = { { color : '$darkGrayTextField' } }
67
- $lg = { { display : 'none' } }
68
- />
69
- ) : (
70
- < ChevronRight
71
- size = { '$1.5' }
72
- color = { '$primary' }
73
- $theme-light = { { color : '$color12' } }
74
- />
75
- ) }
76
- </ Button . Icon >
77
- </ Button >
78
- </ XStack >
79
- </ YStack >
80
- < Paragraph fontSize = { '$10' } fontWeight = { '600' } color = { '$color12' } >
81
- { ( ( ) => {
82
- switch ( true ) {
83
- case isPriceHidden :
84
- return '///////'
85
- case isLoading || ! dollarBalances :
86
- return < Spinner size = { 'large' } />
87
- default :
88
- return `$${ formattedBalance } `
89
- }
90
- } ) ( ) }
55
+ < Card
56
+ elevate
57
+ hoverStyle = { { scale : 0.925 } }
58
+ pressStyle = { { scale : 0.875 } }
59
+ animation = "bouncy"
60
+ onPress = { toggleSubScreen }
61
+ size = { '$5' }
62
+ br = "$7"
63
+ { ...props }
64
+ >
65
+ < Card . Header padded pb = { 0 } fd = "row" ai = "center" jc = "space-between" >
66
+ < Paragraph fontSize = { '$5' } fontWeight = "400" >
67
+ Invest
91
68
</ Paragraph >
92
- < InvestmentsAggregate />
93
- </ YStack >
69
+ { isInvestmentCoin || isInvestmentsScreen ? (
70
+ < ChevronLeft
71
+ size = { '$1' }
72
+ color = { '$primary' }
73
+ $theme-light = { { color : '$color12' } }
74
+ $lg = { { display : 'none' } }
75
+ />
76
+ ) : (
77
+ < ChevronRight
78
+ size = { '$1' }
79
+ color = { '$lightGrayTextField' }
80
+ $theme-light = { { color : '$darkGrayTextField' } }
81
+ />
82
+ ) }
83
+ </ Card . Header >
84
+ < Card . Footer padded pt = { 0 } fd = "column" >
85
+ { isInvestmentsScreen && ! media . gtLg ? (
86
+ < >
87
+ < Paragraph color = { '$color12' } fontWeight = { 500 } size = { '$10' } >
88
+ { ( ( ) => {
89
+ switch ( true ) {
90
+ case isPriceHidden :
91
+ return '///////'
92
+ case isLoading || ! dollarBalances :
93
+ return < Spinner size = { 'large' } color = { '$color12' } />
94
+ default :
95
+ return `$${ formattedBalance } `
96
+ }
97
+ } ) ( ) }
98
+ </ Paragraph >
99
+ < InvestmentsAggregate />
100
+ </ >
101
+ ) : (
102
+ < >
103
+ < InvestmentsPreview />
104
+ < InvestmentsAggregate />
105
+ </ >
106
+ ) }
107
+ </ Card . Footer >
94
108
</ Card >
95
109
)
96
110
}
97
111
112
+ function InvestmentsPreview ( ) {
113
+ const { investmentCoins, isLoading } = useCoins ( )
114
+
115
+ if ( isLoading ) return < Spinner size = "small" />
116
+
117
+ const existingSymbols = new Set ( investmentCoins . map ( ( coin ) => coin . symbol ) )
118
+ const coins = [
119
+ ...investmentCoins ,
120
+ ...investmentCoinsList
121
+ . filter ( ( coin ) => ! existingSymbols . has ( coin . symbol ) )
122
+ . map ( ( coin ) => ( { ...coin , balance : 0n } ) ) ,
123
+ ]
124
+
125
+ const sortedByBalance = coins . toSorted ( ( a , b ) =>
126
+ ( b ?. balance ?? 0n ) > ( a ?. balance ?? 0n ) ? 1 : - 1
127
+ )
128
+ return (
129
+ < XStack ai = "center" jc = "space-between" >
130
+ < OverlappingCoinIcons coins = { sortedByBalance } />
131
+ < Card circular ai = "center" jc = "center" bc = "$color0" w = { '$3.5' } h = "$3.5" mih = { 0 } miw = { 0 } >
132
+ < Paragraph fontSize = { '$4' } fontWeight = "500" >
133
+ { `+${ investmentCoinsList . length - 3 } ` }
134
+ </ Paragraph >
135
+ </ Card >
136
+ </ XStack >
137
+ )
138
+ }
139
+
140
+ function OverlappingCoinIcons ( {
141
+ coins,
142
+ length = 3 ,
143
+ ...props
144
+ } : { coins : CoinWithBalance [ ] ; length ?: number } & XStackProps ) {
145
+ return (
146
+ < XStack ai = "center" { ...props } >
147
+ { coins . slice ( 0 , length ) . map ( ( { symbol } ) => (
148
+ < ThemeableStack key = { symbol } circular mr = { '$-3.5' } bc = "transparent" ai = "center" jc = "center" >
149
+ < IconCoin size = { '$3' } symbol = { symbol } />
150
+ </ ThemeableStack >
151
+ ) ) }
152
+ </ XStack >
153
+ )
154
+ }
155
+
98
156
function InvestmentsAggregate ( ) {
99
157
const tokenIds = useCoins ( )
100
158
. investmentCoins . filter ( ( c ) => c ?. balance && c . balance > 0n )
@@ -117,7 +175,7 @@ function InvestmentsAggregate() {
117
175
return (
118
176
< XStack gap = "$2" ai = "center" >
119
177
< Paragraph color = "$color10" $gtXs = { { fontSize : 14 } } fontSize = { 12 } >
120
- Add popular crypto assets to your portfolio
178
+ Diversify Your Crypto Portfolio
121
179
</ Paragraph >
122
180
</ XStack >
123
181
)
0 commit comments