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
18845138
Commit
18845138
authored
Jun 01, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
skeletons for homepage
parent
825aac59
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
194 additions
and
332 deletions
+194
-332
LatestBlocks.tsx
ui/home/LatestBlocks.tsx
+23
-26
LatestBlocksItem.tsx
ui/home/LatestBlocksItem.tsx
+16
-13
LatestBlocksItemSkeleton.tsx
ui/home/LatestBlocksItemSkeleton.tsx
+0
-45
LatestDeposits.tsx
ui/home/LatestDeposits.tsx
+15
-14
LatestDepositsItem.tsx
ui/home/LatestDepositsItem.tsx
+39
-15
LatestDepositsItemSkeleton.tsx
ui/home/LatestDepositsItemSkeleton.tsx
+0
-47
LatestTxs.tsx
ui/home/LatestTxs.tsx
+15
-14
LatestTxsItem.tsx
ui/home/LatestTxsItem.tsx
+44
-24
LatestTxsItemSkeleton.tsx
ui/home/LatestTxsItemSkeleton.tsx
+0
-82
LatestWatchlistTxs.tsx
ui/home/LatestWatchlistTxs.tsx
+14
-8
Stats.tsx
ui/home/Stats.tsx
+12
-6
StatsItem.tsx
ui/home/StatsItem.tsx
+16
-8
StatsItemSkeleton.tsx
ui/home/StatsItemSkeleton.tsx
+0
-30
No files found.
ui/home/LatestBlocks.tsx
View file @
18845138
...
...
@@ -13,10 +13,11 @@ import useIsMobile from 'lib/hooks/useIsMobile';
import
{
nbsp
}
from
'
lib/html-entities
'
;
import
useSocketChannel
from
'
lib/socket/useSocketChannel
'
;
import
useSocketMessage
from
'
lib/socket/useSocketMessage
'
;
import
{
BLOCK
}
from
'
stubs/block
'
;
import
{
HOMEPAGE_STATS
}
from
'
stubs/stats
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
import
LatestBlocksItem
from
'
./LatestBlocksItem
'
;
import
LatestBlocksItemSkeleton
from
'
./LatestBlocksItemSkeleton
'
;
const
BLOCK_HEIGHT_L1
=
166
;
const
BLOCK_HEIGHT_L2
=
112
;
...
...
@@ -32,10 +33,18 @@ const LatestBlocks = () => {
}
else
{
blocksMaxCount
=
isMobile
?
2
:
3
;
}
const
{
data
,
isLoading
,
isError
}
=
useApiQuery
(
'
homepage_blocks
'
);
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_blocks
'
,
{
queryOptions
:
{
placeholderData
:
Array
(
4
).
fill
(
BLOCK
),
},
});
const
queryClient
=
useQueryClient
();
const
statsQueryResult
=
useApiQuery
(
'
homepage_stats
'
);
const
statsQueryResult
=
useApiQuery
(
'
homepage_stats
'
,
{
queryOptions
:
{
placeholderData
:
HOMEPAGE_STATS
,
},
});
const
handleNewBlockMessage
:
SocketMessage
.
NewBlock
[
'
handler
'
]
=
React
.
useCallback
((
payload
)
=>
{
queryClient
.
setQueryData
(
getResourceKey
(
'
homepage_blocks
'
),
(
prevData
:
Array
<
Block
>
|
undefined
)
=>
{
...
...
@@ -52,7 +61,7 @@ const LatestBlocks = () => {
const
channel
=
useSocketChannel
({
topic
:
'
blocks:new_block
'
,
isDisabled
:
is
Loading
||
isError
,
isDisabled
:
is
PlaceholderData
||
isError
,
});
useSocketMessage
({
channel
,
...
...
@@ -62,22 +71,6 @@ const LatestBlocks = () => {
let
content
;
if
(
isLoading
)
{
content
=
(
<>
<
Skeleton
w=
"100%"
h=
{
6
}
mb=
{
9
}
/>
<
VStack
spacing=
{
`${ BLOCK_MARGIN }px`
}
mb=
{
6
}
height=
{
`${ blockHeight * blocksMaxCount + BLOCK_MARGIN * (blocksMaxCount - 1) }px`
}
overflow=
"hidden"
>
{
Array
.
from
(
Array
(
blocksMaxCount
)).
map
((
item
,
index
)
=>
<
LatestBlocksItemSkeleton
key=
{
index
}
/>)
}
</
VStack
>
</>
);
}
if
(
isError
)
{
content
=
<
Text
>
No data. Please reload page.
</
Text
>;
}
...
...
@@ -88,22 +81,26 @@ const LatestBlocks = () => {
content
=
(
<>
{
statsQueryResult
.
isLoading
&&
(
<
Skeleton
h=
"24px"
w=
"170px"
mb=
{
{
base
:
6
,
lg
:
9
}
}
/>
)
}
{
statsQueryResult
.
data
?.
network_utilization_percentage
!==
undefined
&&
(
<
Box
mb=
{
{
base
:
6
,
lg
:
3
}
}
>
<
Skeleton
isLoaded=
{
!
statsQueryResult
.
isPlaceholderData
}
mb=
{
{
base
:
6
,
lg
:
3
}
}
display=
"inline-block"
>
<
Text
as=
"span"
fontSize=
"sm"
>
Network utilization:
{
nbsp
}
</
Text
>
<
Text
as=
"span"
fontSize=
"sm"
color=
"blue.400"
fontWeight=
{
700
}
>
{
statsQueryResult
.
data
?.
network_utilization_percentage
.
toFixed
(
2
)
}
%
</
Text
>
</
Box
>
</
Skeleton
>
)
}
<
VStack
spacing=
{
`${ BLOCK_MARGIN }px`
}
mb=
{
4
}
height=
{
`${ blockHeight * blocksCount + BLOCK_MARGIN * (blocksCount - 1) }px`
}
overflow=
"hidden"
>
<
AnimatePresence
initial=
{
false
}
>
{
dataToShow
.
map
((
block
=>
<
LatestBlocksItem
key=
{
block
.
height
}
block=
{
block
}
h=
{
blockHeight
}
/>))
}
{
dataToShow
.
map
(((
block
,
index
)
=>
(
<
LatestBlocksItem
key=
{
block
.
height
+
(
isPlaceholderData
?
String
(
index
)
:
''
)
}
block=
{
block
}
h=
{
blockHeight
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
AnimatePresence
>
</
VStack
>
<
Flex
justifyContent=
"center"
>
...
...
ui/home/LatestBlocksItem.tsx
View file @
18845138
...
...
@@ -2,10 +2,8 @@ import {
Box
,
Flex
,
Grid
,
GridItem
,
HStack
,
Icon
,
Text
,
Skeleton
,
}
from
'
@chakra-ui/react
'
;
import
{
motion
}
from
'
framer-motion
'
;
import
{
route
}
from
'
nextjs-routes
'
;
...
...
@@ -18,14 +16,16 @@ import blockIcon from 'icons/block.svg';
import
getBlockTotalReward
from
'
lib/block/getBlockTotalReward
'
;
import
BlockTimestamp
from
'
ui/blocks/BlockTimestamp
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
import
Icon
from
'
ui/shared/chakra/Icon
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
type
Props
=
{
block
:
Block
;
h
:
number
;
isLoading
?:
boolean
;
}
const
LatestBlocksItem
=
({
block
,
h
}:
Props
)
=>
{
const
LatestBlocksItem
=
({
block
,
h
,
isLoading
}:
Props
)
=>
{
const
totalReward
=
getBlockTotalReward
(
block
);
return
(
<
Box
...
...
@@ -43,26 +43,29 @@ const LatestBlocksItem = ({ block, h }: Props) => {
>
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
mb=
{
3
}
>
<
HStack
spacing=
{
2
}
>
<
Icon
as=
{
blockIcon
}
boxSize=
"30px"
color=
"link"
/>
<
Icon
as=
{
blockIcon
}
boxSize=
"30px"
color=
"link"
isLoading=
{
isLoading
}
borderRadius=
"base"
/>
<
LinkInternal
href=
{
route
({
pathname
:
'
/block/[height_or_hash]
'
,
query
:
{
height_or_hash
:
String
(
block
.
height
)
}
})
}
fontSize=
"xl"
fontWeight=
"500"
isLoading=
{
isLoading
}
>
{
block
.
height
}
<
Skeleton
isLoaded=
{
!
isLoading
}
>
{
block
.
height
}
</
Skeleton
>
</
LinkInternal
>
</
HStack
>
<
BlockTimestamp
ts=
{
block
.
timestamp
}
isEnabled
fontSize=
"sm"
/>
<
BlockTimestamp
ts=
{
block
.
timestamp
}
isEnabled
=
{
!
isLoading
}
isLoading=
{
isLoading
}
fontSize=
"sm"
/>
</
Flex
>
<
Grid
gridGap=
{
2
}
templateColumns=
"auto minmax(0, 1fr)"
fontSize=
"sm"
>
<
GridItem
>
Txn
</
GridItem
>
<
GridItem
><
Text
variant=
"secondary"
>
{
block
.
tx_count
}
</
Text
></
GridItem
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
Txn
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
><
span
>
{
block
.
tx_count
}
</
span
></
Skeleton
>
{
!
appConfig
.
L2
.
isL2Network
&&
(
<>
<
GridItem
>
Reward
</
GridItem
>
<
GridItem
><
Text
variant=
"secondary"
>
{
totalReward
.
toFixed
()
}
</
Text
></
GridItem
>
<
GridItem
>
Miner
</
GridItem
>
<
GridItem
><
AddressLink
type=
"address"
alias=
{
block
.
miner
.
name
}
hash=
{
block
.
miner
.
hash
}
truncation=
"constant"
maxW=
"100%"
/></
GridItem
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
Reward
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
><
span
>
{
totalReward
.
toFixed
()
}
</
span
></
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
Miner
</
Skeleton
>
<
AddressLink
type=
"address"
alias=
{
block
.
miner
.
name
}
hash=
{
block
.
miner
.
hash
}
truncation=
"constant"
maxW=
"100%"
isLoading=
{
isLoading
}
/
>
</>
)
}
</
Grid
>
...
...
ui/home/LatestBlocksItemSkeleton.tsx
deleted
100644 → 0
View file @
825aac59
import
{
Box
,
Flex
,
Grid
,
GridItem
,
HStack
,
Skeleton
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
appConfig
from
'
configs/app/config
'
;
const
LatestBlocksItemSkeleton
=
()
=>
{
return
(
<
Box
minWidth=
{
{
base
:
'
100%
'
,
lg
:
'
280px
'
}
}
borderRadius=
"12px"
border=
"1px solid"
borderColor=
"divider"
p=
{
6
}
>
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
mb=
{
3
}
>
<
HStack
spacing=
{
2
}
>
<
Skeleton
w=
"30px"
h=
"30px"
/>
<
Skeleton
w=
"93px"
h=
"15px"
/>
</
HStack
>
<
Skeleton
w=
"44px"
h=
"15px"
/>
</
Flex
>
<
Grid
gridGap=
{
2
}
templateColumns=
"auto minmax(0, 1fr)"
fontSize=
"sm"
>
<
GridItem
><
Skeleton
w=
"30px"
h=
"15px"
/></
GridItem
>
<
GridItem
><
Skeleton
w=
"93px"
h=
"15px"
/></
GridItem
>
{
!
appConfig
.
L2
.
isL2Network
&&
(
<>
<
GridItem
><
Skeleton
w=
"30px"
h=
"15px"
/></
GridItem
>
<
GridItem
><
Skeleton
w=
"93px"
h=
"15px"
/></
GridItem
>
<
GridItem
><
Skeleton
w=
"30px"
h=
"15px"
/></
GridItem
>
<
GridItem
><
Skeleton
w=
"93px"
h=
"15px"
/></
GridItem
>
</>
)
}
</
Grid
>
</
Box
>
);
};
export
default
LatestBlocksItemSkeleton
;
ui/home/LatestDeposits.tsx
View file @
18845138
import
{
Box
,
Flex
,
Text
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Flex
,
Text
}
from
'
@chakra-ui/react
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
React
from
'
react
'
;
...
...
@@ -9,16 +9,20 @@ import useGradualIncrement from 'lib/hooks/useGradualIncrement';
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useSocketChannel
from
'
lib/socket/useSocketChannel
'
;
import
useSocketMessage
from
'
lib/socket/useSocketMessage
'
;
import
{
L2_DEPOSIT_ITEM
}
from
'
stubs/L2
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
import
SocketNewItemsNotice
from
'
ui/shared/SocketNewItemsNotice
'
;
import
LatestDepositsItem
from
'
./LatestDepositsItem
'
;
import
LatestDepositsItemSkeleton
from
'
./LatestDepositsItemSkeleton
'
;
const
LatestDeposits
=
()
=>
{
const
isMobile
=
useIsMobile
();
const
itemsCount
=
isMobile
?
2
:
6
;
const
{
data
,
isLoading
,
isError
}
=
useApiQuery
(
'
homepage_deposits
'
);
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_deposits
'
,
{
queryOptions
:
{
placeholderData
:
Array
(
itemsCount
).
fill
(
L2_DEPOSIT_ITEM
),
},
});
const
[
num
,
setNum
]
=
useGradualIncrement
(
0
);
const
[
socketAlert
,
setSocketAlert
]
=
React
.
useState
(
''
);
...
...
@@ -48,15 +52,6 @@ const LatestDeposits = () => {
handler
:
handleNewDepositMessage
,
});
if
(
isLoading
)
{
return
(
<>
<
Skeleton
h=
"32px"
w=
"100%"
borderBottomLeftRadius=
{
0
}
borderBottomRightRadius=
{
0
}
/>
{
Array
.
from
(
Array
(
itemsCount
)).
map
((
item
,
index
)
=>
<
LatestDepositsItemSkeleton
key=
{
index
}
/>)
}
</>
);
}
if
(
isError
)
{
return
<
Text
mt=
{
4
}
>
No data. Please reload page.
</
Text
>;
}
...
...
@@ -65,9 +60,15 @@ const LatestDeposits = () => {
const
depositsUrl
=
route
({
pathname
:
'
/l2-deposits
'
});
return
(
<>
<
SocketNewItemsNotice
borderBottomRadius=
{
0
}
url=
{
depositsUrl
}
num=
{
num
}
alert=
{
socketAlert
}
type=
"deposit"
/>
<
SocketNewItemsNotice
borderBottomRadius=
{
0
}
url=
{
depositsUrl
}
num=
{
num
}
alert=
{
socketAlert
}
type=
"deposit"
isLoading=
{
isPlaceholderData
}
/>
<
Box
mb=
{
{
base
:
3
,
lg
:
4
}
}
>
{
data
.
slice
(
0
,
itemsCount
).
map
((
item
=>
<
LatestDepositsItem
key=
{
item
.
l2_tx_hash
}
item=
{
item
}
/>))
}
{
data
.
slice
(
0
,
itemsCount
).
map
(((
item
,
index
)
=>
(
<
LatestDepositsItem
key=
{
item
.
l2_tx_hash
+
(
isPlaceholderData
?
index
:
''
)
}
item=
{
item
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
Box
>
<
Flex
justifyContent=
"center"
>
<
LinkInternal
fontSize=
"sm"
href=
{
depositsUrl
}
>
View all deposits
</
LinkInternal
>
...
...
ui/home/LatestDepositsItem.tsx
View file @
18845138
...
...
@@ -2,8 +2,7 @@ import {
Box
,
Flex
,
Grid
,
Icon
,
Text
,
Skeleton
,
}
from
'
@chakra-ui/react
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
React
from
'
react
'
;
...
...
@@ -15,15 +14,17 @@ import blockIcon from 'icons/block.svg';
import
txIcon
from
'
icons/transactions.svg
'
;
import
dayjs
from
'
lib/date/dayjs
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
Icon
from
'
ui/shared/chakra/Icon
'
;
import
HashStringShortenDynamic
from
'
ui/shared/HashStringShortenDynamic
'
;
import
LinkExternal
from
'
ui/shared/LinkExternal
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
type
Props
=
{
item
:
L2DepositsItem
;
isLoading
?:
boolean
;
}
const
LatestTxsItem
=
({
item
}:
Props
)
=>
{
const
LatestTxsItem
=
({
item
,
isLoading
}:
Props
)
=>
{
const
timeAgo
=
dayjs
(
item
.
l1_block_timestamp
).
fromNow
();
const
isMobile
=
useIsMobile
();
...
...
@@ -35,9 +36,10 @@ const LatestTxsItem = ({ item }: Props) => {
fontWeight=
{
700
}
display=
"inline-flex"
mr=
{
2
}
isLoading=
{
isLoading
}
>
<
Icon
as=
{
blockIcon
}
boxSize=
"30px"
mr=
{
1
}
/>
{
item
.
l1_block_number
}
<
Icon
as=
{
blockIcon
}
boxSize=
"30px"
isLoading=
{
isLoading
}
borderRadius=
"base"
/>
<
Skeleton
isLoaded=
{
!
isLoading
}
ml=
{
1
}
>
{
item
.
l1_block_number
}
</
Skeleton
>
</
LinkExternal
>
);
...
...
@@ -48,9 +50,13 @@ const LatestTxsItem = ({ item }: Props) => {
display=
"inline-flex"
alignItems=
"center"
overflow=
"hidden"
isLoading=
{
isLoading
}
my=
"3px"
>
<
Icon
as=
{
txIcon
}
boxSize=
{
6
}
mr=
{
1
}
/>
<
Box
overflow=
"hidden"
whiteSpace=
"nowrap"
><
HashStringShortenDynamic
hash=
{
item
.
l1_tx_hash
}
/></
Box
>
<
Icon
as=
{
txIcon
}
boxSize=
{
6
}
isLoading=
{
isLoading
}
/>
<
Skeleton
isLoaded=
{
!
isLoading
}
overflow=
"hidden"
whiteSpace=
"nowrap"
ml=
{
1
}
>
<
HashStringShortenDynamic
hash=
{
item
.
l1_tx_hash
}
/>
</
Skeleton
>
</
LinkExternal
>
);
...
...
@@ -61,9 +67,12 @@ const LatestTxsItem = ({ item }: Props) => {
alignItems=
"center"
overflow=
"hidden"
w=
"100%"
isLoading=
{
isLoading
}
>
<
Icon
as=
{
txIcon
}
boxSize=
{
6
}
mr=
{
1
}
/>
<
Box
w=
"calc(100% - 36px)"
overflow=
"hidden"
whiteSpace=
"nowrap"
><
HashStringShortenDynamic
hash=
{
item
.
l2_tx_hash
}
/></
Box
>
<
Icon
as=
{
txIcon
}
boxSize=
{
6
}
isLoading=
{
isLoading
}
/>
<
Skeleton
isLoaded=
{
!
isLoading
}
w=
"calc(100% - 36px)"
overflow=
"hidden"
whiteSpace=
"nowrap"
ml=
{
1
}
>
<
HashStringShortenDynamic
hash=
{
item
.
l2_tx_hash
}
/>
</
Skeleton
>
</
LinkInternal
>
);
...
...
@@ -73,28 +82,42 @@ const LatestTxsItem = ({ item }: Props) => {
<>
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
mb=
{
1
}
>
{
l1BlockLink
}
<
Text
variant=
"secondary"
>
{
timeAgo
}
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
</
Flex
>
<
Grid
gridTemplateColumns=
"56px auto"
>
<
Text
lineHeight=
"30px"
>
L1 txn
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
my=
"5px"
w=
"fit-content"
>
L1 txn
</
Skeleton
>
{
l1TxLink
}
<
Text
lineHeight=
"30px"
>
L2 txn
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
my=
"3px"
w=
"fit-content"
>
L2 txn
</
Skeleton
>
{
l2TxLink
}
</
Grid
>
</>
);
}
return
(
<
Grid
width=
"100%"
columnGap=
{
4
}
rowGap=
{
2
}
templateColumns=
"max-content max-content auto"
w=
"100%"
>
{
l1BlockLink
}
<
Text
lineHeight=
"30px"
>
L1 txn
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
w=
"fit-content"
h=
"fit-content"
my=
"5px"
>
L1 txn
</
Skeleton
>
{
l1TxLink
}
<
Text
variant=
"secondary"
>
{
timeAgo
}
</
Text
>
<
Text
lineHeight=
"30px"
>
L2 txn
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
w=
"fit-content"
h=
"fit-content"
my=
"2px"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
w=
"fit-content"
h=
"fit-content"
my=
"2px"
>
L2 txn
</
Skeleton
>
{
l2TxLink
}
</
Grid
>
);
})();
return
(
<
Box
width=
"100%"
...
...
@@ -104,6 +127,7 @@ const LatestTxsItem = ({ item }: Props) => {
px=
{
{
base
:
0
,
lg
:
4
}
}
_last=
{
{
borderBottom
:
'
1px solid
'
,
borderColor
:
'
divider
'
}
}
fontSize=
"sm"
lineHeight=
{
5
}
>
{
content
}
</
Box
>
...
...
ui/home/LatestDepositsItemSkeleton.tsx
deleted
100644 → 0
View file @
825aac59
import
{
Box
,
Flex
,
Skeleton
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
const
LatestTxsItemSkeleton
=
()
=>
{
const
isMobile
=
useIsMobile
();
return
(
<
Box
width=
"100%"
borderTop=
"1px solid"
borderColor=
"divider"
py=
{
4
}
px=
{
{
base
:
0
,
lg
:
4
}
}
_last=
{
{
borderBottom
:
'
1px solid
'
,
borderColor
:
'
divider
'
}
}
>
{
isMobile
&&
(
<>
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
mt=
{
1
}
mb=
{
4
}
>
<
Skeleton
w=
"120px"
h=
"20px"
></
Skeleton
>
<
Skeleton
w=
"80px"
h=
"20px"
></
Skeleton
>
</
Flex
>
<
Skeleton
w=
"100%"
h=
"20px"
mb=
{
2
}
></
Skeleton
>
<
Skeleton
w=
"100%"
h=
"20px"
mb=
{
2
}
></
Skeleton
>
</>
)
}
{
!
isMobile
&&
(
<>
<
Flex
w=
"100%"
mb=
{
2
}
h=
"30px"
alignItems=
"center"
justifyContent=
"space-between"
>
<
Skeleton
w=
"120px"
h=
"20px"
></
Skeleton
>
<
Skeleton
w=
"calc(100% - 120px - 48px)"
h=
"20px"
></
Skeleton
>
</
Flex
><
Flex
w=
"100%"
h=
"30px"
alignItems=
"center"
justifyContent=
"space-between"
>
<
Skeleton
w=
"120px"
h=
"20px"
></
Skeleton
>
<
Skeleton
w=
"calc(100% - 120px - 48px)"
h=
"20px"
></
Skeleton
>
</
Flex
>
</>
)
}
</
Box
>
);
};
export
default
LatestTxsItemSkeleton
;
ui/home/LatestTxs.tsx
View file @
18845138
import
{
Box
,
Flex
,
Text
,
Skeleton
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Flex
,
Text
}
from
'
@chakra-ui/react
'
;
import
{
route
}
from
'
nextjs-routes
'
;
import
React
from
'
react
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useNewTxsSocket
from
'
lib/hooks/useNewTxsSocket
'
;
import
{
TX
}
from
'
stubs/tx
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
import
SocketNewItemsNotice
from
'
ui/shared/SocketNewItemsNotice
'
;
import
LatestTxsItem
from
'
./LatestTxsItem
'
;
import
LatestTxsItemSkeleton
from
'
./LatestTxsItemSkeleton
'
;
const
LatestTransactions
=
()
=>
{
const
isMobile
=
useIsMobile
();
const
txsCount
=
isMobile
?
2
:
6
;
const
{
data
,
isLoading
,
isError
}
=
useApiQuery
(
'
homepage_txs
'
);
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_txs
'
,
{
queryOptions
:
{
placeholderData
:
Array
(
txsCount
).
fill
(
TX
),
},
});
const
{
num
,
socketAlert
}
=
useNewTxsSocket
();
if
(
isLoading
)
{
return
(
<>
<
Skeleton
h=
"32px"
w=
"100%"
borderBottomLeftRadius=
{
0
}
borderBottomRightRadius=
{
0
}
/>
{
Array
.
from
(
Array
(
txsCount
)).
map
((
item
,
index
)
=>
<
LatestTxsItemSkeleton
key=
{
index
}
/>)
}
</>
);
}
if
(
isError
)
{
return
<
Text
mt=
{
4
}
>
No data. Please reload page.
</
Text
>;
}
...
...
@@ -35,9 +30,15 @@ const LatestTransactions = () => {
const
txsUrl
=
route
({
pathname
:
'
/txs
'
});
return
(
<>
<
SocketNewItemsNotice
borderBottomRadius=
{
0
}
url=
{
txsUrl
}
num=
{
num
}
alert=
{
socketAlert
}
/>
<
SocketNewItemsNotice
borderBottomRadius=
{
0
}
url=
{
txsUrl
}
num=
{
num
}
alert=
{
socketAlert
}
isLoading=
{
isPlaceholderData
}
/>
<
Box
mb=
{
{
base
:
3
,
lg
:
4
}
}
>
{
data
.
slice
(
0
,
txsCount
).
map
((
tx
=>
<
LatestTxsItem
key=
{
tx
.
hash
}
tx=
{
tx
}
/>))
}
{
data
.
slice
(
0
,
txsCount
).
map
(((
tx
,
index
)
=>
(
<
LatestTxsItem
key=
{
tx
.
hash
+
(
isPlaceholderData
?
index
:
''
)
}
tx=
{
tx
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
Box
>
<
Flex
justifyContent=
"center"
>
<
LinkInternal
fontSize=
"sm"
href=
{
txsUrl
}
>
View all transactions
</
LinkInternal
>
...
...
ui/home/LatestTxsItem.tsx
View file @
18845138
...
...
@@ -2,9 +2,9 @@ import {
Box
,
Flex
,
HStack
,
Icon
,
Text
,
Grid
,
Skeleton
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
...
...
@@ -19,15 +19,17 @@ import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import
Address
from
'
ui/shared/address/Address
'
;
import
AddressIcon
from
'
ui/shared/address/AddressIcon
'
;
import
AddressLink
from
'
ui/shared/address/AddressLink
'
;
import
Icon
from
'
ui/shared/chakra/Icon
'
;
import
TxStatus
from
'
ui/shared/TxStatus
'
;
import
TxAdditionalInfo
from
'
ui/txs/TxAdditionalInfo
'
;
import
TxType
from
'
ui/txs/TxType
'
;
type
Props
=
{
tx
:
Transaction
;
isLoading
?:
boolean
;
}
const
LatestTxsItem
=
({
tx
}:
Props
)
=>
{
const
LatestTxsItem
=
({
tx
,
isLoading
}:
Props
)
=>
{
const
dataTo
=
tx
.
to
?
tx
.
to
:
tx
.
created_contract
;
const
timeAgo
=
useTimeAgoIncrement
(
tx
.
timestamp
||
'
0
'
,
true
);
...
...
@@ -44,10 +46,10 @@ const LatestTxsItem = ({ tx }: Props) => {
>
<
Flex
justifyContent=
"space-between"
>
<
HStack
>
<
TxType
types=
{
tx
.
tx_types
}
/>
<
TxStatus
status=
{
tx
.
status
}
errorText=
{
tx
.
status
===
'
error
'
?
tx
.
result
:
undefined
}
/>
<
TxType
types=
{
tx
.
tx_types
}
isLoading=
{
isLoading
}
/>
<
TxStatus
status=
{
tx
.
status
}
errorText=
{
tx
.
status
===
'
error
'
?
tx
.
result
:
undefined
}
isLoading=
{
isLoading
}
/>
</
HStack
>
<
TxAdditionalInfo
tx=
{
tx
}
isMobile
/>
<
TxAdditionalInfo
tx=
{
tx
}
isMobile
isLoading=
{
isLoading
}
/>
</
Flex
>
<
Flex
mt=
{
2
}
...
...
@@ -62,6 +64,7 @@ const LatestTxsItem = ({ tx }: Props) => {
boxSize=
"30px"
mr=
{
2
}
color=
"link"
isLoading=
{
isLoading
}
/>
<
Address
width=
"100%"
>
<
AddressLink
...
...
@@ -69,14 +72,19 @@ const LatestTxsItem = ({ tx }: Props) => {
type=
"transaction"
fontWeight=
"700"
truncation=
"constant"
isLoading=
{
isLoading
}
/>
</
Address
>
</
Flex
>
{
tx
.
timestamp
&&
<
Text
variant=
"secondary"
fontWeight=
"400"
fontSize=
"sm"
>
{
timeAgo
}
</
Text
>
}
{
tx
.
timestamp
&&
(
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
fontWeight=
"400"
fontSize=
"sm"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
)
}
</
Flex
>
<
Flex
alignItems=
"center"
mb=
{
3
}
>
<
Address
>
<
AddressIcon
address=
{
tx
.
from
}
/>
<
AddressIcon
address=
{
tx
.
from
}
isLoading=
{
isLoading
}
/>
<
AddressLink
type=
"address"
hash=
{
tx
.
from
.
hash
}
...
...
@@ -85,6 +93,7 @@ const LatestTxsItem = ({ tx }: Props) => {
ml=
{
2
}
truncation=
"constant"
fontSize=
"sm"
isLoading=
{
isLoading
}
/>
</
Address
>
<
Icon
...
...
@@ -92,10 +101,11 @@ const LatestTxsItem = ({ tx }: Props) => {
boxSize=
{
6
}
mx=
{
2
}
color=
"gray.500"
isLoading=
{
isLoading
}
/>
{
dataTo
&&
(
<
Address
>
<
AddressIcon
address=
{
dataTo
}
/>
<
AddressIcon
address=
{
dataTo
}
isLoading=
{
isLoading
}
/>
<
AddressLink
type=
"address"
hash=
{
dataTo
.
hash
}
...
...
@@ -104,18 +114,19 @@ const LatestTxsItem = ({ tx }: Props) => {
ml=
{
2
}
truncation=
"constant"
fontSize=
"sm"
isLoading=
{
isLoading
}
/>
</
Address
>
)
}
</
Flex
>
<
Box
mb=
{
2
}
fontSize=
"sm
"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
mb=
{
2
}
fontSize=
"sm"
w=
"fit-content
"
>
<
Text
as=
"span"
>
Value
{
appConfig
.
network
.
currency
.
symbol
}
</
Text
>
<
Text
as=
"span"
variant=
"secondary"
>
{
getValueWithUnit
(
tx
.
value
).
dp
(
5
).
toFormat
()
}
</
Text
>
</
Box
>
<
Box
fontSize=
"sm
"
>
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontSize=
"sm"
w=
"fit-content
"
>
<
Text
as=
"span"
>
Fee
{
appConfig
.
network
.
currency
.
symbol
}
</
Text
>
<
Text
as=
"span"
variant=
"secondary"
>
{
getValueWithUnit
(
tx
.
fee
.
value
).
dp
(
5
).
toFormat
()
}
</
Text
>
</
Box
>
</
Skeleton
>
</
Box
>
);
}
...
...
@@ -131,11 +142,11 @@ const LatestTxsItem = ({ tx }: Props) => {
>
<
Grid
width=
"100%"
gridTemplateColumns=
"3fr 2fr 150px"
gridGap=
{
8
}
>
<
Flex
overflow=
"hidden"
w=
"100%"
>
<
TxAdditionalInfo
tx=
{
tx
}
/>
<
TxAdditionalInfo
tx=
{
tx
}
isLoading=
{
isLoading
}
/>
<
Box
ml=
{
3
}
w=
"calc(100% - 40px)"
>
<
HStack
>
<
TxType
types=
{
tx
.
tx_types
}
/>
<
TxStatus
status=
{
tx
.
status
}
errorText=
{
tx
.
status
===
'
error
'
?
tx
.
result
:
undefined
}
/>
<
TxType
types=
{
tx
.
tx_types
}
isLoading=
{
isLoading
}
/>
<
TxStatus
status=
{
tx
.
status
}
errorText=
{
tx
.
status
===
'
error
'
?
tx
.
result
:
undefined
}
isLoading=
{
isLoading
}
/>
</
HStack
>
<
Flex
mt=
{
2
}
...
...
@@ -146,16 +157,22 @@ const LatestTxsItem = ({ tx }: Props) => {
boxSize=
"30px"
color=
"link"
display=
"inline"
mr=
{
2
}
isLoading=
{
isLoading
}
borderRadius=
"base"
/>
<
Address
overflow=
"hidden"
w=
"calc(100% - 130px)"
maxW=
"calc(100% - 130px)"
mr=
{
2
}
>
<
Address
overflow=
"hidden"
w=
"calc(100% - 130px)"
maxW=
"calc(100% - 130px)"
m
l=
{
2
}
m
r=
{
2
}
>
<
AddressLink
hash=
{
tx
.
hash
}
type=
"transaction"
fontWeight=
"700"
isLoading=
{
isLoading
}
/>
</
Address
>
{
tx
.
timestamp
&&
<
Text
variant=
"secondary"
fontWeight=
"400"
fontSize=
"sm"
>
{
timeAgo
}
</
Text
>
}
{
tx
.
timestamp
&&
(
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
fontWeight=
"400"
fontSize=
"sm"
>
<
span
>
{
timeAgo
}
</
span
>
</
Skeleton
>
)
}
</
Flex
>
</
Box
>
</
Flex
>
...
...
@@ -165,10 +182,11 @@ const LatestTxsItem = ({ tx }: Props) => {
boxSize=
{
6
}
color=
"gray.500"
transform=
"rotate(90deg)"
isLoading=
{
isLoading
}
/>
<
Box
overflow=
"hidden"
ml=
{
1
}
>
<
Address
mb=
{
2
}
>
<
AddressIcon
address=
{
tx
.
from
}
/>
<
AddressIcon
address=
{
tx
.
from
}
isLoading=
{
isLoading
}
/>
<
AddressLink
type=
"address"
hash=
{
tx
.
from
.
hash
}
...
...
@@ -176,11 +194,12 @@ const LatestTxsItem = ({ tx }: Props) => {
fontWeight=
"500"
ml=
{
2
}
fontSize=
"sm"
isLoading=
{
isLoading
}
/>
</
Address
>
{
dataTo
&&
(
<
Address
>
<
AddressIcon
address=
{
dataTo
}
/>
<
AddressIcon
address=
{
dataTo
}
isLoading=
{
isLoading
}
/>
<
AddressLink
type=
"address"
hash=
{
dataTo
.
hash
}
...
...
@@ -188,20 +207,21 @@ const LatestTxsItem = ({ tx }: Props) => {
fontWeight=
"500"
ml=
{
2
}
fontSize=
"sm"
isLoading=
{
isLoading
}
/>
</
Address
>
)
}
</
Box
>
</
Grid
>
<
Box
>
<
Box
mb=
{
2
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
mb=
{
2
}
>
<
Text
as=
"span"
whiteSpace=
"pre"
>
{
appConfig
.
network
.
currency
.
symbol
}
</
Text
>
<
Text
as=
"span"
variant=
"secondary"
>
{
getValueWithUnit
(
tx
.
value
).
dp
(
5
).
toFormat
()
}
</
Text
>
</
Box
>
<
Box
>
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
>
<
Text
as=
"span"
>
Fee
</
Text
>
<
Text
as=
"span"
variant=
"secondary"
>
{
getValueWithUnit
(
tx
.
fee
.
value
).
dp
(
5
).
toFormat
()
}
</
Text
>
</
Box
>
</
Skeleton
>
</
Box
>
</
Grid
>
</
Box
>
...
...
ui/home/LatestTxsItemSkeleton.tsx
deleted
100644 → 0
View file @
825aac59
import
{
Box
,
Flex
,
HStack
,
Skeleton
,
SkeletonCircle
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
const
LatestTxsItemSkeleton
=
()
=>
{
return
(
<
Box
width=
"100%"
minW=
{
{
base
:
'
unset
'
,
lg
:
'
700px
'
}
}
borderTop=
"1px solid"
borderColor=
"divider"
py=
{
4
}
px=
{
{
base
:
0
,
lg
:
4
}
}
_last=
{
{
borderBottom
:
'
1px solid
'
,
borderColor
:
'
divider
'
}
}
>
<
Box
width=
"100%"
display=
{
{
base
:
'
block
'
,
lg
:
'
none
'
}
}
>
<
HStack
spacing=
{
2
}
>
<
Skeleton
w=
"101px"
h=
"24px"
/>
<
Skeleton
w=
"101px"
h=
"24px"
/>
</
HStack
>
<
Flex
mt=
{
2
}
alignItems=
"center"
width=
"100%"
justifyContent=
"space-between"
mb=
{
6
}
>
<
Flex
mr=
{
3
}
alignItems=
"center"
>
<
Skeleton
w=
"30px"
h=
"30px"
mr=
{
2
}
/>
<
Skeleton
w=
"101px"
h=
"12px"
/>
</
Flex
>
<
Skeleton
w=
"40px"
h=
"12px"
/>
</
Flex
>
<
Flex
alignItems=
"center"
mb=
{
3
}
>
<
SkeletonCircle
w=
"30px"
h=
"30px"
mr=
{
2
}
/>
<
Skeleton
w=
"101px"
h=
"12px"
mr=
{
5
}
/>
<
SkeletonCircle
w=
"30px"
h=
"30px"
mr=
{
2
}
/>
<
Skeleton
w=
"101px"
h=
"12px"
/>
</
Flex
>
<
Skeleton
w=
"123px"
h=
"12px"
mb=
{
2
}
mt=
{
3
}
/>
<
Skeleton
w=
"123px"
h=
"12px"
/>
</
Box
>
<
Box
display=
{
{
base
:
'
none
'
,
lg
:
'
grid
'
}
}
width=
"100%"
gridTemplateColumns=
"3fr 2fr 150px"
gridGap=
{
8
}
>
<
Flex
w=
"100%"
>
<
Skeleton
w=
{
5
}
h=
{
5
}
mr=
{
3
}
/>
<
Box
w=
"100%"
>
<
HStack
>
<
Skeleton
w=
"101px"
h=
"24px"
/>
<
Skeleton
w=
"101px"
h=
"24px"
/>
</
HStack
>
<
Flex
alignItems=
"center"
mt=
{
2
}
>
<
Skeleton
w=
"30px"
h=
"30px"
mr=
{
2
}
/>
<
Skeleton
w=
"calc(100% - 100px)"
h=
"20px"
mr=
{
5
}
/>
<
Skeleton
w=
"40px"
h=
"16px"
/>
</
Flex
>
</
Box
>
</
Flex
>
<
Box
>
<
Flex
alignItems=
"center"
mb=
{
2
}
mt=
{
1
}
>
<
SkeletonCircle
w=
"24px"
h=
"24px"
mr=
{
2
}
/>
<
Skeleton
w=
"100%"
h=
"16px"
/>
</
Flex
>
<
Flex
alignItems=
"center"
>
<
SkeletonCircle
w=
"24px"
h=
"24px"
mr=
{
2
}
/>
<
Skeleton
w=
"100%"
h=
"16px"
/>
</
Flex
>
</
Box
>
<
Box
>
<
Skeleton
w=
"123px"
h=
"16px"
mb=
{
4
}
mt=
{
2
}
/>
<
Skeleton
w=
"123px"
h=
"16px"
/>
</
Box
>
</
Box
>
</
Box
>
);
};
export
default
LatestTxsItemSkeleton
;
ui/home/LatestWatchlistTxs.tsx
View file @
18845138
...
...
@@ -5,26 +5,26 @@ import React from 'react';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
useRedirectForInvalidAuthToken
from
'
lib/hooks/useRedirectForInvalidAuthToken
'
;
import
{
TX
}
from
'
stubs/tx
'
;
import
LinkInternal
from
'
ui/shared/LinkInternal
'
;
import
LatestTxsItem
from
'
./LatestTxsItem
'
;
import
LatestTxsItemSkeleton
from
'
./LatestTxsItemSkeleton
'
;
const
LatestWatchlistTxs
=
()
=>
{
useRedirectForInvalidAuthToken
();
const
isMobile
=
useIsMobile
();
const
txsCount
=
isMobile
?
2
:
6
;
const
{
data
,
is
Loading
,
isError
}
=
useApiQuery
(
'
homepage_txs_watchlist
'
);
if
(
isLoading
)
{
return
<>
{
Array
.
from
(
Array
(
txsCount
)).
map
((
item
,
index
)
=>
<
LatestTxsItemSkeleton
key=
{
index
}
/>)
}
</>;
}
const
{
data
,
is
PlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_txs_watchlist
'
,
{
queryOptions
:
{
placeholderData
:
Array
(
txsCount
).
fill
(
TX
),
},
}
);
if
(
isError
)
{
return
<
Text
mt=
{
4
}
>
No data. Please reload page.
</
Text
>;
}
if
(
data
.
length
===
0
)
{
if
(
!
data
?.
length
)
{
return
<
Text
mt=
{
4
}
>
There are no transactions.
</
Text
>;
}
...
...
@@ -33,7 +33,13 @@ const LatestWatchlistTxs = () => {
return
(
<>
<
Box
mb=
{
{
base
:
3
,
lg
:
4
}
}
>
{
data
.
slice
(
0
,
txsCount
).
map
((
tx
=>
<
LatestTxsItem
key=
{
tx
.
hash
}
tx=
{
tx
}
/>))
}
{
data
.
slice
(
0
,
txsCount
).
map
(((
tx
,
index
)
=>
(
<
LatestTxsItem
key=
{
tx
.
hash
+
(
isPlaceholderData
?
index
:
''
)
}
tx=
{
tx
}
isLoading=
{
isPlaceholderData
}
/>
)))
}
</
Box
>
<
Flex
justifyContent=
"center"
>
<
LinkInternal
fontSize=
"sm"
href=
{
txsUrl
}
>
View all watch list transactions
</
LinkInternal
>
...
...
ui/home/Stats.tsx
View file @
18845138
...
...
@@ -9,10 +9,10 @@ import gasIcon from 'icons/gas.svg';
import
txIcon
from
'
icons/transactions.svg
'
;
import
walletIcon
from
'
icons/wallet.svg
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
HOMEPAGE_STATS
}
from
'
stubs/stats
'
;
import
StatsGasPrices
from
'
./StatsGasPrices
'
;
import
StatsItem
from
'
./StatsItem
'
;
import
StatsItemSkeleton
from
'
./StatsItemSkeleton
'
;
const
hasGasTracker
=
appConfig
.
homepage
.
showGasTracker
;
const
hasAvgBlockTime
=
appConfig
.
homepage
.
showAvgBlockTime
;
...
...
@@ -22,7 +22,11 @@ let itemsCount = 5;
!
hasAvgBlockTime
&&
itemsCount
--
;
const
Stats
=
()
=>
{
const
{
data
,
isLoading
,
isError
}
=
useApiQuery
(
'
homepage_stats
'
);
const
{
data
,
isPlaceholderData
,
isError
}
=
useApiQuery
(
'
homepage_stats
'
,
{
queryOptions
:
{
placeholderData
:
HOMEPAGE_STATS
,
},
});
if
(
isError
)
{
return
null
;
...
...
@@ -32,13 +36,10 @@ const Stats = () => {
const
lastItemTouchStyle
=
{
gridColumn
:
{
base
:
'
span 2
'
,
lg
:
'
unset
'
}
};
if
(
isLoading
)
{
content
=
Array
.
from
(
Array
(
itemsCount
)).
map
((
item
,
index
)
=>
<
StatsItemSkeleton
key=
{
index
}
_last=
{
itemsCount
%
2
?
lastItemTouchStyle
:
undefined
}
/>);
}
if
(
data
)
{
const
isOdd
=
Boolean
(
hasGasTracker
&&
!
data
.
gas_prices
?
(
itemsCount
-
1
)
%
2
:
itemsCount
%
2
);
const
gasLabel
=
hasGasTracker
&&
data
.
gas_prices
?
<
StatsGasPrices
gasPrices=
{
data
.
gas_prices
}
/>
:
null
;
content
=
(
<>
<
StatsItem
...
...
@@ -46,12 +47,14 @@ const Stats = () => {
title=
"Total blocks"
value=
{
Number
(
data
.
total_blocks
).
toLocaleString
()
}
url=
{
route
({
pathname
:
'
/blocks
'
})
}
isLoading=
{
isPlaceholderData
}
/>
{
hasAvgBlockTime
&&
(
<
StatsItem
icon=
{
clockIcon
}
title=
"Average block time"
value=
{
`${ (data.average_block_time / 1000).toFixed(1) } s`
}
isLoading=
{
isPlaceholderData
}
/>
)
}
<
StatsItem
...
...
@@ -59,12 +62,14 @@ const Stats = () => {
title=
"Total transactions"
value=
{
Number
(
data
.
total_transactions
).
toLocaleString
()
}
url=
{
route
({
pathname
:
'
/txs
'
})
}
isLoading=
{
isPlaceholderData
}
/>
<
StatsItem
icon=
{
walletIcon
}
title=
"Wallet addresses"
value=
{
Number
(
data
.
total_addresses
).
toLocaleString
()
}
_last=
{
isOdd
?
lastItemTouchStyle
:
undefined
}
isLoading=
{
isPlaceholderData
}
/>
{
hasGasTracker
&&
data
.
gas_prices
&&
(
<
StatsItem
...
...
@@ -73,6 +78,7 @@ const Stats = () => {
value=
{
`${ Number(data.gas_prices.average).toLocaleString() } Gwei`
}
_last=
{
isOdd
?
lastItemTouchStyle
:
undefined
}
tooltipLabel=
{
gasLabel
}
isLoading=
{
isPlaceholderData
}
/>
)
}
</>
...
...
ui/home/StatsItem.tsx
View file @
18845138
import
type
{
SystemStyleObject
,
TooltipProps
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Icon
,
Text
,
useColorModeValue
,
chakra
,
LightMode
}
from
'
@chakra-ui/react
'
;
import
{
Skeleton
,
Flex
,
useColorModeValue
,
chakra
,
LightMode
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
breakpoints
from
'
theme/foundations/breakpoints
'
;
import
Icon
from
'
ui/shared/chakra/Icon
'
;
import
Hint
from
'
ui/shared/Hint
'
;
type
Props
=
{
...
...
@@ -12,6 +13,7 @@ type Props = {
className
?:
string
;
tooltipLabel
?:
React
.
ReactNode
;
url
?:
string
;
isLoading
?:
boolean
;
}
const
LARGEST_BREAKPOINT
=
'
1240px
'
;
...
...
@@ -24,7 +26,7 @@ const TOOLTIP_PROPS: Partial<TooltipProps> = {
bgColor
:
'
blackAlpha.900
'
,
};
const
StatsItem
=
({
icon
,
title
,
value
,
className
,
tooltipLabel
,
url
}:
Props
)
=>
{
const
StatsItem
=
({
icon
,
title
,
value
,
className
,
tooltipLabel
,
url
,
isLoading
}:
Props
)
=>
{
const
sxContainer
:
SystemStyleObject
=
{
[
`@media screen and (min-width:
${
breakpoints
.
lg
}
) and (max-width:
${
LARGEST_BREAKPOINT
}
)`
]:
{
flexDirection
:
'
column
'
},
};
...
...
@@ -33,11 +35,13 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props)
[
`@media screen and (min-width:
${
breakpoints
.
lg
}
) and (max-width:
${
LARGEST_BREAKPOINT
}
)`
]:
{
alignItems
:
'
center
'
},
};
const
bgColor
=
useColorModeValue
(
'
blue.50
'
,
'
blue.800
'
);
const
loadingBgColor
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
);
const
infoColor
=
useColorModeValue
(
'
gray.600
'
,
'
gray.400
'
);
return
(
<
Flex
backgroundColor=
{
useColorModeValue
(
'
blue.50
'
,
'
blue.800
'
)
}
backgroundColor=
{
isLoading
?
loadingBgColor
:
bgColor
}
padding=
{
3
}
borderRadius=
"md"
flexDirection=
"row"
...
...
@@ -48,21 +52,25 @@ const StatsItem = ({ icon, title, value, className, tooltipLabel, url }: Props)
className=
{
className
}
color=
{
useColorModeValue
(
'
black
'
,
'
white
'
)
}
position=
"relative"
{
...
(
url
?
{
{
...
(
url
&&
!
isLoading
?
{
as
:
'
a
',
href
:
url
,
}
:
{})
}
>
<
Icon
as=
{
icon
}
boxSize=
{
7
}
/>
<
Icon
as=
{
icon
}
boxSize=
{
7
}
isLoading=
{
isLoading
}
borderRadius=
"base"
/>
<
Flex
flexDirection=
"column"
alignItems=
"start"
sx=
{
sxText
}
>
<
Text
variant=
"secondary"
fontSize=
"xs"
lineHeight=
"16px"
>
{
title
}
</
Text
>
<
Text
fontWeight=
{
500
}
fontSize=
"md"
color=
{
useColorModeValue
(
'
black
'
,
'
white
'
)
}
>
{
value
}
</
Text
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text_secondary"
fontSize=
"xs"
lineHeight=
"16px"
borderRadius=
"base"
>
<
span
>
{
title
}
</
span
>
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
fontWeight=
{
500
}
fontSize=
"md"
color=
{
useColorModeValue
(
'
black
'
,
'
white
'
)
}
borderRadius=
"base"
>
<
span
>
{
value
}
</
span
>
</
Skeleton
>
</
Flex
>
{
tooltipLabel
&&
(
{
tooltipLabel
&&
!
isLoading
&&
(
<
LightMode
>
<
Hint
label=
{
tooltipLabel
}
...
...
ui/home/StatsItemSkeleton.tsx
deleted
100644 → 0
View file @
825aac59
import
{
Flex
,
Skeleton
,
useColorModeValue
,
chakra
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
const
StatsItemSkeleton
=
({
className
}:
{
className
?:
string
})
=>
{
const
bgColor
=
useColorModeValue
(
'
blackAlpha.50
'
,
'
whiteAlpha.50
'
);
return
(
<
Flex
backgroundColor=
{
bgColor
}
padding=
{
3
}
borderRadius=
"md"
flexDirection=
{
{
base
:
'
row
'
,
lg
:
'
column
'
,
xl
:
'
row
'
}
}
alignItems=
"center"
columnGap=
{
3
}
rowGap=
{
2
}
className=
{
className
}
>
<
Skeleton
w=
"40px"
h=
"40px"
/>
<
Flex
flexDirection=
"column"
alignItems=
{
{
base
:
'
start
'
,
lg
:
'
center
'
,
xl
:
'
start
'
}
}
>
<
Skeleton
w=
"69px"
h=
"10px"
mt=
"4px"
mb=
"8px"
/>
<
Skeleton
w=
"93px"
h=
"14px"
mb=
"4px"
/>
</
Flex
>
</
Flex
>
);
};
export
default
chakra
(
StatsItemSkeleton
);
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