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
+ useMedia ,
9
+ XStack ,
10
+ type XStackProps ,
11
+ } from '@my/ui'
2
12
import formatAmount from 'app/utils/formatAmount'
3
13
4
14
import { ChevronLeft , ChevronRight } from '@tamagui/lucide-icons'
5
15
6
16
import { useIsPriceHidden } from './utils/useIsPriceHidden'
7
17
8
18
import { useSendAccountBalances } from 'app/utils/useSendAccountBalances'
9
- import { investmentCoins } from 'app/data/coins'
19
+ import { type CoinWithBalance , investmentCoins } from 'app/data/coins'
10
20
11
21
import { useRootScreenParams } from 'app/routers/params'
12
22
import { useMultipleTokensMarketData } from 'app/utils/coin-gecko'
13
23
import { useMemo } from 'react'
14
- import { IconError } from 'app/components/icons'
24
+ import { IconCoin , IconError } from 'app/components/icons'
15
25
import { useCoins } from 'app/provider/coins'
26
+ import { investmentCoins as investmentCoinsList } from 'app/data/coins'
16
27
17
- export const InvestmentsBalanceCard = ( ) => {
28
+ export const InvestmentsBalanceCard = ( props : CardProps ) => {
29
+ const media = useMedia ( )
18
30
const [ queryParams , setParams ] = useRootScreenParams ( )
19
31
const isInvestmentCoin = investmentCoins . some (
20
- ( coin ) => coin . token . toLowerCase ( ) === queryParams . token
32
+ ( coin ) => coin . token . toLowerCase ( ) === queryParams . token ?. toLowerCase ( )
21
33
)
22
34
const isInvestmentsScreen = queryParams . token === 'investments'
23
35
@@ -39,62 +51,105 @@ export const InvestmentsBalanceCard = () => {
39
51
const formattedBalance = formatAmount ( dollarTotal , 9 , 0 )
40
52
41
53
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
- } ) ( ) }
54
+ < Card
55
+ elevate
56
+ hoverStyle = { { scale : 0.925 } }
57
+ pressStyle = { { scale : 0.875 } }
58
+ animation = "bouncy"
59
+ onPress = { toggleSubScreen }
60
+ size = { '$5' }
61
+ br = "$7"
62
+ w = "100%"
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 fd = "column" gap = "$2" >
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
+ < InvestmentsPreview />
103
+ ) }
104
+ </ Card . Footer >
94
105
</ Card >
95
106
)
96
107
}
97
108
109
+ function InvestmentsPreview ( ) {
110
+ const { investmentCoins, isLoading } = useCoins ( )
111
+
112
+ if ( isLoading ) return < Spinner size = "small" />
113
+
114
+ const existingSymbols = new Set ( investmentCoins . map ( ( coin ) => coin . symbol ) )
115
+ const coins = [
116
+ ...investmentCoins ,
117
+ ...investmentCoinsList
118
+ . filter ( ( coin ) => ! existingSymbols . has ( coin . symbol ) )
119
+ . map ( ( coin ) => ( { ...coin , balance : 0n } ) ) ,
120
+ ]
121
+
122
+ const sortedByBalance = coins . toSorted ( ( a , b ) =>
123
+ ( b ?. balance ?? 0n ) > ( a ?. balance ?? 0n ) ? 1 : - 1
124
+ )
125
+ return (
126
+ < XStack ai = "center" jc = "space-between" >
127
+ < OverlappingCoinIcons coins = { sortedByBalance } />
128
+ < Card circular ai = "center" jc = "center" bc = "$color0" w = { '$3.5' } h = "$3.5" mih = { 0 } miw = { 0 } >
129
+ < Paragraph fontSize = { '$4' } fontWeight = "500" >
130
+ { `+${ investmentCoinsList . length - 3 } ` }
131
+ </ Paragraph >
132
+ </ Card >
133
+ </ XStack >
134
+ )
135
+ }
136
+
137
+ function OverlappingCoinIcons ( {
138
+ coins,
139
+ length = 3 ,
140
+ ...props
141
+ } : { coins : CoinWithBalance [ ] ; length ?: number } & XStackProps ) {
142
+ return (
143
+ < XStack ai = "center" { ...props } >
144
+ { coins . slice ( 0 , length ) . map ( ( { symbol } ) => (
145
+ < Card key = { symbol } circular mr = { '$-5' } bc = "transparent" ai = "center" jc = "center" >
146
+ < IconCoin size = { '$3' } symbol = { symbol } />
147
+ </ Card >
148
+ ) ) }
149
+ </ XStack >
150
+ )
151
+ }
152
+
98
153
function InvestmentsAggregate ( ) {
99
154
const tokenIds = useCoins ( )
100
155
. investmentCoins . filter ( ( c ) => c ?. balance && c . balance > 0n )
0 commit comments