mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
skeleton for token inventory
This commit is contained in:
+26
-1
@@ -1,4 +1,4 @@
|
||||
import type { TokenCounters, TokenHolder, TokenInfo, TokenType } from 'types/api/token';
|
||||
import type { TokenCounters, TokenHolder, TokenHolders, TokenInfo, TokenInstance, TokenInventoryResponse, TokenType } from 'types/api/token';
|
||||
import type { TokenTransfer, TokenTransferResponse } from 'types/api/tokenTransfer';
|
||||
|
||||
const ADDRESS_PARAMS = {
|
||||
@@ -43,6 +43,8 @@ export const TOKEN_HOLDER: TokenHolder = {
|
||||
value: '1021378038331138520668',
|
||||
};
|
||||
|
||||
export const TOKEN_HOLDERS: TokenHolders = { items: Array(50).fill(TOKEN_HOLDER), next_page_params: null };
|
||||
|
||||
export const TOKEN_TRANSFER_ERC_20: TokenTransfer = {
|
||||
block_hash: '0x8fa7b9e5e5e79deeb62d608db22ba9a5cb45388c7ebb9223ae77331c6080dc70',
|
||||
from: ADDRESS_PARAMS,
|
||||
@@ -87,3 +89,26 @@ export const getTokenTransfersStub = (type?: TokenType): TokenTransferResponse =
|
||||
return { items: Array(50).fill(TOKEN_TRANSFER_ERC_20), next_page_params: null };
|
||||
}
|
||||
};
|
||||
|
||||
export const TOKEN_INSTANCE: TokenInstance = {
|
||||
animation_url: null,
|
||||
external_app_url: 'https://vipsland.com/nft/collections/genesis/188882',
|
||||
id: '188882',
|
||||
image_url: 'https://ipfs.vipsland.com/nft/collections/genesis/188882.gif',
|
||||
is_unique: true,
|
||||
metadata: {
|
||||
attributes: Array(3).fill({ trait_type: 'skin', value: '6' }),
|
||||
description: '**GENESIS #188882**, **8a77ca1bcaa4036f** :: *844th* generation of *#57806 and #57809* :: **eGenetic Hash Code (eDNA)** = *2822355e953a462d*',
|
||||
external_url: 'https://vipsland.com/nft/collections/genesis/188882',
|
||||
image: 'https://ipfs.vipsland.com/nft/collections/genesis/188882.gif',
|
||||
name: 'GENESIS #188882, 8a77ca1bcaa4036f. Blockchain pixel PFP NFT + "on music video" trait inspired by God',
|
||||
},
|
||||
owner: ADDRESS_PARAMS,
|
||||
token: TOKEN_INFO_ERC_1155,
|
||||
holder_address_hash: '0x2B51Ae4412F79c3c1cB12AA40Ea4ECEb4e80511a',
|
||||
};
|
||||
|
||||
export const TOKEN_INSTANCES: TokenInventoryResponse = {
|
||||
items: Array(50).fill(TOKEN_INSTANCE),
|
||||
next_page_params: null,
|
||||
};
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ export interface TokenInstanceTransfersCount {
|
||||
|
||||
export interface TokenInventoryResponse {
|
||||
items: Array<TokenInstance>;
|
||||
next_page_params: TokenInventoryPagination;
|
||||
next_page_params: TokenInventoryPagination | null;
|
||||
}
|
||||
|
||||
export type TokenInventoryPagination = {
|
||||
|
||||
+2
-1
@@ -76,7 +76,7 @@ const TokenPageContent = () => {
|
||||
scrollRef,
|
||||
options: {
|
||||
enabled: Boolean(router.query.hash && router.query.tab === 'holders' && tokenQuery.data),
|
||||
placeholderData: { items: Array(50).fill(stubs.TOKEN_HOLDER), next_page_params: null },
|
||||
placeholderData: stubs.TOKEN_HOLDERS,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -86,6 +86,7 @@ const TokenPageContent = () => {
|
||||
scrollRef,
|
||||
options: {
|
||||
enabled: Boolean(router.query.hash && router.query.tab === 'inventory' && tokenQuery.data),
|
||||
placeholderData: stubs.TOKEN_INSTANCES,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -11,13 +11,14 @@ interface Props {
|
||||
imageUrl: string | null;
|
||||
animationUrl: string | null;
|
||||
className?: string;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const NftMedia = ({ imageUrl, animationUrl, className }: Props) => {
|
||||
const NftMedia = ({ imageUrl, animationUrl, className, isLoading }: Props) => {
|
||||
const [ type, setType ] = React.useState<MediaType | undefined>(!animationUrl ? 'image' : undefined);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!animationUrl) {
|
||||
if (!animationUrl || isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,9 +46,9 @@ const NftMedia = ({ imageUrl, animationUrl, className }: Props) => {
|
||||
setType('image');
|
||||
});
|
||||
|
||||
}, [ animationUrl ]);
|
||||
}, [ animationUrl, isLoading ]);
|
||||
|
||||
if (!type) {
|
||||
if (!type || isLoading) {
|
||||
return (
|
||||
<AspectRatio
|
||||
className={ className }
|
||||
|
||||
+10
-19
@@ -1,4 +1,4 @@
|
||||
import { Grid, Skeleton } from '@chakra-ui/react';
|
||||
import { Grid } from '@chakra-ui/react';
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
@@ -28,21 +28,6 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
|
||||
</ActionBar>
|
||||
);
|
||||
|
||||
const skeleton = (
|
||||
<Grid
|
||||
w="100%"
|
||||
columnGap={{ base: 3, lg: 6 }}
|
||||
rowGap={{ base: 3, lg: 6 }}
|
||||
gridTemplateColumns={{ base: 'repeat(2, calc((100% - 12px)/2))', lg: 'repeat(auto-fill, minmax(210px, 1fr))' }}
|
||||
>
|
||||
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
|
||||
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
|
||||
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
|
||||
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
|
||||
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
const items = inventoryQuery.data?.items;
|
||||
|
||||
const content = items ? (
|
||||
@@ -52,19 +37,25 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
|
||||
rowGap={{ base: 3, lg: 6 }}
|
||||
gridTemplateColumns={{ base: 'repeat(2, calc((100% - 12px)/2))', lg: 'repeat(auto-fill, minmax(210px, 1fr))' }}
|
||||
>
|
||||
{ items.map((item) => <TokenInventoryItem key={ item.token.address + '_' + item.id } item={ item }/>) }
|
||||
{ items.map((item, index) => (
|
||||
<TokenInventoryItem
|
||||
key={ item.token.address + '_' + item.id + (inventoryQuery.isPlaceholderData ? '_' + index : '') }
|
||||
item={ item }
|
||||
isLoading={ inventoryQuery.isPlaceholderData }
|
||||
/>
|
||||
)) }
|
||||
</Grid>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<DataListDisplay
|
||||
isError={ inventoryQuery.isError }
|
||||
isLoading={ inventoryQuery.isLoading }
|
||||
isLoading={ false }
|
||||
items={ items }
|
||||
emptyText="There are no tokens."
|
||||
content={ content }
|
||||
actionBar={ actionBar }
|
||||
skeletonProps={{ customSkeleton: skeleton }}
|
||||
skeletonProps={{ customSkeleton: null }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Flex, Text, LinkBox, LinkOverlay, useColorModeValue, Hide } from '@chakra-ui/react';
|
||||
import { Flex, Text, LinkBox, LinkOverlay, useColorModeValue, Hide, Skeleton } from '@chakra-ui/react';
|
||||
import NextLink from 'next/link';
|
||||
import React from 'react';
|
||||
|
||||
@@ -11,9 +11,9 @@ import LinkInternal from 'ui/shared/LinkInternal';
|
||||
import NftMedia from 'ui/shared/nft/NftMedia';
|
||||
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
|
||||
|
||||
type Props = { item: TokenInstance };
|
||||
type Props = { item: TokenInstance; isLoading: boolean };
|
||||
|
||||
const NFTItem = ({ item }: Props) => {
|
||||
const NFTItem = ({ item, isLoading }: Props) => {
|
||||
return (
|
||||
<LinkBox
|
||||
w={{ base: '100%', lg: '210px' }}
|
||||
@@ -32,6 +32,7 @@ const NFTItem = ({ item }: Props) => {
|
||||
mb="18px"
|
||||
imageUrl={ item.image_url }
|
||||
animationUrl={ item.animation_url }
|
||||
isLoading={ isLoading }
|
||||
/>
|
||||
</LinkOverlay>
|
||||
</NextLink>
|
||||
@@ -44,7 +45,9 @@ const NFTItem = ({ item }: Props) => {
|
||||
whiteSpace="nowrap"
|
||||
textOverflow="ellipsis"
|
||||
>
|
||||
{ item.id }
|
||||
<Skeleton isLoaded={ !isLoading }>
|
||||
{ item.id }
|
||||
</Skeleton>
|
||||
</LinkInternal>
|
||||
</TruncatedTextTooltip>
|
||||
</Flex>
|
||||
@@ -53,8 +56,8 @@ const NFTItem = ({ item }: Props) => {
|
||||
<Flex mb={ 2 } ml={ 1 }>
|
||||
<Text whiteSpace="pre" variant="secondary" mr={ 2 } lineHeight="24px">Owner</Text>
|
||||
<Address>
|
||||
<Hide below="lg" ssr={ false }><AddressIcon address={ item.owner } mr={ 1 }/></Hide>
|
||||
<AddressLink hash={ item.owner.hash } alias={ item.owner.name } type="address" truncation="constant"/>
|
||||
<Hide below="lg" ssr={ false }><AddressIcon address={ item.owner } mr={ 1 } isLoading={ isLoading }/></Hide>
|
||||
<AddressLink hash={ item.owner.hash } alias={ item.owner.name } type="address" truncation="constant" isLoading={ isLoading }/>
|
||||
</Address>
|
||||
</Flex>
|
||||
) }
|
||||
|
||||
Reference in New Issue
Block a user