Commit c0834be6 authored by tom's avatar tom

skeleton for address details

parent 16467af8
import type { NextPage } from 'next'; import type { NextPage } from 'next';
import dynamic from 'next/dynamic';
import Head from 'next/head'; import Head from 'next/head';
import type { RoutedQuery } from 'nextjs-routes'; import type { RoutedQuery } from 'nextjs-routes';
import React from 'react'; import React from 'react';
import getSeo from 'lib/next/address/getSeo'; import getSeo from 'lib/next/address/getSeo';
import Address from 'ui/pages/Address'; import Page from 'ui/shared/Page/Page';
const Address = dynamic(() => import('ui/pages/Address'), { ssr: false });
const AddressPage: NextPage<RoutedQuery<'/address/[hash]'>> = ({ hash }: RoutedQuery<'/address/[hash]'>) => { const AddressPage: NextPage<RoutedQuery<'/address/[hash]'>> = ({ hash }: RoutedQuery<'/address/[hash]'>) => {
const { title, description } = getSeo({ hash }); const { title, description } = getSeo({ hash });
...@@ -15,7 +18,9 @@ const AddressPage: NextPage<RoutedQuery<'/address/[hash]'>> = ({ hash }: RoutedQ ...@@ -15,7 +18,9 @@ const AddressPage: NextPage<RoutedQuery<'/address/[hash]'>> = ({ hash }: RoutedQ
<title>{ title }</title> <title>{ title }</title>
<meta name="description" content={ description }/> <meta name="description" content={ description }/>
</Head> </Head>
<Address/> <Page>
<Address/>
</Page>
</> </>
); );
}; };
......
import type { Address } from 'types/api/address'; import type { Address, AddressCounters } from 'types/api/address';
import type { AddressesItem } from 'types/api/addresses'; import type { AddressesItem } from 'types/api/addresses';
import { ADDRESS_HASH } from './addressParams'; import { ADDRESS_HASH } from './addressParams';
...@@ -6,7 +6,7 @@ import { TOKEN_INFO_ERC_20 } from './token'; ...@@ -6,7 +6,7 @@ import { TOKEN_INFO_ERC_20 } from './token';
export const ADDRESS_INFO: Address = { export const ADDRESS_INFO: Address = {
block_number_balance_updated_at: 8774377, block_number_balance_updated_at: 8774377,
coin_balance: '0', coin_balance: '810941268802273085757',
creation_tx_hash: null, creation_tx_hash: null,
creator_address_hash: null, creator_address_hash: null,
exchange_rate: null, exchange_rate: null,
...@@ -34,6 +34,13 @@ export const ADDRESS_INFO: Address = { ...@@ -34,6 +34,13 @@ export const ADDRESS_INFO: Address = {
watchlist_address_id: null, watchlist_address_id: null,
}; };
export const ADDRESS_COUNTERS: AddressCounters = {
gas_usage_count: '8028907522',
token_transfers_count: '420',
transactions_count: '119020',
validations_count: '0',
};
export const TOP_ADDRESS: AddressesItem = { export const TOP_ADDRESS: AddressesItem = {
coin_balance: '11886682377162664596540805', coin_balance: '11886682377162664596540805',
tx_count: '1835', tx_count: '1835',
......
import { Box, Text, Icon, Grid } from '@chakra-ui/react'; import { Box, Text, Grid, Skeleton } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
...@@ -10,9 +10,11 @@ import blockIcon from 'icons/block.svg'; ...@@ -10,9 +10,11 @@ import blockIcon from 'icons/block.svg';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import { ADDRESS_COUNTERS } from 'stubs/address';
import AddressCounterItem from 'ui/address/details/AddressCounterItem'; import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import AddressLink from 'ui/shared/address/AddressLink'; import AddressLink from 'ui/shared/address/AddressLink';
import AddressHeadingInfo from 'ui/shared/AddressHeadingInfo'; import AddressHeadingInfo from 'ui/shared/AddressHeadingInfo';
import Icon from 'ui/shared/chakra/Icon';
import DataFetchAlert from 'ui/shared/DataFetchAlert'; import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem'; import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem'; import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
...@@ -20,7 +22,6 @@ import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic'; ...@@ -20,7 +22,6 @@ import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
import AddressBalance from './details/AddressBalance'; import AddressBalance from './details/AddressBalance';
import AddressDetailsSkeleton from './details/AddressDetailsSkeleton';
import AddressNameInfo from './details/AddressNameInfo'; import AddressNameInfo from './details/AddressNameInfo';
import TokenSelect from './tokenSelect/TokenSelect'; import TokenSelect from './tokenSelect/TokenSelect';
...@@ -38,6 +39,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -38,6 +39,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
queryOptions: { queryOptions: {
enabled: Boolean(addressHash) && Boolean(addressQuery.data), enabled: Boolean(addressHash) && Boolean(addressQuery.data),
placeholderData: ADDRESS_COUNTERS,
}, },
}); });
...@@ -77,26 +79,27 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -77,26 +79,27 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (addressQuery.isLoading) {
return <AddressDetailsSkeleton/>;
}
const data = addressQuery.isError ? errorData : addressQuery.data; const data = addressQuery.isError ? errorData : addressQuery.data;
if (!data) {
return null;
}
return ( return (
<Box> <Box>
<AddressHeadingInfo address={ data } token={ data.token } isLinkDisabled/> <AddressHeadingInfo address={ data } token={ data.token } isLoading={ addressQuery.isPlaceholderData } isLinkDisabled/>
<Grid <Grid
mt={ 8 } mt={ 8 }
columnGap={ 8 } columnGap={ 8 }
rowGap={{ base: 1, lg: 3 }} rowGap={{ base: 1, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden" templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden"
> >
<AddressNameInfo data={ data }/> <AddressNameInfo data={ data } isLoading={ addressQuery.isPlaceholderData }/>
{ data.is_contract && data.creation_tx_hash && data.creator_address_hash && ( { data.is_contract && data.creation_tx_hash && data.creator_address_hash && (
<DetailsInfoItem <DetailsInfoItem
title="Creator" title="Creator"
hint="Transaction and address of creation" hint="Transaction and address of creation"
isLoading={ addressQuery.isPlaceholderData }
> >
<AddressLink type="address" hash={ data.creator_address_hash } truncation="constant"/> <AddressLink type="address" hash={ data.creator_address_hash } truncation="constant"/>
<Text whiteSpace="pre"> at txn </Text> <Text whiteSpace="pre"> at txn </Text>
...@@ -119,7 +122,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -119,7 +122,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
) } ) }
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
<AddressBalance data={ data }/> <AddressBalance data={ data } isLoading={ addressQuery.isPlaceholderData }/>
{ data.has_tokens && ( { data.has_tokens && (
<DetailsInfoItem <DetailsInfoItem
title="Tokens" title="Tokens"
...@@ -133,36 +136,68 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -133,36 +136,68 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
<DetailsInfoItem <DetailsInfoItem
title="Transactions" title="Transactions"
hint="Number of transactions related to this address" hint="Number of transactions related to this address"
isLoading={ addressQuery.isPlaceholderData || countersQuery.isPlaceholderData }
> >
{ addressQuery.data ? { addressQuery.data ? (
<AddressCounterItem prop="transactions_count" query={ countersQuery } address={ data.hash } onClick={ handleCounterItemClick }/> : <AddressCounterItem
prop="transactions_count"
query={ countersQuery }
address={ data.hash }
onClick={ handleCounterItemClick }
isAddressQueryLoading={ addressQuery.isPlaceholderData }
/>
) :
0 } 0 }
</DetailsInfoItem> </DetailsInfoItem>
{ data.has_token_transfers && ( { data.has_token_transfers && (
<DetailsInfoItem <DetailsInfoItem
title="Transfers" title="Transfers"
hint="Number of transfers to/from this address" hint="Number of transfers to/from this address"
isLoading={ addressQuery.isPlaceholderData || countersQuery.isPlaceholderData }
> >
{ addressQuery.data ? { addressQuery.data ? (
<AddressCounterItem prop="token_transfers_count" query={ countersQuery } address={ data.hash } onClick={ handleCounterItemClick }/> : <AddressCounterItem
prop="token_transfers_count"
query={ countersQuery }
address={ data.hash }
onClick={ handleCounterItemClick }
isAddressQueryLoading={ addressQuery.isPlaceholderData }
/>
) :
0 } 0 }
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
<DetailsInfoItem <DetailsInfoItem
title="Gas used" title="Gas used"
hint="Gas used by the address" hint="Gas used by the address"
isLoading={ addressQuery.isPlaceholderData || countersQuery.isPlaceholderData }
> >
{ addressQuery.data ? { addressQuery.data ? (
<AddressCounterItem prop="gas_usage_count" query={ countersQuery } address={ data.hash } onClick={ handleCounterItemClick }/> : <AddressCounterItem
prop="gas_usage_count"
query={ countersQuery }
address={ data.hash }
onClick={ handleCounterItemClick }
isAddressQueryLoading={ addressQuery.isPlaceholderData }
/>
) :
0 } 0 }
</DetailsInfoItem> </DetailsInfoItem>
{ data.has_validated_blocks && ( { data.has_validated_blocks && (
<DetailsInfoItem <DetailsInfoItem
title="Blocks validated" title="Blocks validated"
hint="Number of blocks validated by this validator" hint="Number of blocks validated by this validator"
isLoading={ addressQuery.isPlaceholderData || countersQuery.isPlaceholderData }
> >
{ addressQuery.data ? { addressQuery.data ? (
<AddressCounterItem prop="validations_count" query={ countersQuery } address={ data.hash } onClick={ handleCounterItemClick }/> : <AddressCounterItem
prop="validations_count"
query={ countersQuery }
address={ data.hash }
onClick={ handleCounterItemClick }
isAddressQueryLoading={ addressQuery.isPlaceholderData }
/>
) :
0 } 0 }
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
...@@ -172,18 +207,21 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -172,18 +207,21 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
hint="Block number in which the address was updated" hint="Block number in which the address was updated"
alignSelf="center" alignSelf="center"
py={{ base: '2px', lg: 1 }} py={{ base: '2px', lg: 1 }}
isLoading={ addressQuery.isPlaceholderData }
> >
<LinkInternal <LinkInternal
href={ route({ pathname: '/block/[height]', query: { height: String(data.block_number_balance_updated_at) } }) } href={ route({ pathname: '/block/[height]', query: { height: String(data.block_number_balance_updated_at) } }) }
display="flex" display="flex"
alignItems="center" alignItems="center"
> >
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 }/> <Box mr={ 2 }>
{ data.block_number_balance_updated_at } <Icon as={ blockIcon } boxSize={ 6 } isLoading={ addressQuery.isPlaceholderData }/>
</Box>
<Skeleton isLoaded={ !addressQuery.isPlaceholderData }>{ data.block_number_balance_updated_at }</Skeleton>
</LinkInternal> </LinkInternal>
</DetailsInfoItem> </DetailsInfoItem>
) } ) }
<DetailsSponsoredItem/> <DetailsSponsoredItem isLoading={ addressQuery.isPlaceholderData }/>
</Grid> </Grid>
</Box> </Box>
); );
......
...@@ -14,9 +14,10 @@ import TokenLogo from 'ui/shared/TokenLogo'; ...@@ -14,9 +14,10 @@ import TokenLogo from 'ui/shared/TokenLogo';
interface Props { interface Props {
data: Pick<Address, 'block_number_balance_updated_at' | 'coin_balance' | 'hash' | 'exchange_rate'>; data: Pick<Address, 'block_number_balance_updated_at' | 'coin_balance' | 'hash' | 'exchange_rate'>;
isLoading: boolean;
} }
const AddressBalance = ({ data }: Props) => { const AddressBalance = ({ data, isLoading }: Props) => {
const [ lastBlockNumber, setLastBlockNumber ] = React.useState<number>(data.block_number_balance_updated_at || 0); const [ lastBlockNumber, setLastBlockNumber ] = React.useState<number>(data.block_number_balance_updated_at || 0);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
...@@ -75,12 +76,14 @@ const AddressBalance = ({ data }: Props) => { ...@@ -75,12 +76,14 @@ const AddressBalance = ({ data }: Props) => {
hint={ `Address balance in ${ appConfig.network.currency.symbol }. Doesn't include ERC20, ERC721 and ERC1155 tokens` } hint={ `Address balance in ${ appConfig.network.currency.symbol }. Doesn't include ERC20, ERC721 and ERC1155 tokens` }
flexWrap="nowrap" flexWrap="nowrap"
alignItems="flex-start" alignItems="flex-start"
isLoading={ isLoading }
> >
<TokenLogo <TokenLogo
data={ tokenData } data={ tokenData }
boxSize={ 5 } boxSize={ 5 }
mr={ 2 } mr={ 2 }
fontSize="sm" fontSize="sm"
isLoading={ isLoading }
/> />
<CurrencyValue <CurrencyValue
value={ data.coin_balance || '0' } value={ data.coin_balance || '0' }
...@@ -90,6 +93,7 @@ const AddressBalance = ({ data }: Props) => { ...@@ -90,6 +93,7 @@ const AddressBalance = ({ data }: Props) => {
accuracyUsd={ 2 } accuracyUsd={ 2 }
accuracy={ 8 } accuracy={ 8 }
flexWrap="wrap" flexWrap="wrap"
isLoading={ isLoading }
/> />
</DetailsInfoItem> </DetailsInfoItem>
); );
......
...@@ -13,6 +13,7 @@ interface Props { ...@@ -13,6 +13,7 @@ interface Props {
query: UseQueryResult<AddressCounters>; query: UseQueryResult<AddressCounters>;
address: string; address: string;
onClick: () => void; onClick: () => void;
isAddressQueryLoading: boolean;
} }
const PROP_TO_TAB = { const PROP_TO_TAB = {
...@@ -21,8 +22,8 @@ const PROP_TO_TAB = { ...@@ -21,8 +22,8 @@ const PROP_TO_TAB = {
validations_count: 'blocks_validated', validations_count: 'blocks_validated',
}; };
const AddressCounterItem = ({ prop, query, address, onClick }: Props) => { const AddressCounterItem = ({ prop, query, address, onClick, isAddressQueryLoading }: Props) => {
if (query.isLoading) { if (query.isPlaceholderData || isAddressQueryLoading) {
return <Skeleton h={ 5 } w="80px" borderRadius="full"/>; return <Skeleton h={ 5 } w="80px" borderRadius="full"/>;
} }
......
import { Box, Flex, Grid, Skeleton, SkeletonCircle } from '@chakra-ui/react';
import React from 'react';
import DetailsSkeletonRow from 'ui/shared/skeletons/DetailsSkeletonRow';
const AddressDetailsSkeleton = () => {
return (
<Box>
<Flex align="center">
<SkeletonCircle boxSize={ 6 } flexShrink={ 0 }/>
<Skeleton h={ 6 } w={{ base: '100px', lg: '420px' }} ml={ 2 } borderRadius="full"/>
<Skeleton h={ 8 } w="36px" ml={ 3 } flexShrink={ 0 }/>
<Skeleton h={ 8 } w="36px" ml={ 3 } flexShrink={ 0 }/>
</Flex>
<Flex align="center" columnGap={ 4 } mt={ 8 }>
<Skeleton h={ 6 } w="200px" borderRadius="full"/>
<Skeleton h={ 6 } w="80px" borderRadius="full"/>
</Flex>
<Grid columnGap={ 8 } rowGap={{ base: 5, lg: 7 }} templateColumns={{ base: '1fr', lg: '150px 1fr' }} maxW="1000px" mt={ 8 }>
<DetailsSkeletonRow w="30%"/>
<DetailsSkeletonRow w="30%"/>
<DetailsSkeletonRow w="10%"/>
<DetailsSkeletonRow w="10%"/>
<DetailsSkeletonRow w="20%"/>
<DetailsSkeletonRow w="20%"/>
</Grid>
</Box>
);
};
export default AddressDetailsSkeleton;
import { Skeleton } from '@chakra-ui/react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import React from 'react'; import React from 'react';
...@@ -9,19 +10,23 @@ import LinkInternal from 'ui/shared/LinkInternal'; ...@@ -9,19 +10,23 @@ import LinkInternal from 'ui/shared/LinkInternal';
interface Props { interface Props {
data: Pick<Address, 'name' | 'token' | 'is_contract'>; data: Pick<Address, 'name' | 'token' | 'is_contract'>;
isLoading: boolean;
} }
const AddressNameInfo = ({ data }: Props) => { const AddressNameInfo = ({ data, isLoading }: Props) => {
if (data.token) { if (data.token) {
const symbol = data.token.symbol ? ` (${ trimTokenSymbol(data.token.symbol) })` : ''; const symbol = data.token.symbol ? ` (${ trimTokenSymbol(data.token.symbol) })` : '';
return ( return (
<DetailsInfoItem <DetailsInfoItem
title="Token name" title="Token name"
hint="Token name and symbol" hint="Token name and symbol"
isLoading={ isLoading }
> >
<LinkInternal href={ route({ pathname: '/token/[hash]', query: { hash: data.token.address } }) }> <Skeleton isLoaded={ !isLoading }>
{ data.token.name || 'Unnamed token' }{ symbol } <LinkInternal href={ route({ pathname: '/token/[hash]', query: { hash: data.token.address } }) }>
</LinkInternal> { data.token.name || 'Unnamed token' }{ symbol }
</LinkInternal>
</Skeleton>
</DetailsInfoItem> </DetailsInfoItem>
); );
} }
...@@ -31,8 +36,11 @@ const AddressNameInfo = ({ data }: Props) => { ...@@ -31,8 +36,11 @@ const AddressNameInfo = ({ data }: Props) => {
<DetailsInfoItem <DetailsInfoItem
title="Contract name" title="Contract name"
hint="The name found in the source code of the Contract" hint="The name found in the source code of the Contract"
isLoading={ isLoading }
> >
{ data.name } <Skeleton isLoaded={ !isLoading }>
{ data.name }
</Skeleton>
</DetailsInfoItem> </DetailsInfoItem>
); );
} }
...@@ -42,8 +50,11 @@ const AddressNameInfo = ({ data }: Props) => { ...@@ -42,8 +50,11 @@ const AddressNameInfo = ({ data }: Props) => {
<DetailsInfoItem <DetailsInfoItem
title="Validator name" title="Validator name"
hint="The name of the validator" hint="The name of the validator"
isLoading={ isLoading }
> >
{ data.name } <Skeleton isLoaded={ !isLoading }>
{ data.name }
</Skeleton>
</DetailsInfoItem> </DetailsInfoItem>
); );
} }
......
...@@ -67,7 +67,12 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -67,7 +67,12 @@ const TokenSelect = ({ onClick }: Props) => {
}); });
if (isLoading) { if (isLoading) {
return <Skeleton h={ 8 } w="160px"/>; return (
<Flex columnGap={ 3 }>
<Skeleton h={ 8 } w="150px" borderRadius="base"/>
<Skeleton h={ 8 } w={ 9 } borderRadius="base"/>
</Flex>
);
} }
const hasTokens = _sumBy(Object.values(data), ({ items }) => items.length) > 0; const hasTokens = _sumBy(Object.values(data), ({ items }) => items.length) > 0;
......
...@@ -12,6 +12,7 @@ import { useAppContext } from 'lib/appContext'; ...@@ -12,6 +12,7 @@ import { useAppContext } from 'lib/appContext';
import useContractTabs from 'lib/hooks/useContractTabs'; import useContractTabs from 'lib/hooks/useContractTabs';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import { ADDRESS_INFO } from 'stubs/address';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated'; import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance'; import AddressCoinBalance from 'ui/address/AddressCoinBalance';
import AddressContract from 'ui/address/AddressContract'; import AddressContract from 'ui/address/AddressContract';
...@@ -25,7 +26,6 @@ import AddressWithdrawals from 'ui/address/AddressWithdrawals'; ...@@ -25,7 +26,6 @@ import AddressWithdrawals from 'ui/address/AddressWithdrawals';
import TextAd from 'ui/shared/ad/TextAd'; import TextAd from 'ui/shared/ad/TextAd';
import EntityTags from 'ui/shared/EntityTags'; import EntityTags from 'ui/shared/EntityTags';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import SkeletonTabs from 'ui/shared/skeletons/SkeletonTabs'; import SkeletonTabs from 'ui/shared/skeletons/SkeletonTabs';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs'; import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
...@@ -48,7 +48,10 @@ const AddressPageContent = () => { ...@@ -48,7 +48,10 @@ const AddressPageContent = () => {
const addressQuery = useApiQuery('address', { const addressQuery = useApiQuery('address', {
pathParams: { hash }, pathParams: { hash },
queryOptions: { enabled: Boolean(hash) }, queryOptions: {
enabled: Boolean(hash),
placeholderData: ADDRESS_INFO,
},
}); });
const contractTabs = useContractTabs(addressQuery.data); const contractTabs = useContractTabs(addressQuery.data);
...@@ -120,23 +123,20 @@ const AddressPageContent = () => { ...@@ -120,23 +123,20 @@ const AddressPageContent = () => {
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
return ( return (
<Page> <>
{ addressQuery.isLoading ? <Skeleton h={{ base: 12, lg: 6 }} mb={ 6 } w="100%" maxW="680px"/> : <TextAd mb={ 6 }/> } { addressQuery.isPlaceholderData ? <Skeleton h={{ base: 12, lg: 6 }} mb={ 6 } w="100%" maxW="680px"/> : <TextAd mb={ 6 }/> }
{ addressQuery.isLoading ? ( <PageTitle
<Skeleton h={ 10 } w="260px" mb={ 6 }/> title={ `${ addressQuery.data?.is_contract ? 'Contract' : 'Address' } details` }
) : ( backLink={ backLink }
<PageTitle contentAfter={ tags }
title={ `${ addressQuery.data?.is_contract ? 'Contract' : 'Address' } details` } isLoading={ addressQuery.isPlaceholderData }
backLink={ backLink } />
contentAfter={ tags }
/>
) }
<AddressDetails addressQuery={ addressQuery } scrollRef={ tabsScrollRef }/> <AddressDetails addressQuery={ addressQuery } scrollRef={ tabsScrollRef }/>
{ /* should stay before tabs to scroll up with pagination */ } { /* should stay before tabs to scroll up with pagination */ }
<Box ref={ tabsScrollRef }></Box> <Box ref={ tabsScrollRef }></Box>
{ addressQuery.isLoading ? <SkeletonTabs/> : content } { addressQuery.isPlaceholderData ? <SkeletonTabs tabs={ tabs }/> : content }
{ !addressQuery.isLoading && !addressQuery.isError && <Box h={{ base: 0, lg: '40vh' }}/> } { !addressQuery.isPlaceholderData && !addressQuery.isError && <Box h={{ base: 0, lg: '40vh' }}/> }
</Page> </>
); );
}; };
......
...@@ -64,7 +64,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa ...@@ -64,7 +64,7 @@ const PageTitle = ({ title, contentAfter, withTextAd, backLink, className, isLoa
{ beforeTitle } { beforeTitle }
<Skeleton <Skeleton
isLoaded={ !isLoading } isLoaded={ !isLoading }
display="inline" display={ isLoading ? 'inline-block' : 'inline' }
verticalAlign={ isLoading ? 'super' : undefined } verticalAlign={ isLoading ? 'super' : undefined }
> >
<Heading <Heading
......
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