import { Box, HStack } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import React from 'react'; import type { PaginationParams } from 'ui/shared/pagination/types'; import config from 'configs/app'; import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMounted from 'lib/hooks/useIsMounted'; import getQueryParamString from 'lib/router/getQueryParamString'; import { ADDRESS_TOKEN_BALANCE_ERC_20 } from 'stubs/address'; import { generateListStub } from 'stubs/utils'; import RoutedTabs from 'toolkit/components/RoutedTabs/RoutedTabs'; import Pagination from 'ui/shared/pagination/Pagination'; import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages'; import AddressCollections from './tokens/AddressCollections'; import AddressNftDisplayTypeRadio from './tokens/AddressNftDisplayTypeRadio'; import AddressNFTs from './tokens/AddressNFTs'; import AddressNftTypeFilter from './tokens/AddressNftTypeFilter'; import ERC20Tokens from './tokens/ERC20Tokens'; import TokenBalances from './tokens/TokenBalances'; import useAddressNftQuery from './tokens/useAddressNftQuery'; const TAB_LIST_PROPS = { mt: 1, mb: { base: 6, lg: 1 }, py: 5, }; const TAB_LIST_PROPS_MOBILE = { my: 8, }; type Props = { shouldRender?: boolean; isQueryEnabled?: boolean; }; const AddressTokens = ({ shouldRender = true, isQueryEnabled = true }: Props) => { const router = useRouter(); const isMobile = useIsMobile(); const isMounted = useIsMounted(); const scrollRef = React.useRef(null); const tab = getQueryParamString(router.query.tab); const hash = getQueryParamString(router.query.hash); // on address details we have tokens requests for all token types, separately // react query can behave unexpectedly, when it already has data for ERC-20 (string type) // and we fetch it again with the array type // so if it's just one token type, we heed to keep it a string for queries compatibility const tokenTypesFilter = config.chain.additionalTokenTypes.length > 0 ? [ 'ERC-20', ...config.chain.additionalTokenTypes.map(item => item.id) ] : 'ERC-20'; const erc20Query = useQueryWithPages({ resourceName: 'general:address_tokens', pathParams: { hash }, filters: { type: tokenTypesFilter }, scrollRef, options: { enabled: isQueryEnabled && (tab === 'tokens' || tab === 'tokens_erc20'), refetchOnMount: false, placeholderData: generateListStub<'general:address_tokens'>(ADDRESS_TOKEN_BALANCE_ERC_20, 10, { next_page_params: null }), }, }); const { nftsQuery, collectionsQuery, displayType: nftDisplayType, tokenTypes: nftTokenTypes, onDisplayTypeChange, onTokenTypesChange } = useAddressNftQuery({ scrollRef, enabled: isQueryEnabled && tab === 'tokens_nfts', addressHash: hash, }); if (!isMounted || !shouldRender) { return null; } const hasActiveFilters = Boolean(nftTokenTypes?.length); const tabs = [ { id: 'tokens_erc20', title: [ `${ config.chain.tokenStandard }-20`, ...config.chain.additionalTokenTypes.map((item) => item.name), ].join(' & '), component: ( ), }, { id: 'tokens_nfts', title: 'NFTs', component: nftDisplayType === 'list' ? : , }, ]; let pagination: PaginationParams | undefined; if (tab === 'tokens_nfts') { pagination = nftDisplayType === 'list' ? nftsQuery.pagination : collectionsQuery.pagination; } else { pagination = erc20Query.pagination; } const hasNftData = (!nftsQuery.isPlaceholderData && nftsQuery.data?.items.length) || (!collectionsQuery.isPlaceholderData && collectionsQuery.data?.items.length); const isNftTab = tab !== 'tokens' && tab !== 'tokens_erc20'; const rightSlot = ( <> { isNftTab && (hasNftData || hasActiveFilters) && } { isNftTab && (hasNftData || hasActiveFilters) && !(isMobile && pagination.isVisible) && } { pagination.isVisible && !isMobile && } ); return ( <> { /* should stay before tabs to scroll up with pagination */ } ); }; export default AddressTokens;