Commit ea01511b authored by tom's avatar tom

refactor latest blocks, batches and deposits

parent 083fd33f
import React from 'react';
type Id = string | number;
interface Params<T> {
data: Array<T>;
idFn: (item: T) => Id;
enabled: boolean;
}
export default function useInitialList<T>({ data, idFn, enabled }: Params<T>) {
const [ list, setList ] = React.useState<Array<Id>>([]);
React.useEffect(() => {
if (enabled) {
setList(data.map(idFn));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ enabled ]);
const isNew = React.useCallback((data: T) => {
return !list.includes(idFn(data));
}, [ list, idFn ]);
return React.useMemo(() => {
return {
list,
isNew,
};
}, [ list, isNew ]);
}
...@@ -57,6 +57,14 @@ export const textStyles: ThemingConfig['textStyles'] = { ...@@ -57,6 +57,14 @@ export const textStyles: ThemingConfig['textStyles'] = {
}, },
}, },
text: { text: {
xl: {
value: {
fontSize: '20px',
lineHeight: '28px',
fontWeight: '400',
fontFamily: 'body',
},
},
md: { md: {
value: { value: {
fontSize: '16px', fontSize: '16px',
......
import { chakra, Box, Heading, Flex, Text, VStack } from '@chakra-ui/react'; import { chakra, Box, Flex, Text, VStack } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { AnimatePresence } from 'framer-motion';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
...@@ -10,13 +9,15 @@ import { route } from 'nextjs-routes'; ...@@ -10,13 +9,15 @@ import { route } from 'nextjs-routes';
import config from 'configs/app'; import config from 'configs/app';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useInitialList from 'lib/hooks/useInitialList';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp } from 'lib/html-entities'; import { nbsp } from 'lib/html-entities';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { BLOCK } from 'stubs/block'; import { BLOCK } from 'stubs/block';
import { HOMEPAGE_STATS } from 'stubs/stats'; import { HOMEPAGE_STATS } from 'stubs/stats';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Heading } from 'toolkit/chakra/heading';
import { Skeleton } from 'toolkit/chakra/skeleton';
import LinkInternal from 'ui/shared/links/LinkInternal'; import LinkInternal from 'ui/shared/links/LinkInternal';
import LatestBlocksItem from './LatestBlocksItem'; import LatestBlocksItem from './LatestBlocksItem';
...@@ -35,6 +36,11 @@ const LatestBlocks = () => { ...@@ -35,6 +36,11 @@ const LatestBlocks = () => {
placeholderData: Array(blocksMaxCount).fill(BLOCK), placeholderData: Array(blocksMaxCount).fill(BLOCK),
}, },
}); });
const initialList = useInitialList({
data: data ?? [],
idFn: (block) => block.height,
enabled: !isPlaceholderData,
});
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const statsQueryResult = useApiQuery('stats', { const statsQueryResult = useApiQuery('stats', {
...@@ -78,16 +84,15 @@ const LatestBlocks = () => { ...@@ -78,16 +84,15 @@ const LatestBlocks = () => {
content = ( content = (
<> <>
<VStack spacing={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch"> <VStack gap={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch">
<AnimatePresence initial={ false } > { dataToShow.map(((block, index) => (
{ dataToShow.map(((block, index) => ( <LatestBlocksItem
<LatestBlocksItem key={ block.height + (isPlaceholderData ? String(index) : '') }
key={ block.height + (isPlaceholderData ? String(index) : '') } block={ block }
block={ block } isLoading={ isPlaceholderData }
isLoading={ isPlaceholderData } isNew={ initialList.isNew(block) }
/> />
))) } ))) }
</AnimatePresence>
</VStack> </VStack>
<Flex justifyContent="center"> <Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ route({ pathname: '/blocks' }) }>View all blocks</LinkInternal> <LinkInternal fontSize="sm" href={ route({ pathname: '/blocks' }) }>View all blocks</LinkInternal>
...@@ -98,9 +103,9 @@ const LatestBlocks = () => { ...@@ -98,9 +103,9 @@ const LatestBlocks = () => {
return ( return (
<Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }> <Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }>
<Heading as="h4" size="sm">Latest blocks</Heading> <Heading level="3" mb={ 3 }>Latest blocks</Heading>
{ statsQueryResult.data?.network_utilization_percentage !== undefined && ( { statsQueryResult.data?.network_utilization_percentage !== undefined && (
<Skeleton isLoaded={ !statsQueryResult.isPlaceholderData } mt={ 1 } display="inline-block"> <Skeleton loading={ statsQueryResult.isPlaceholderData } mt={ 1 } display="inline-block">
<Text as="span" fontSize="sm"> <Text as="span" fontSize="sm">
Network utilization:{ nbsp } Network utilization:{ nbsp }
</Text> </Text>
......
import { import { Box, Flex, Grid } from '@chakra-ui/react';
Box,
Flex,
Grid,
Tooltip,
} from '@chakra-ui/react';
import { motion } from 'framer-motion';
import React from 'react'; import React from 'react';
import type { Block } from 'types/api/block'; import type { Block } from 'types/api/block';
...@@ -12,7 +6,8 @@ import type { Block } from 'types/api/block'; ...@@ -12,7 +6,8 @@ import type { Block } from 'types/api/block';
import config from 'configs/app'; import config from 'configs/app';
import getBlockTotalReward from 'lib/block/getBlockTotalReward'; import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle'; import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import { Tooltip } from 'toolkit/chakra/tooltip';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import BlockEntity from 'ui/shared/entities/block/BlockEntity'; import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
...@@ -21,18 +16,14 @@ import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip'; ...@@ -21,18 +16,14 @@ import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
type Props = { type Props = {
block: Block; block: Block;
isLoading?: boolean; isLoading?: boolean;
isNew?: boolean;
}; };
const LatestBlocksItem = ({ block, isLoading }: Props) => { const LatestBlocksItem = ({ block, isLoading, isNew }: Props) => {
const totalReward = getBlockTotalReward(block); const totalReward = getBlockTotalReward(block);
return ( return (
<Box <Box
as={ motion.div } animation={ isNew ? 'fade-in 500ms linear' : undefined }
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ display: 'none' }}
transitionDuration="normal"
transitionTimingFunction="linear"
borderRadius="md" borderRadius="md"
border="1px solid" border="1px solid"
borderColor="border.divider" borderColor="border.divider"
...@@ -43,13 +34,12 @@ const LatestBlocksItem = ({ block, isLoading }: Props) => { ...@@ -43,13 +34,12 @@ const LatestBlocksItem = ({ block, isLoading }: Props) => {
isLoading={ isLoading } isLoading={ isLoading }
number={ block.height } number={ block.height }
tailLength={ 2 } tailLength={ 2 }
fontSize="xl" textStyle="xl"
lineHeight={ 7 }
fontWeight={ 500 } fontWeight={ 500 }
mr="auto" mr="auto"
/> />
{ block.celo?.is_epoch_block && ( { block.celo?.is_epoch_block && (
<Tooltip label={ `Finalized epoch #${ block.celo.epoch_number }` }> <Tooltip content={ `Finalized epoch #${ block.celo.epoch_number }` }>
<IconSvg name="checkered_flag" boxSize={ 5 } p="1px" ml={ 2 } isLoading={ isLoading } flexShrink={ 0 }/> <IconSvg name="checkered_flag" boxSize={ 5 } p="1px" ml={ 2 } isLoading={ isLoading } flexShrink={ 0 }/>
</Tooltip> </Tooltip>
) } ) }
...@@ -57,28 +47,27 @@ const LatestBlocksItem = ({ block, isLoading }: Props) => { ...@@ -57,28 +47,27 @@ const LatestBlocksItem = ({ block, isLoading }: Props) => {
timestamp={ block.timestamp } timestamp={ block.timestamp }
enableIncrement={ !isLoading } enableIncrement={ !isLoading }
isLoading={ isLoading } isLoading={ isLoading }
color="text_secondary" color="text.secondary"
fontWeight={ 400 }
display="inline-block" display="inline-block"
fontSize="sm" textStyle="sm"
flexShrink={ 0 } flexShrink={ 0 }
ml={ 2 } ml={ 2 }
/> />
</Flex> </Flex>
<Grid gridGap={ 2 } templateColumns="auto minmax(0, 1fr)" fontSize="sm"> <Grid gridGap={ 2 } templateColumns="auto minmax(0, 1fr)" fontSize="sm">
<Skeleton isLoaded={ !isLoading }>Txn</Skeleton> <Skeleton loading={ isLoading }>Txn</Skeleton>
<Skeleton isLoaded={ !isLoading } color="text_secondary"><span>{ block.transaction_count }</span></Skeleton> <Skeleton loading={ isLoading } color="text.secondary"><span>{ block.transaction_count }</span></Skeleton>
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward && ( { !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.total_reward && (
<> <>
<Skeleton isLoaded={ !isLoading }>Reward</Skeleton> <Skeleton loading={ isLoading }>Reward</Skeleton>
<Skeleton isLoaded={ !isLoading } color="text_secondary"><span>{ totalReward.dp(10).toFixed() }</span></Skeleton> <Skeleton loading={ isLoading } color="text.secondary"><span>{ totalReward.dp(10).toFixed() }</span></Skeleton>
</> </>
) } ) }
{ !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.miner && ( { !config.features.rollup.isEnabled && !config.UI.views.block.hiddenFields?.miner && (
<> <>
<Skeleton isLoaded={ !isLoading } textTransform="capitalize">{ getNetworkValidatorTitle() }</Skeleton> <Skeleton loading={ isLoading } textTransform="capitalize">{ getNetworkValidatorTitle() }</Skeleton>
<AddressEntity <AddressEntity
address={ block.miner } address={ block.miner }
isLoading={ isLoading } isLoading={ isLoading }
......
...@@ -19,7 +19,7 @@ const ChainIndicatorChartContainer = ({ data, isError, isPending }: Props) => { ...@@ -19,7 +19,7 @@ const ChainIndicatorChartContainer = ({ data, isError, isPending }: Props) => {
} }
if (isError) { if (isError) {
return <DataFetchAlert fontSize="xs" p={ 3 }/>; return <DataFetchAlert fontSize="xs"/>;
} }
if (data[0].items.length === 0) { if (data[0].items.length === 0) {
......
import { Box, Heading, Flex, Text, VStack } from '@chakra-ui/react'; import { Box, Flex, Text, VStack } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { AnimatePresence } from 'framer-motion'; // import { AnimatePresence } from 'framer-motion';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
...@@ -9,10 +9,12 @@ import type { ArbitrumL2TxnBatchesItem } from 'types/api/arbitrumL2'; ...@@ -9,10 +9,12 @@ import type { ArbitrumL2TxnBatchesItem } from 'types/api/arbitrumL2';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useInitialList from 'lib/hooks/useInitialList';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { ARBITRUM_L2_TXN_BATCHES_ITEM } from 'stubs/arbitrumL2'; import { ARBITRUM_L2_TXN_BATCHES_ITEM } from 'stubs/arbitrumL2';
import { Heading } from 'toolkit/chakra/heading';
import LinkInternal from 'ui/shared/links/LinkInternal'; import LinkInternal from 'ui/shared/links/LinkInternal';
import LatestBatchItem from './LatestBatchItem'; import LatestBatchItem from './LatestBatchItem';
...@@ -28,6 +30,12 @@ const LatestArbitrumL2Batches = () => { ...@@ -28,6 +30,12 @@ const LatestArbitrumL2Batches = () => {
}, },
}); });
const initialList = useInitialList({
data: data?.items ?? [],
idFn: (batch) => batch.number,
enabled: !isPlaceholderData,
});
const handleNewBatchMessage: SocketMessage.NewArbitrumL2Batch['handler'] = React.useCallback((payload) => { const handleNewBatchMessage: SocketMessage.NewArbitrumL2Batch['handler'] = React.useCallback((payload) => {
queryClient.setQueryData(getResourceKey('homepage_arbitrum_l2_batches'), (prevData: { items: Array<ArbitrumL2TxnBatchesItem> } | undefined) => { queryClient.setQueryData(getResourceKey('homepage_arbitrum_l2_batches'), (prevData: { items: Array<ArbitrumL2TxnBatchesItem> } | undefined) => {
const newItems = prevData?.items ? [ ...prevData.items ] : []; const newItems = prevData?.items ? [ ...prevData.items ] : [];
...@@ -61,18 +69,17 @@ const LatestArbitrumL2Batches = () => { ...@@ -61,18 +69,17 @@ const LatestArbitrumL2Batches = () => {
content = ( content = (
<> <>
<VStack spacing={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch"> <VStack gap={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch">
<AnimatePresence initial={ false } > { dataToShow.map(((batch, index) => (
{ dataToShow.map(((batch, index) => ( <LatestBatchItem
<LatestBatchItem key={ batch.number + (isPlaceholderData ? String(index) : '') }
key={ batch.number + (isPlaceholderData ? String(index) : '') } number={ batch.number }
number={ batch.number } timestamp={ batch.commitment_transaction.timestamp }
timestamp={ batch.commitment_transaction.timestamp } txCount={ batch.transactions_count }
txCount={ batch.transactions_count } isLoading={ isPlaceholderData }
isLoading={ isPlaceholderData } isNew={ initialList.isNew(batch) }
/> />
))) } ))) }
</AnimatePresence>
</VStack> </VStack>
<Flex justifyContent="center"> <Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ route({ pathname: '/batches' }) }>View all batches</LinkInternal> <LinkInternal fontSize="sm" href={ route({ pathname: '/batches' }) }>View all batches</LinkInternal>
...@@ -83,7 +90,7 @@ const LatestArbitrumL2Batches = () => { ...@@ -83,7 +90,7 @@ const LatestArbitrumL2Batches = () => {
return ( return (
<Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }> <Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }>
<Heading as="h4" size="sm" mb={ 3 }>Latest batches</Heading> <Heading level="3" mb={ 3 }>Latest batches</Heading>
{ content } { content }
</Box> </Box>
); );
......
import { import { Box, Flex } from '@chakra-ui/react';
Box,
Flex,
} from '@chakra-ui/react';
import { motion } from 'framer-motion';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import BatchEntityL2 from 'ui/shared/entities/block/BatchEntityL2'; import BatchEntityL2 from 'ui/shared/entities/block/BatchEntityL2';
import LinkInternal from 'ui/shared/links/LinkInternal'; import LinkInternal from 'ui/shared/links/LinkInternal';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip'; import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
...@@ -18,17 +14,13 @@ type Props = { ...@@ -18,17 +14,13 @@ type Props = {
txCount: number; txCount: number;
status?: React.ReactNode; status?: React.ReactNode;
isLoading: boolean; isLoading: boolean;
isNew?: boolean;
}; };
const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading }: Props) => { const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading, isNew }: Props) => {
return ( return (
<Box <Box
as={ motion.div } animation={ isNew ? 'fade-in 500ms linear' : undefined }
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ display: 'none' }}
transitionDuration="normal"
transitionTimingFunction="linear"
borderRadius="md" borderRadius="md"
border="1px solid" border="1px solid"
borderColor="border.divider" borderColor="border.divider"
...@@ -39,8 +31,7 @@ const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading }: Prop ...@@ -39,8 +31,7 @@ const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading }: Prop
isLoading={ isLoading } isLoading={ isLoading }
number={ number } number={ number }
tailLength={ 2 } tailLength={ 2 }
fontSize="xl" textStyle="xl"
lineHeight={ 7 }
fontWeight={ 500 } fontWeight={ 500 }
mr="auto" mr="auto"
/> />
...@@ -48,22 +39,21 @@ const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading }: Prop ...@@ -48,22 +39,21 @@ const LatestBatchItem = ({ number, timestamp, txCount, status, isLoading }: Prop
timestamp={ timestamp } timestamp={ timestamp }
enableIncrement={ !isLoading } enableIncrement={ !isLoading }
isLoading={ isLoading } isLoading={ isLoading }
color="text_secondary" color="text.secondary"
fontWeight={ 400 }
display="inline-block" display="inline-block"
fontSize="sm" textStyle="sm"
flexShrink={ 0 } flexShrink={ 0 }
ml={ 2 } ml={ 2 }
/> />
</Flex> </Flex>
<Flex alignItems="center" justifyContent="space-between" w="100%" flexWrap="wrap"> <Flex alignItems="center" justifyContent="space-between" w="100%" flexWrap="wrap">
<Flex alignItems="center"> <Flex alignItems="center">
<Skeleton isLoaded={ !isLoading } mr={ 2 }>Txn</Skeleton> <Skeleton loading={ isLoading } mr={ 2 }>Txn</Skeleton>
<LinkInternal <LinkInternal
href={ route({ pathname: '/batches/[number]', query: { number: number.toString(), tab: 'txs' } }) } href={ route({ pathname: '/batches/[number]', query: { number: number.toString(), tab: 'txs' } }) }
isLoading={ isLoading } isLoading={ isLoading }
> >
<Skeleton isLoaded={ !isLoading }> <Skeleton loading={ isLoading }>
{ txCount } { txCount }
</Skeleton> </Skeleton>
</LinkInternal> </LinkInternal>
......
import { Box, Heading, Flex, Text, VStack } from '@chakra-ui/react'; import { Box, Flex, Text, VStack } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { AnimatePresence } from 'framer-motion';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
...@@ -9,10 +8,12 @@ import type { ZkEvmL2TxnBatchesItem } from 'types/api/zkEvmL2'; ...@@ -9,10 +8,12 @@ import type { ZkEvmL2TxnBatchesItem } from 'types/api/zkEvmL2';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
import useInitialList from 'lib/hooks/useInitialList';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import useSocketChannel from 'lib/socket/useSocketChannel'; import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage'; import useSocketMessage from 'lib/socket/useSocketMessage';
import { ZKEVM_L2_TXN_BATCHES_ITEM } from 'stubs/zkEvmL2'; import { ZKEVM_L2_TXN_BATCHES_ITEM } from 'stubs/zkEvmL2';
import { Heading } from 'toolkit/chakra/heading';
import LinkInternal from 'ui/shared/links/LinkInternal'; import LinkInternal from 'ui/shared/links/LinkInternal';
import ZkEvmL2TxnBatchStatus from 'ui/shared/statusTag/ZkEvmL2TxnBatchStatus'; import ZkEvmL2TxnBatchStatus from 'ui/shared/statusTag/ZkEvmL2TxnBatchStatus';
...@@ -29,6 +30,12 @@ const LatestZkEvmL2Batches = () => { ...@@ -29,6 +30,12 @@ const LatestZkEvmL2Batches = () => {
}, },
}); });
const initialList = useInitialList({
data: data?.items ?? [],
idFn: (batch) => batch.number,
enabled: !isPlaceholderData,
});
const handleNewBatchMessage: SocketMessage.NewZkEvmL2Batch['handler'] = React.useCallback((payload) => { const handleNewBatchMessage: SocketMessage.NewZkEvmL2Batch['handler'] = React.useCallback((payload) => {
queryClient.setQueryData(getResourceKey('homepage_zkevm_l2_batches'), (prevData: { items: Array<ZkEvmL2TxnBatchesItem> } | undefined) => { queryClient.setQueryData(getResourceKey('homepage_zkevm_l2_batches'), (prevData: { items: Array<ZkEvmL2TxnBatchesItem> } | undefined) => {
const newItems = prevData?.items ? [ ...prevData.items ] : []; const newItems = prevData?.items ? [ ...prevData.items ] : [];
...@@ -62,22 +69,21 @@ const LatestZkEvmL2Batches = () => { ...@@ -62,22 +69,21 @@ const LatestZkEvmL2Batches = () => {
content = ( content = (
<> <>
<VStack spacing={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch"> <VStack gap={ 2 } mb={ 3 } overflow="hidden" alignItems="stretch">
<AnimatePresence initial={ false } > { dataToShow.map(((batch, index) => {
{ dataToShow.map(((batch, index) => { const status = <ZkEvmL2TxnBatchStatus status={ batch.status } isLoading={ isPlaceholderData }/>;
const status = <ZkEvmL2TxnBatchStatus status={ batch.status } isLoading={ isPlaceholderData }/>; return (
return ( <LatestBatchItem
<LatestBatchItem key={ batch.number + (isPlaceholderData ? String(index) : '') }
key={ batch.number + (isPlaceholderData ? String(index) : '') } number={ batch.number }
number={ batch.number } txCount={ batch.transaction_count }
txCount={ batch.transaction_count } timestamp={ batch.timestamp }
timestamp={ batch.timestamp } status={ status }
status={ status } isLoading={ isPlaceholderData }
isLoading={ isPlaceholderData } isNew={ initialList.isNew(batch) }
/> />
); );
})) } })) }
</AnimatePresence>
</VStack> </VStack>
<Flex justifyContent="center"> <Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ route({ pathname: '/batches' }) }>View all batches</LinkInternal> <LinkInternal fontSize="sm" href={ route({ pathname: '/batches' }) }>View all batches</LinkInternal>
...@@ -88,7 +94,7 @@ const LatestZkEvmL2Batches = () => { ...@@ -88,7 +94,7 @@ const LatestZkEvmL2Batches = () => {
return ( return (
<Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }> <Box width={{ base: '100%', lg: '280px' }} flexShrink={ 0 }>
<Heading as="h4" size="sm" mb={ 3 }>Latest batches</Heading> <Heading level="3" mb={ 3 }>Latest batches</Heading>
{ content } { content }
</Box> </Box>
); );
......
...@@ -9,7 +9,7 @@ import React from 'react'; ...@@ -9,7 +9,7 @@ import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1'; import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1'; import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
...@@ -43,16 +43,14 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -43,16 +43,14 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
<BlockEntityL1 <BlockEntityL1
number={ item.l1BlockNumber } number={ item.l1BlockNumber }
isLoading={ isLoading } isLoading={ isLoading }
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
fontWeight={ 700 } fontWeight={ 700 }
/> />
) : ( ) : (
<BlockEntityL1 <BlockEntityL1
number="TBD" number="TBD"
isLoading={ isLoading } isLoading={ isLoading }
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
fontWeight={ 700 } fontWeight={ 700 }
noLink noLink
/> />
...@@ -62,16 +60,14 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -62,16 +60,14 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
<TxEntityL1 <TxEntityL1
isLoading={ isLoading } isLoading={ isLoading }
hash={ item.l1TxHash } hash={ item.l1TxHash }
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
truncation={ isMobile ? 'constant_long' : 'dynamic' } truncation={ isMobile ? 'constant_long' : 'dynamic' }
/> />
) : ( ) : (
<TxEntityL1 <TxEntityL1
isLoading={ isLoading } isLoading={ isLoading }
hash="To be determined" hash="To be determined"
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
truncation="none" truncation="none"
noLink noLink
/> />
...@@ -81,8 +77,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -81,8 +77,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
<TxEntity <TxEntity
isLoading={ isLoading } isLoading={ isLoading }
hash={ item.l2TxHash } hash={ item.l2TxHash }
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
truncation={ isMobile ? 'constant_long' : 'dynamic' } truncation={ isMobile ? 'constant_long' : 'dynamic' }
/> />
); );
...@@ -97,16 +92,16 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -97,16 +92,16 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
<TimeAgoWithTooltip <TimeAgoWithTooltip
timestamp={ item.timestamp } timestamp={ item.timestamp }
isLoading={ isLoading } isLoading={ isLoading }
color="text_secondary" color="text.secondary"
/> />
) : <GridItem/> } ) : <GridItem/> }
</Flex> </Flex>
<Grid gridTemplateColumns="56px auto"> <Grid gridTemplateColumns="56px auto">
<Skeleton isLoaded={ !isLoading } my="5px" w="fit-content"> <Skeleton loading={ isLoading } my="5px" w="fit-content">
L1 txn L1 txn
</Skeleton> </Skeleton>
{ l1TxLink } { l1TxLink }
<Skeleton isLoaded={ !isLoading } my="3px" w="fit-content"> <Skeleton loading={ isLoading } my="3px" w="fit-content">
L2 txn L2 txn
</Skeleton> </Skeleton>
{ l2TxLink } { l2TxLink }
...@@ -118,7 +113,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -118,7 +113,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
return ( return (
<Grid width="100%" columnGap={ 4 } rowGap={ 2 } templateColumns="max-content max-content auto" w="100%"> <Grid width="100%" columnGap={ 4 } rowGap={ 2 } templateColumns="max-content max-content auto" w="100%">
{ l1BlockLink } { l1BlockLink }
<Skeleton isLoaded={ !isLoading } w="fit-content" h="fit-content" my="5px"> <Skeleton loading={ isLoading } w="fit-content" h="fit-content" my="5px">
L1 txn L1 txn
</Skeleton> </Skeleton>
{ l1TxLink } { l1TxLink }
...@@ -126,13 +121,13 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -126,13 +121,13 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
<TimeAgoWithTooltip <TimeAgoWithTooltip
timestamp={ item.timestamp } timestamp={ item.timestamp }
isLoading={ isLoading } isLoading={ isLoading }
color="text_secondary" color="text.secondary"
w="fit-content" w="fit-content"
h="fit-content" h="fit-content"
my="2px" my="2px"
/> />
) : <GridItem/> } ) : <GridItem/> }
<Skeleton isLoaded={ !isLoading } w="fit-content" h="fit-content" my="2px"> <Skeleton loading={ isLoading } w="fit-content" h="fit-content" my="2px">
L2 txn L2 txn
</Skeleton> </Skeleton>
{ l2TxLink } { l2TxLink }
...@@ -148,8 +143,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => { ...@@ -148,8 +143,7 @@ const LatestDepositsItem = ({ item, isLoading }: ItemProps) => {
py={ 4 } py={ 4 }
px={{ base: 0, lg: 4 }} px={{ base: 0, lg: 4 }}
_last={{ borderBottom: '1px solid', borderColor: 'border.divider' }} _last={{ borderBottom: '1px solid', borderColor: 'border.divider' }}
fontSize="sm" textStyle="sm"
lineHeight={ 5 }
> >
{ content } { content }
</Box> </Box>
...@@ -171,7 +165,7 @@ const LatestDeposits = ({ isLoading, items, socketAlert, socketItemsNum }: Props ...@@ -171,7 +165,7 @@ const LatestDeposits = ({ isLoading, items, socketAlert, socketItemsNum }: Props
))) } ))) }
</Box> </Box>
<Flex justifyContent="center"> <Flex justifyContent="center">
<LinkInternal fontSize="sm" href={ depositsUrl }>View all deposits</LinkInternal> <LinkInternal textStyle="sm" href={ depositsUrl }>View all deposits</LinkInternal>
</Flex> </Flex>
</> </>
); );
......
...@@ -15,18 +15,18 @@ const rollupFeature = config.features.rollup; ...@@ -15,18 +15,18 @@ const rollupFeature = config.features.rollup;
const Home = () => { const Home = () => {
// const leftWidget = (() => { const leftWidget = (() => {
// if (rollupFeature.isEnabled && !rollupFeature.homepage.showLatestBlocks) { if (rollupFeature.isEnabled && !rollupFeature.homepage.showLatestBlocks) {
// switch (rollupFeature.type) { switch (rollupFeature.type) {
// case 'zkEvm': case 'zkEvm':
// return <LatestZkEvmL2Batches/>; return <LatestZkEvmL2Batches/>;
// case 'arbitrum': case 'arbitrum':
// return <LatestArbitrumL2Batches/>; return <LatestArbitrumL2Batches/>;
// } }
// } }
// return <LatestBlocks/>; return <LatestBlocks/>;
// })(); })();
return ( return (
<Box as="main"> <Box as="main">
...@@ -37,7 +37,7 @@ const Home = () => { ...@@ -37,7 +37,7 @@ const Home = () => {
</Flex> </Flex>
<AdBanner mt={ 6 } mx="auto" display={{ base: 'flex', lg: 'none' }} justifyContent="center"/> <AdBanner mt={ 6 } mx="auto" display={{ base: 'flex', lg: 'none' }} justifyContent="center"/>
<Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 6 }> <Flex mt={ 8 } direction={{ base: 'column', lg: 'row' }} columnGap={ 12 } rowGap={ 6 }>
{ /* { leftWidget } */ } { leftWidget }
<Box flexGrow={ 1 }> <Box flexGrow={ 1 }>
<Transactions/> <Transactions/>
</Box> </Box>
......
...@@ -174,7 +174,7 @@ const AddressEntry = (props: EntityProps) => { ...@@ -174,7 +174,7 @@ const AddressEntry = (props: EntityProps) => {
zIndex={ 0 } zIndex={ 0 }
> >
<Icon { ...partsProps.icon }/> <Icon { ...partsProps.icon }/>
{ props.noLink ? content : (<Link { ...partsProps.link }> { content } </Link>) } { props.noLink ? content : <Link { ...partsProps.link }>{ content }</Link> }
<Copy { ...partsProps.copy } altHash={ altHash }/> <Copy { ...partsProps.copy } altHash={ altHash }/>
</Container> </Container>
); );
......
import type { As } from '@chakra-ui/react';
import { chakra } from '@chakra-ui/react'; import { chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
...@@ -55,17 +54,17 @@ export interface EntityProps extends EntityBase.EntityBaseProps { ...@@ -55,17 +54,17 @@ export interface EntityProps extends EntityBase.EntityBaseProps {
const BlockEntity = (props: EntityProps) => { const BlockEntity = (props: EntityProps) => {
const partsProps = distributeEntityProps(props); const partsProps = distributeEntityProps(props);
const content = <Content { ...partsProps.content }/>;
return ( return (
<Container { ...partsProps.container }> <Container { ...partsProps.container }>
<Icon { ...partsProps.icon }/> <Icon { ...partsProps.icon }/>
<Link { ...partsProps.link }> { props.noLink ? content : <Link { ...partsProps.link }>{ content }</Link> }
<Content { ...partsProps.content }/>
</Link>
</Container> </Container>
); );
}; };
export default React.memo(chakra<As, EntityProps>(BlockEntity)); export default React.memo(chakra(BlockEntity));
export { export {
Container, Container,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment