Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
695a0322
Commit
695a0322
authored
Feb 19, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tokens page
parent
b9417e2e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
121 additions
and
107 deletions
+121
-107
tokens.tsx
pages/tokens.tsx
+2
-2
tokens.ts
types/api/tokens.ts
+1
-1
Tokens.tsx
ui/pages/Tokens.tsx
+8
-8
getSortParamsFromValue.ts
ui/shared/sort/getSortParamsFromValue.ts
+1
-1
Select.tsx
ui/showcases/Select.tsx
+2
-0
Tokens.tsx
ui/tokens/Tokens.tsx
+11
-10
TokensActionBar.tsx
ui/tokens/TokensActionBar.tsx
+17
-9
TokensBridgedChainsFilter.tsx
ui/tokens/TokensBridgedChainsFilter.tsx
+16
-10
TokensListItem.tsx
ui/tokens/TokensListItem.tsx
+15
-15
TokensTable.tsx
ui/tokens/TokensTable.tsx
+23
-23
TokensTableItem.tsx
ui/tokens/TokensTableItem.tsx
+24
-27
utils.ts
ui/tokens/utils.ts
+1
-1
No files found.
pages/tokens.tsx
View file @
695a0322
...
...
@@ -4,12 +4,12 @@ import React from 'react';
import
PageNextJs
from
'
nextjs/PageNextJs
'
;
//
const Tokens = dynamic(() => import('ui/pages/Tokens'), { ssr: false });
const
Tokens
=
dynamic
(()
=>
import
(
'
ui/pages/Tokens
'
),
{
ssr
:
false
});
const
Page
:
NextPage
=
()
=>
{
return
(
<
PageNextJs
pathname=
"/tokens"
>
{
/* <Tokens/> */
}
<
Tokens
/>
</
PageNextJs
>
);
};
...
...
types/api/tokens.ts
View file @
695a0322
...
...
@@ -34,4 +34,4 @@ export interface TokensSorting {
export
type
TokensSortingField
=
TokensSorting
[
'
sort
'
];
export
type
TokensSortingValue
=
`
${
TokensSortingField
}
-
${
TokensSorting
[
'
order
'
]
}
`
;
export
type
TokensSortingValue
=
`
${
TokensSortingField
}
-
${
TokensSorting
[
'
order
'
]
}
`
|
'
default
'
;
ui/pages/Tokens.tsx
View file @
695a0322
...
...
@@ -2,9 +2,9 @@ import { Box } from '@chakra-ui/react';
import
{
useRouter
}
from
'
next/router
'
;
import
React
from
'
react
'
;
import
type
{
TabItemRegular
}
from
'
toolkit/components/AdaptiveTabs/types
'
;
import
type
{
TokenType
}
from
'
types/api/token
'
;
import
type
{
TokensSortingValue
,
TokensSortingField
,
TokensSorting
}
from
'
types/api/tokens
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/Tabs/types
'
;
import
config
from
'
configs/app
'
;
import
useDebounce
from
'
lib/hooks/useDebounce
'
;
...
...
@@ -12,13 +12,13 @@ import useIsMobile from 'lib/hooks/useIsMobile';
import
getQueryParamString
from
'
lib/router/getQueryParamString
'
;
import
{
TOKEN_INFO_ERC_20
}
from
'
stubs/token
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
RoutedTabs
from
'
toolkit/components/RoutedTabs/RoutedTabs
'
;
import
PopoverFilter
from
'
ui/shared/filters/PopoverFilter
'
;
import
TokenTypeFilter
from
'
ui/shared/filters/TokenTypeFilter
'
;
import
PageTitle
from
'
ui/shared/Page/PageTitle
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
getSortParamsFromValue
from
'
ui/shared/sort/getSortParamsFromValue
'
;
import
getSortValueFromQuery
from
'
ui/shared/sort/getSortValueFromQuery
'
;
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
TokensList
from
'
ui/tokens/Tokens
'
;
import
TokensActionBar
from
'
ui/tokens/TokensActionBar
'
;
import
TokensBridgedChainsFilter
from
'
ui/tokens/TokensBridgedChainsFilter
'
;
...
...
@@ -48,7 +48,7 @@ const Tokens = () => {
const
q
=
getQueryParamString
(
router
.
query
.
q
);
const
[
searchTerm
,
setSearchTerm
]
=
React
.
useState
<
string
>
(
q
??
''
);
const
[
sort
,
setSort
]
=
React
.
useState
<
TokensSortingValue
|
undefined
>
(
getSortValueFromQuery
<
TokensSortingValue
>
(
router
.
query
,
SORT_OPTIONS
)
);
const
[
sort
,
setSort
]
=
React
.
useState
<
TokensSortingValue
>
(
getSortValueFromQuery
<
TokensSortingValue
>
(
router
.
query
,
SORT_OPTIONS
)
??
'
default
'
);
const
[
tokenTypes
,
setTokenTypes
]
=
React
.
useState
<
Array
<
TokenType
>
|
undefined
>
(
getTokenFilterValue
(
router
.
query
.
type
));
const
[
bridgeChains
,
setBridgeChains
]
=
React
.
useState
<
Array
<
string
>
|
undefined
>
(
getBridgedChainsFilterValue
(
router
.
query
.
chain_ids
));
...
...
@@ -91,14 +91,14 @@ const Tokens = () => {
setBridgeChains
(
value
);
},
[
debouncedSearchTerm
,
tokensQuery
]);
const
handleSortChange
=
React
.
useCallback
((
value
?
:
TokensSortingValue
)
=>
{
const
handleSortChange
=
React
.
useCallback
((
value
:
TokensSortingValue
)
=>
{
setSort
(
value
);
tokensQuery
.
onSortingChange
(
getSortParamsFromValue
(
value
));
},
[
tokensQuery
]);
const
handleTabChange
=
React
.
useCallback
(()
=>
{
setSearchTerm
(
''
);
setSort
(
undefined
);
setSort
(
'
default
'
);
setTokenTypes
(
undefined
);
setBridgeChains
(
undefined
);
},
[]);
...
...
@@ -144,7 +144,7 @@ const Tokens = () => {
);
}
)();
const tabs: Array
<
RoutedTab
>
= [
const tabs: Array
<
TabItemRegular
>
= [
{
id
:
'
all
'
,
title
:
'
All
'
,
...
...
@@ -185,11 +185,11 @@ const Tokens = () => {
{
!
hasMultipleTabs
&&
!
isMobile
&&
actionBar
}
<
RoutedTabs
tabs=
{
tabs
}
tabL
istProps=
{
isMobile
?
undefined
:
TAB_LIST_PROPS
}
l
istProps=
{
isMobile
?
undefined
:
TAB_LIST_PROPS
}
rightSlot=
{
hasMultipleTabs
&&
!
isMobile
?
actionBar
:
null
}
rightSlotProps=
{
!
isMobile
?
TABS_RIGHT_SLOT_PROPS
:
undefined
}
stickyEnabled=
{
!
isMobile
}
on
Tab
Change=
{
handleTabChange
}
on
Value
Change=
{
handleTabChange
}
/>
</>
);
...
...
ui/shared/sort/getSortParamsFromValue.ts
View file @
695a0322
export
default
function
getSortParamsFromValue
<
SortValue
extends
string
,
SortField
extends
string
,
SortOrder
extends
string
>
(
val
?:
SortValue
)
{
if
(
!
val
)
{
if
(
!
val
||
val
===
'
default
'
)
{
return
undefined
;
}
...
...
ui/showcases/Select.tsx
View file @
695a0322
...
...
@@ -22,6 +22,8 @@ const txSortingOptions = createListCollection({
items
:
SORT_OPTIONS
,
});
// TODO @tom2drum + tanya: select with search
const
SelectShowcase
=
()
=>
{
const
[
hasActiveFilter
,
setHasActiveFilter
]
=
React
.
useState
(
false
);
...
...
ui/tokens/Tokens.tsx
View file @
695a0322
import
{
Hide
,
Show
}
from
'
@chakra-ui/react
'
;
import
{
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokensSortingValue
}
from
'
types/api/tokens
'
;
...
...
@@ -13,8 +13,8 @@ import TokensTable from './TokensTable';
interface
Props
{
query
:
QueryWithPagesResult
<
'
tokens
'
>
|
QueryWithPagesResult
<
'
tokens_bridged
'
>
;
onSortChange
:
()
=>
void
;
sort
:
TokensSortingValue
|
undefined
;
onSortChange
:
(
value
:
TokensSortingValue
)
=>
void
;
sort
:
TokensSortingValue
;
actionBar
?:
React
.
ReactNode
;
hasActiveFilters
:
boolean
;
description
?:
React
.
ReactNode
;
...
...
@@ -31,7 +31,7 @@ const Tokens = ({ query, onSortChange, sort, actionBar, description, hasActiveFi
const
content
=
data
?.
items
?
(
<>
<
Show
below=
"lg"
ssr=
{
false
}
>
<
Box
hideFrom=
"lg"
>
{
description
}
{
data
.
items
.
map
((
item
,
index
)
=>
(
<
TokensListItem
...
...
@@ -42,8 +42,8 @@ const Tokens = ({ query, onSortChange, sort, actionBar, description, hasActiveFi
isLoading=
{
isPlaceholderData
}
/>
))
}
</
Show
>
<
Hide
below=
"lg"
ssr=
{
false
}
>
</
Box
>
<
Box
hideBelow=
"lg"
>
{
description
}
<
TokensTable
items=
{
data
.
items
}
...
...
@@ -53,22 +53,23 @@ const Tokens = ({ query, onSortChange, sort, actionBar, description, hasActiveFi
sorting=
{
sort
}
top=
{
tableTop
}
/>
</
Hide
>
</
Box
>
</>
)
:
null
;
return
(
<
DataListDisplay
isError=
{
isError
}
items
=
{
data
?.
items
}
items
Num=
{
data
?.
items
.
length
}
emptyText=
"There are no tokens."
filterProps=
{
{
emptyFilteredText
:
`Couldn${ apos }t find token that matches your filter query.`
,
hasActiveFilters
,
}
}
content=
{
content
}
actionBar=
{
query
.
pagination
.
isVisible
||
hasActiveFilters
?
actionBar
:
null
}
/>
>
{
content
}
</
DataListDisplay
>
);
};
...
...
ui/tokens/TokensActionBar.tsx
View file @
695a0322
import
{
HStack
}
from
'
@chakra-ui/react
'
;
import
{
createListCollection
,
HStack
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokensSortingValue
}
from
'
types/api/tokens
'
;
...
...
@@ -10,12 +10,16 @@ import Pagination from 'ui/shared/pagination/Pagination';
import
Sort
from
'
ui/shared/sort/Sort
'
;
import
{
SORT_OPTIONS
}
from
'
ui/tokens/utils
'
;
const
sortCollection
=
createListCollection
({
items
:
SORT_OPTIONS
,
});
interface
Props
{
pagination
:
PaginationParams
;
searchTerm
:
string
|
undefined
;
onSearchChange
:
(
value
:
string
)
=>
void
;
sort
:
TokensSortingValue
|
undefined
;
onSortChange
:
()
=>
void
;
sort
:
TokensSortingValue
;
onSortChange
:
(
value
:
TokensSortingValue
)
=>
void
;
filter
:
React
.
ReactNode
;
inTabsSlot
?:
boolean
;
}
...
...
@@ -30,10 +34,14 @@ const TokensActionBar = ({
inTabsSlot
,
}:
Props
)
=>
{
const
handleSortChange
=
React
.
useCallback
(({
value
}:
{
value
:
Array
<
string
>
})
=>
{
onSortChange
(
value
[
0
]
as
TokensSortingValue
);
},
[
onSortChange
]);
const
searchInput
=
(
<
FilterInput
w=
{
{
base
:
'
100%
'
,
lg
:
'
360px
'
}
}
size=
"
xs
"
size=
"
sm
"
onChange=
{
onSearchChange
}
placeholder=
"Token name or symbol"
initialValue=
{
searchTerm
}
...
...
@@ -42,13 +50,13 @@ const TokensActionBar = ({
return
(
<>
<
HStack
spacing
=
{
3
}
mb=
{
6
}
display=
{
{
base
:
'
flex
'
,
lg
:
'
none
'
}
}
>
<
HStack
gap
=
{
3
}
mb=
{
6
}
display=
{
{
base
:
'
flex
'
,
lg
:
'
none
'
}
}
>
{
filter
}
<
Sort
name=
"tokens_sorting"
defaultValue=
{
sort
}
options=
{
SORT_OPTIONS
}
on
Change=
{
on
SortChange
}
defaultValue=
{
[
sort
]
}
collection=
{
sortCollection
}
on
ValueChange=
{
handle
SortChange
}
/>
{
searchInput
}
</
HStack
>
...
...
@@ -58,7 +66,7 @@ const TokensActionBar = ({
justifyContent=
{
inTabsSlot
?
'
space-between
'
:
undefined
}
display=
{
{
base
:
pagination
.
isVisible
?
'
flex
'
:
'
none
'
,
lg
:
'
flex
'
}
}
>
<
HStack
spacing
=
{
3
}
display=
{
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
>
<
HStack
gap
=
{
3
}
display=
{
{
base
:
'
none
'
,
lg
:
'
flex
'
}
}
>
{
filter
}
{
searchInput
}
</
HStack
>
...
...
ui/tokens/TokensBridgedChainsFilter.tsx
View file @
695a0322
import
{
CheckboxGroup
,
Checkbox
,
Text
,
Flex
,
Link
,
useCheckboxGroup
,
chakra
}
from
'
@chakra-ui/react
'
;
import
{
CheckboxGroup
,
Text
,
Flex
,
useCheckboxGroup
,
chakra
,
Fieldset
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
config
from
'
configs/app
'
;
import
{
Checkbox
}
from
'
toolkit/chakra/checkbox
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
const
feature
=
config
.
features
.
bridgedTokens
;
...
...
@@ -33,7 +35,7 @@ const TokensBridgedChainsFilter = ({ onChange, defaultValue }: Props) => {
return
(
<>
<
Flex
justifyContent=
"space-between"
fontSize=
"sm"
>
<
Text
fontWeight=
{
600
}
variant=
"
secondary"
>
Show bridged tokens from
</
Text
>
<
Text
fontWeight=
{
600
}
color=
"text.
secondary"
>
Show bridged tokens from
</
Text
>
<
Link
onClick=
{
handleReset
}
color=
{
value
.
length
>
0
?
'
link
'
:
'
text_secondary
'
}
...
...
@@ -44,14 +46,18 @@ const TokensBridgedChainsFilter = ({ onChange, defaultValue }: Props) => {
Reset
</
Link
>
</
Flex
>
<
CheckboxGroup
size=
"lg"
onChange=
{
handleChange
}
value=
{
value
}
>
{
feature
.
chains
.
map
(({
title
,
id
,
short_title
:
shortTitle
})
=>
(
<
Checkbox
key=
{
id
}
value=
{
id
}
fontSize=
"md"
whiteSpace=
"pre-wrap"
>
<
span
>
{
title
}
</
span
>
<
chakra
.
span
color=
"text_secondary"
>
(
{
shortTitle
}
)
</
chakra
.
span
>
</
Checkbox
>
))
}
</
CheckboxGroup
>
<
Fieldset
.
Root
>
<
CheckboxGroup
defaultValue=
{
defaultValue
}
onValueChange=
{
handleChange
}
value=
{
value
}
name=
"bridged_token_chain"
>
<
Fieldset
.
Content
>
{
feature
.
chains
.
map
(({
title
,
id
,
short_title
:
shortTitle
})
=>
(
<
Checkbox
key=
{
id
}
value=
{
id
}
textStyle=
"md"
whiteSpace=
"pre-wrap"
>
<
span
>
{
title
}
</
span
>
<
chakra
.
span
color=
"text_secondary"
>
(
{
shortTitle
}
)
</
chakra
.
span
>
</
Checkbox
>
))
}
</
Fieldset
.
Content
>
</
CheckboxGroup
>
</
Fieldset
.
Root
>
</>
);
};
...
...
ui/tokens/TokensListItem.tsx
View file @
695a0322
...
...
@@ -7,9 +7,9 @@ import type { TokenInfo } from 'types/api/token';
import
config
from
'
configs/app
'
;
import
getItemIndex
from
'
lib/getItemIndex
'
;
import
{
getTokenTypeName
}
from
'
lib/token/tokenTypes
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/skeleton
'
;
import
{
Tag
}
from
'
toolkit/chakra/tag
'
;
import
AddressAddToWallet
from
'
ui/shared/address/AddressAddToWallet
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
TokenEntity
from
'
ui/shared/entities/token/TokenEntity
'
;
import
ListItemMobile
from
'
ui/shared/ListItemMobile/ListItemMobile
'
;
...
...
@@ -57,14 +57,14 @@ const TokensTableItem = ({
jointSymbol
noCopy
w=
"auto"
fontSiz
e=
"sm"
textStyl
e=
"sm"
fontWeight=
"700"
/>
<
Flex
ml=
{
3
}
flexShrink=
{
0
}
columnGap=
{
1
}
>
<
Tag
isL
oading=
{
isLoading
}
>
{
getTokenTypeName
(
type
)
}
</
Tag
>
{
bridgedChainTag
&&
<
Tag
isL
oading=
{
isLoading
}
>
{
bridgedChainTag
}
</
Tag
>
}
<
Tag
l
oading=
{
isLoading
}
>
{
getTokenTypeName
(
type
)
}
</
Tag
>
{
bridgedChainTag
&&
<
Tag
l
oading=
{
isLoading
}
>
{
bridgedChainTag
}
</
Tag
>
}
</
Flex
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
ml=
"auto"
color=
"text_secondary"
minW=
"24px"
textAlign=
"right"
lineHeight=
{
6
}
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm"
ml=
"auto"
color=
"text.secondary"
minW=
"24px"
textAlign=
"right"
>
<
span
>
{
getItemIndex
(
index
,
page
)
}
</
span
>
</
Skeleton
>
</
GridItem
>
...
...
@@ -79,22 +79,22 @@ const TokensTableItem = ({
<
AddressAddToWallet
token=
{
token
}
isLoading=
{
isLoading
}
/>
</
Flex
>
{
exchangeRate
&&
(
<
HStack
spacing
=
{
3
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSiz
e=
"sm"
fontWeight=
{
500
}
>
Price
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
color=
"text_
secondary"
>
<
HStack
gap
=
{
3
}
>
<
Skeleton
loading=
{
isLoading
}
textStyl
e=
"sm"
fontWeight=
{
500
}
>
Price
</
Skeleton
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm"
color=
"text.
secondary"
>
<
span
>
$
{
Number
(
exchangeRate
).
toLocaleString
(
undefined
,
{
minimumSignificantDigits
:
4
})
}
</
span
>
</
Skeleton
>
</
HStack
>
)
}
{
marketCap
&&
(
<
HStack
spacing
=
{
3
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSiz
e=
"sm"
fontWeight=
{
500
}
>
On-chain market cap
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
color=
"text_
secondary"
><
span
>
{
BigNumber
(
marketCap
).
toFormat
()
}
</
span
></
Skeleton
>
<
HStack
gap
=
{
3
}
>
<
Skeleton
loading=
{
isLoading
}
textStyl
e=
"sm"
fontWeight=
{
500
}
>
On-chain market cap
</
Skeleton
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm"
color=
"text.
secondary"
><
span
>
{
BigNumber
(
marketCap
).
toFormat
()
}
</
span
></
Skeleton
>
</
HStack
>
)
}
<
HStack
spacing
=
{
3
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSiz
e=
"sm"
fontWeight=
{
500
}
>
Holders
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
color=
"text_
secondary"
><
span
>
{
Number
(
holders
).
toLocaleString
()
}
</
span
></
Skeleton
>
<
HStack
gap
=
{
3
}
>
<
Skeleton
loading=
{
isLoading
}
textStyl
e=
"sm"
fontWeight=
{
500
}
>
Holders
</
Skeleton
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm"
color=
"text.
secondary"
><
span
>
{
Number
(
holders
).
toLocaleString
()
}
</
span
></
Skeleton
>
</
HStack
>
</
ListItemMobile
>
);
...
...
ui/tokens/TokensTable.tsx
View file @
695a0322
import
{
Link
,
Table
,
Tbody
,
Th
,
Tr
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokenInfo
}
from
'
types/api/token
'
;
import
type
{
TokensSortingField
,
TokensSortingValue
}
from
'
types/api/tokens
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
TableBody
,
TableColumnHeader
,
TableHeaderSticky
,
TableRoot
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
ACTION_BAR_HEIGHT_DESKTOP
}
from
'
ui/shared/ActionBar
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
{
default
as
getNextSortValueShared
}
from
'
ui/shared/sort/getNextSortValue
'
;
import
{
default
as
Thead
}
from
'
ui/shared/TheadSticky
'
;
import
TokensTableItem
from
'
./TokensTableItem
'
;
const
SORT_SEQUENCE
:
Record
<
TokensSortingField
,
Array
<
TokensSortingValue
|
undefined
>>
=
{
fiat_value
:
[
'
fiat_value-desc
'
,
'
fiat_value-asc
'
,
undefined
],
holder_count
:
[
'
holder_count-desc
'
,
'
holder_count-asc
'
,
undefined
],
circulating_market_cap
:
[
'
circulating_market_cap-desc
'
,
'
circulating_market_cap-asc
'
,
undefined
],
const
SORT_SEQUENCE
:
Record
<
TokensSortingField
,
Array
<
TokensSortingValue
>>
=
{
fiat_value
:
[
'
fiat_value-desc
'
,
'
fiat_value-asc
'
,
'
default
'
],
holder_count
:
[
'
holder_count-desc
'
,
'
holder_count-asc
'
,
'
default
'
],
circulating_market_cap
:
[
'
circulating_market_cap-desc
'
,
'
circulating_market_cap-asc
'
,
'
default
'
],
};
const
getNextSortValue
=
(
getNextSortValueShared
<
TokensSortingField
,
TokensSortingValue
>
).
bind
(
undefined
,
SORT_SEQUENCE
);
...
...
@@ -22,8 +22,8 @@ const getNextSortValue = (getNextSortValueShared<TokensSortingField, TokensSorti
type
Props
=
{
items
:
Array
<
TokenInfo
>
;
page
:
number
;
sorting
?
:
TokensSortingValue
;
setSorting
:
(
val
?
:
TokensSortingValue
)
=>
void
;
sorting
:
TokensSortingValue
;
setSorting
:
(
val
ue
:
TokensSortingValue
)
=>
void
;
isLoading
?:
boolean
;
top
?:
number
;
};
...
...
@@ -37,36 +37,36 @@ const TokensTable = ({ items, page, isLoading, sorting, setSorting, top }: Props
},
[
sorting
,
setSorting
]);
return
(
<
Table
>
<
T
head
top=
{
top
??
ACTION_BAR_HEIGHT_DESKTOP
}
>
<
T
r
>
<
T
h
w=
"50%"
>
Token
</
Th
>
<
T
h
isNumeric
w=
"15%"
>
<
Table
Root
>
<
T
ableHeaderSticky
top=
{
top
??
ACTION_BAR_HEIGHT_DESKTOP
}
>
<
T
ableRow
>
<
T
ableColumnHeader
w=
"50%"
>
Token
</
TableColumnHeader
>
<
T
ableColumnHeader
isNumeric
w=
"15%"
>
<
Link
onClick=
{
sort
(
'
fiat_value
'
)
}
display=
"flex"
justifyContent=
"end"
>
{
sorting
?.
includes
(
'
fiat_value
'
)
&&
<
IconSvg
name=
"arrows/east-mini"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Price
</
Link
>
</
T
h
>
<
T
h
isNumeric
w=
"20%"
>
</
T
ableColumnHeader
>
<
T
ableColumnHeader
isNumeric
w=
"20%"
>
<
Link
onClick=
{
sort
(
'
circulating_market_cap
'
)
}
display=
"flex"
justifyContent=
"end"
>
{
sorting
?.
includes
(
'
circulating_market_cap
'
)
&&
<
IconSvg
name=
"arrows/east-mini"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
On-chain market cap
</
Link
>
</
T
h
>
<
T
h
isNumeric
w=
"15%"
>
</
T
ableColumnHeader
>
<
T
ableColumnHeader
isNumeric
w=
"15%"
>
<
Link
onClick=
{
sort
(
'
holder_count
'
)
}
display=
"flex"
justifyContent=
"end"
>
{
sorting
?.
includes
(
'
holder_count
'
)
&&
<
IconSvg
name=
"arrows/east-mini"
boxSize=
{
4
}
transform=
{
sortIconTransform
}
/>
}
Holders
</
Link
>
</
T
h
>
</
T
r
>
</
T
head
>
<
T
b
ody
>
</
T
ableColumnHeader
>
</
T
ableRow
>
</
T
ableHeaderSticky
>
<
T
ableB
ody
>
{
items
.
map
((
item
,
index
)
=>
(
<
TokensTableItem
key=
{
item
.
address
+
(
isLoading
?
index
:
''
)
}
token=
{
item
}
index=
{
index
}
page=
{
page
}
isLoading=
{
isLoading
}
/>
))
}
</
T
b
ody
>
</
Table
>
</
T
ableB
ody
>
</
Table
Root
>
);
};
...
...
ui/tokens/TokensTableItem.tsx
View file @
695a0322
import
{
Flex
,
Td
,
Tr
}
from
'
@chakra-ui/react
'
;
import
{
Flex
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
...
...
@@ -7,9 +7,10 @@ import type { TokenInfo } from 'types/api/token';
import
config
from
'
configs/app
'
;
import
getItemIndex
from
'
lib/getItemIndex
'
;
import
{
getTokenTypeName
}
from
'
lib/token/tokenTypes
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/skeleton
'
;
import
{
TableCell
,
TableRow
}
from
'
toolkit/chakra/table
'
;
import
{
Tag
}
from
'
toolkit/chakra/tag
'
;
import
AddressAddToWallet
from
'
ui/shared/address/AddressAddToWallet
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
import
type
{
EntityProps
as
AddressEntityProps
}
from
'
ui/shared/entities/address/AddressEntity
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
TokenEntity
from
'
ui/shared/entities/token/TokenEntity
'
;
...
...
@@ -57,15 +58,12 @@ const TokensTableItem = ({
};
return
(
<
Tr
role=
"group"
>
<
Td
>
<
TableRow
className=
"group"
>
<
TableCell
>
<
Flex
alignItems=
"flex-start"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
lineHeight=
"20px"
loading=
{
isLoading
}
textStyle=
"sm"
fontWeight=
{
600
}
mr=
{
3
}
minW=
"28px"
...
...
@@ -78,7 +76,7 @@ const TokensTableItem = ({
isLoading=
{
isLoading
}
jointSymbol
noCopy
fontSiz
e=
"sm"
textStyl
e=
"sm"
fontWeight=
"700"
/>
<
Flex
columnGap=
{
2
}
py=
"5px"
alignItems=
"center"
>
...
...
@@ -86,7 +84,7 @@ const TokensTableItem = ({
address=
{
tokenAddress
}
isLoading=
{
isLoading
}
noIcon
fontSiz
e=
"sm"
textStyl
e=
"sm"
fontWeight=
{
500
}
/>
<
AddressAddToWallet
...
...
@@ -98,34 +96,33 @@ const TokensTableItem = ({
/>
</
Flex
>
<
Flex
columnGap=
{
1
}
>
<
Tag
isL
oading=
{
isLoading
}
>
{
getTokenTypeName
(
type
)
}
</
Tag
>
{
bridgedChainTag
&&
<
Tag
isL
oading=
{
isLoading
}
>
{
bridgedChainTag
}
</
Tag
>
}
<
Tag
l
oading=
{
isLoading
}
>
{
getTokenTypeName
(
type
)
}
</
Tag
>
{
bridgedChainTag
&&
<
Tag
l
oading=
{
isLoading
}
>
{
bridgedChainTag
}
</
Tag
>
}
</
Flex
>
</
Flex
>
</
Flex
>
</
T
d
>
<
T
d
isNumeric
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
lineHeight=
"24px
"
fontWeight=
{
500
}
display=
"inline-block"
>
</
T
ableCell
>
<
T
ableCell
isNumeric
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm
"
fontWeight=
{
500
}
display=
"inline-block"
>
{
exchangeRate
&&
`$${ Number(exchangeRate).toLocaleString(undefined, { minimumSignificantDigits: 4 }) }`
}
</
Skeleton
>
</
T
d
>
<
T
d
isNumeric
maxWidth=
"300px"
width=
"300px"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
lineHeight=
"24px
"
fontWeight=
{
500
}
display=
"inline-block"
>
</
T
ableCell
>
<
T
ableCell
isNumeric
maxWidth=
"300px"
width=
"300px"
>
<
Skeleton
loading=
{
isLoading
}
textStyle=
"sm
"
fontWeight=
{
500
}
display=
"inline-block"
>
{
marketCap
&&
`$${ BigNumber(marketCap).toFormat() }`
}
</
Skeleton
>
</
T
d
>
<
T
d
isNumeric
>
</
T
ableCell
>
<
T
ableCell
isNumeric
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
lineHeight=
"24px"
loading=
{
isLoading
}
textStyle=
"sm"
fontWeight=
{
500
}
display=
"inline-block"
>
{
Number
(
holders
).
toLocaleString
()
}
</
Skeleton
>
</
T
d
>
</
T
r
>
</
T
ableCell
>
</
T
ableRow
>
);
};
...
...
ui/tokens/utils.ts
View file @
695a0322
...
...
@@ -7,7 +7,7 @@ import { TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
import
type
{
SelectOption
}
from
'
toolkit/chakra/select
'
;
export
const
SORT_OPTIONS
:
Array
<
SelectOption
<
TokensSortingValue
>>
=
[
{
label
:
'
Default
'
,
value
:
undefined
},
{
label
:
'
Default
'
,
value
:
'
default
'
},
{
label
:
'
Price ascending
'
,
value
:
'
fiat_value-asc
'
},
{
label
:
'
Price descending
'
,
value
:
'
fiat_value-desc
'
},
{
label
:
'
Holders ascending
'
,
value
:
'
holder_count-asc
'
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment