Commit 4c61233e authored by tom's avatar tom

custom tab set based on address tab

parent b8575a7a
import { Box, Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react'; import { Box, Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import type { UseQueryResult } from '@tanstack/react-query'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Address, AddressBlocksValidatedResponse } from 'types/api/address'; import type { AddressBlocksValidatedResponse } from 'types/api/address';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
...@@ -22,20 +22,15 @@ import { default as Thead } from 'ui/shared/TheadSticky'; ...@@ -22,20 +22,15 @@ import { default as Thead } from 'ui/shared/TheadSticky';
import AddressBlocksValidatedListItem from './blocksValidated/AddressBlocksValidatedListItem'; import AddressBlocksValidatedListItem from './blocksValidated/AddressBlocksValidatedListItem';
import AddressBlocksValidatedTableItem from './blocksValidated/AddressBlocksValidatedTableItem'; import AddressBlocksValidatedTableItem from './blocksValidated/AddressBlocksValidatedTableItem';
interface Props { const AddressBlocksValidated = () => {
addressQuery: UseQueryResult<Address>;
}
const AddressBlocksValidated = ({ addressQuery }: Props) => {
const [ socketAlert, setSocketAlert ] = React.useState(false); const [ socketAlert, setSocketAlert ] = React.useState(false);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const router = useRouter();
const addressHash = String(router.query?.id);
const query = useQueryWithPages({ const query = useQueryWithPages({
resourceName: 'address_blocks_validated', resourceName: 'address_blocks_validated',
pathParams: { id: addressQuery.data?.hash }, pathParams: { id: addressHash },
options: {
enabled: Boolean(addressQuery.data),
},
}); });
const handleSocketError = React.useCallback(() => { const handleSocketError = React.useCallback(() => {
...@@ -46,7 +41,7 @@ const AddressBlocksValidated = ({ addressQuery }: Props) => { ...@@ -46,7 +41,7 @@ const AddressBlocksValidated = ({ addressQuery }: Props) => {
setSocketAlert(false); setSocketAlert(false);
queryClient.setQueryData( queryClient.setQueryData(
getResourceKey('address_blocks_validated', { pathParams: { id: addressQuery.data?.hash } }), getResourceKey('address_blocks_validated', { pathParams: { id: addressHash } }),
(prevData: AddressBlocksValidatedResponse | undefined) => { (prevData: AddressBlocksValidatedResponse | undefined) => {
if (!prevData) { if (!prevData) {
return; return;
...@@ -57,13 +52,13 @@ const AddressBlocksValidated = ({ addressQuery }: Props) => { ...@@ -57,13 +52,13 @@ const AddressBlocksValidated = ({ addressQuery }: Props) => {
items: [ payload.block, ...prevData.items ], items: [ payload.block, ...prevData.items ],
}; };
}); });
}, [ addressQuery.data?.hash, queryClient ]); }, [ addressHash, queryClient ]);
const channel = useSocketChannel({ const channel = useSocketChannel({
topic: `blocks:${ addressQuery.data?.hash.toLowerCase() }`, topic: `blocks:${ addressHash.toLowerCase() }`,
onSocketClose: handleSocketError, onSocketClose: handleSocketError,
onSocketError: handleSocketError, onSocketError: handleSocketError,
isDisabled: addressQuery.isLoading || addressQuery.isError || !addressQuery.data.hash || query.pagination.page !== 1, isDisabled: !addressHash || query.pagination.page !== 1,
}); });
useSocketMessage({ useSocketMessage({
channel, channel,
......
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import type { UseQueryResult } from '@tanstack/react-query'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { Address, AddressCoinBalanceHistoryResponse } from 'types/api/address'; import type { AddressCoinBalanceHistoryResponse } from 'types/api/address';
import { getResourceKey } from 'lib/api/useApiQuery'; import { getResourceKey } from 'lib/api/useApiQuery';
import useQueryWithPages from 'lib/hooks/useQueryWithPages'; import useQueryWithPages from 'lib/hooks/useQueryWithPages';
...@@ -14,20 +14,15 @@ import SocketAlert from 'ui/shared/SocketAlert'; ...@@ -14,20 +14,15 @@ import SocketAlert from 'ui/shared/SocketAlert';
import AddressCoinBalanceChart from './coinBalance/AddressCoinBalanceChart'; import AddressCoinBalanceChart from './coinBalance/AddressCoinBalanceChart';
import AddressCoinBalanceHistory from './coinBalance/AddressCoinBalanceHistory'; import AddressCoinBalanceHistory from './coinBalance/AddressCoinBalanceHistory';
interface Props { const AddressCoinBalance = () => {
addressQuery: UseQueryResult<Address>;
}
const AddressCoinBalance = ({ addressQuery }: Props) => {
const [ socketAlert, setSocketAlert ] = React.useState(false); const [ socketAlert, setSocketAlert ] = React.useState(false);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const router = useRouter();
const addressHash = String(router.query?.id);
const coinBalanceQuery = useQueryWithPages({ const coinBalanceQuery = useQueryWithPages({
resourceName: 'address_coin_balance', resourceName: 'address_coin_balance',
pathParams: { id: addressQuery.data?.hash }, pathParams: { id: addressHash },
options: {
enabled: Boolean(addressQuery.data),
},
}); });
const handleSocketError = React.useCallback(() => { const handleSocketError = React.useCallback(() => {
...@@ -38,7 +33,7 @@ const AddressCoinBalance = ({ addressQuery }: Props) => { ...@@ -38,7 +33,7 @@ const AddressCoinBalance = ({ addressQuery }: Props) => {
setSocketAlert(false); setSocketAlert(false);
queryClient.setQueryData( queryClient.setQueryData(
getResourceKey('address_coin_balance', { pathParams: { id: addressQuery.data?.hash } }), getResourceKey('address_coin_balance', { pathParams: { id: addressHash } }),
(prevData: AddressCoinBalanceHistoryResponse | undefined) => { (prevData: AddressCoinBalanceHistoryResponse | undefined) => {
if (!prevData) { if (!prevData) {
return; return;
...@@ -52,13 +47,13 @@ const AddressCoinBalance = ({ addressQuery }: Props) => { ...@@ -52,13 +47,13 @@ const AddressCoinBalance = ({ addressQuery }: Props) => {
], ],
}; };
}); });
}, [ addressQuery.data?.hash, queryClient ]); }, [ addressHash, queryClient ]);
const channel = useSocketChannel({ const channel = useSocketChannel({
topic: `addresses:${ addressQuery.data?.hash.toLowerCase() }`, topic: `addresses:${ addressHash.toLowerCase() }`,
onSocketClose: handleSocketError, onSocketClose: handleSocketError,
onSocketError: handleSocketError, onSocketError: handleSocketError,
isDisabled: addressQuery.isLoading || addressQuery.isError || !addressQuery.data.hash || coinBalanceQuery.pagination.page !== 1, isDisabled: !addressHash || coinBalanceQuery.pagination.page !== 1,
}); });
useSocketMessage({ useSocketMessage({
channel, channel,
...@@ -69,7 +64,7 @@ const AddressCoinBalance = ({ addressQuery }: Props) => { ...@@ -69,7 +64,7 @@ const AddressCoinBalance = ({ addressQuery }: Props) => {
return ( return (
<> <>
{ socketAlert && <SocketAlert mb={ 6 }/> } { socketAlert && <SocketAlert mb={ 6 }/> }
<AddressCoinBalanceChart addressQuery={ addressQuery }/> <AddressCoinBalanceChart addressHash={ addressHash }/>
<AddressCoinBalanceHistory query={ coinBalanceQuery }/> <AddressCoinBalanceHistory query={ coinBalanceQuery }/>
</> </>
); );
......
import type { UseQueryResult } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { Address } from 'types/api/address';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import ChartWidget from 'ui/shared/chart/ChartWidget'; import ChartWidget from 'ui/shared/chart/ChartWidget';
interface Props { interface Props {
addressQuery: UseQueryResult<Address>; addressHash: string;
} }
const AddressCoinBalanceChart = ({ addressQuery }: Props) => { const AddressCoinBalanceChart = ({ addressHash }: Props) => {
const { data, isLoading, isError } = useApiQuery('address_coin_balance_chart', { const { data, isLoading, isError } = useApiQuery('address_coin_balance_chart', {
pathParams: { id: addressQuery.data?.hash }, pathParams: { id: addressHash },
queryOptions: { enabled: Boolean(addressQuery.data?.hash) },
}); });
const items = React.useMemo(() => data?.map(({ date, value }) => ({ const items = React.useMemo(() => data?.map(({ date, value }) => ({
......
import { Box } from '@chakra-ui/react';
import React from 'react';
const AddressLogs = () => {
return <Box>FOO BAR</Box>;
};
export default AddressLogs;
...@@ -5,15 +5,18 @@ import React from 'react'; ...@@ -5,15 +5,18 @@ import React from 'react';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types'; import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import notEmpty from 'lib/notEmpty';
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 AddressDetails from 'ui/address/AddressDetails'; import AddressDetails from 'ui/address/AddressDetails';
import AddressInternalTxs from 'ui/address/AddressInternalTxs'; import AddressInternalTxs from 'ui/address/AddressInternalTxs';
import AddressTokenTransfers from 'ui/address/AddressTokenTransfers'; import AddressTokenTransfers from 'ui/address/AddressTokenTransfers';
import AddressTxs from 'ui/address/AddressTxs'; import AddressTxs from 'ui/address/AddressTxs';
import AddressLogs from 'ui/address/logs/AddressLogs';
import Page from 'ui/shared/Page/Page'; import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs'; import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
import SkeletonTabs from 'ui/shared/skeletons/SkeletonTabs';
const AddressPageContent = () => { const AddressPageContent = () => {
const router = useRouter(); const router = useRouter();
...@@ -29,16 +32,21 @@ const AddressPageContent = () => { ...@@ -29,16 +32,21 @@ const AddressPageContent = () => {
...(addressQuery.data?.watchlist_names || []), ...(addressQuery.data?.watchlist_names || []),
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>); ].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
const tabs: Array<RoutedTab> = [ const isContract = addressQuery.data?.is_contract;
{ id: 'txs', title: 'Transactions', component: <AddressTxs/> },
{ id: 'token_transfers', title: 'Token transfers', component: <AddressTokenTransfers/> }, const tabs: Array<RoutedTab> = React.useMemo(() => {
{ id: 'tokens', title: 'Tokens', component: null }, return [
{ id: 'internal_txns', title: 'Internal txns', component: <AddressInternalTxs/> }, { id: 'txs', title: 'Transactions', component: <AddressTxs/> },
{ id: 'coin_balance_history', title: 'Coin balance history', component: <AddressCoinBalance addressQuery={ addressQuery }/> }, { id: 'token_transfers', title: 'Token transfers', component: <AddressTokenTransfers/> },
// temporary show this tab in all address { id: 'tokens', title: 'Tokens', component: null },
// later api will return info about available tabs { id: 'internal_txns', title: 'Internal txns', component: <AddressInternalTxs/> },
{ id: 'blocks_validated', title: 'Blocks validated', component: <AddressBlocksValidated addressQuery={ addressQuery }/> }, { id: 'coin_balance_history', title: 'Coin balance history', component: <AddressCoinBalance/> },
]; // temporary show this tab in all address
// later api will return info about available tabs
{ id: 'blocks_validated', title: 'Blocks validated', component: <AddressBlocksValidated/> },
isContract ? { id: 'logs', title: 'Logs', component: <AddressLogs/> } : undefined,
].filter(notEmpty);
}, [ isContract ]);
return ( return (
<Page> <Page>
...@@ -51,7 +59,7 @@ const AddressPageContent = () => { ...@@ -51,7 +59,7 @@ const AddressPageContent = () => {
) } ) }
</Flex> </Flex>
<AddressDetails addressQuery={ addressQuery }/> <AddressDetails addressQuery={ addressQuery }/>
<RoutedTabs tabs={ tabs } tabListProps={{ mt: 8 }}/> { addressQuery.isLoading ? <SkeletonTabs/> : <RoutedTabs tabs={ tabs } tabListProps={{ mt: 8 }}/> }
</Page> </Page>
); );
}; };
......
import { Flex, Skeleton, chakra } from '@chakra-ui/react';
import React from 'react';
interface Props {
className?: string;
}
const SkeletonTabs = ({ className }: Props) => {
return (
<Flex my={ 8 } className={ className }>
<Skeleton h={ 6 } my={ 2 } mx={ 4 } w="100px"/>
<Skeleton h={ 6 } my={ 2 } mx={ 4 } w="120px"/>
<Skeleton h={ 6 } my={ 2 } mx={ 4 } w="80px" display={{ base: 'none', lg: 'block' }}/>
<Skeleton h={ 6 } my={ 2 } mx={ 4 } w="100px" display={{ base: 'none', lg: 'block' }}/>
<Skeleton h={ 6 } my={ 2 } mx={ 4 } w="140px" display={{ base: 'none', lg: 'block' }}/>
</Flex>
);
};
export default chakra(SkeletonTabs);
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