Commit a3417b52 authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

Merge pull request #690 from blockscout/display

display list component
parents d5eb9cd0 e3de71bc
import { Box, Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import { Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import { useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -12,10 +12,8 @@ import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import SocketAlert from 'ui/shared/SocketAlert';
import { default as Thead } from 'ui/shared/TheadSticky';
......@@ -71,30 +69,9 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
handler: handleNewSocketMessage,
});
const content = (() => {
if (query.isLoading) {
return (
<>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '17%', '17%', '16%', '25%', '25%' ] } isLong/>
</Hide>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
);
}
if (query.isError) {
return <DataFetchAlert/>;
}
if (query.data.items.length === 0) {
return 'There is no validated blocks for this address';
}
return (
const content = query.data?.items ? (
<>
{ socketAlert && <SocketAlert mb={ 6 }/> }
<Hide below="lg" ssr={ false }>
<Table variant="simple" size="sm">
<Thead top={ query.isPaginationVisible ? 80 : 0 }>
......@@ -119,19 +96,24 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
)) }
</Show>
</>
);
})();
) : null;
return (
<Box>
{ query.isPaginationVisible && (
const actionBar = query.isPaginationVisible ? (
<ActionBar mt={ -6 } showShadow={ query.isLoading }>
<Pagination ml="auto" { ...query.pagination }/>
</ActionBar>
) }
{ socketAlert && <SocketAlert mb={ 6 }/> }
{ content }
</Box>
) : null;
return (
<DataListDisplay
isError={ query.isError }
isLoading={ query.isLoading }
items={ query.data?.items }
skeletonProps={{ isLongSkeleton: true, skeletonDesktopColumns: [ '17%', '17%', '16%', '25%', '25%' ] }}
emptyText="There are no validated blocks for this address."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Text, Show, Hide } from '@chakra-ui/react';
import { Show, Hide } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -10,12 +10,9 @@ import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { apos } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString';
import AddressIntTxsTable from 'ui/address/internals/AddressIntTxsTable';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import AddressCsvExportLink from './AddressCsvExportLink';
import AddressTxsFilter from './AddressTxsFilter';
......@@ -43,33 +40,7 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
onFilterChange({ filter: newVal });
}, [ onFilterChange ]);
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
if (isLoading) {
return (
<>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '15%', '15%', '10%', '20%', '20%', '20%' ] } isLong/>
</Hide>
</>
);
}
if (data.items.length === 0 && !filterValue) {
return <Text as="span">There are no internal transactions for this address.</Text>;
}
if (data.items.length === 0) {
return <EmptySearchResult text={ `Couldn${ apos }t find any transaction that matches your query.` }/>;
}
return (
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
<AddressIntTxsList data={ data.items } currentAddress={ hash }/>
......@@ -78,11 +49,9 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
<AddressIntTxsTable data={ data.items } currentAddress={ hash }/>
</Hide>
</>
);
})();
) : null ;
return (
<>
const actionBar = (
<ActionBar mt={ -6 } justifyContent="left" showShadow={ isLoading }>
<AddressTxsFilter
defaultFilter={ filterValue }
......@@ -92,8 +61,19 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
<AddressCsvExportLink address={ hash } type="internal-transactions" ml={{ base: 2, lg: 'auto' }}/>
{ isPaginationVisible && <Pagination ml={{ base: 'auto', lg: 8 }} { ...pagination }/> }
</ActionBar>
{ content }
</>
);
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ isLongSkeleton: true, skeletonDesktopColumns: [ '15%', '15%', '10%', '20%', '20%', '20%' ] }}
filterProps={{ emptyFilteredText: `Couldn${ apos }t find any transaction that matches your query.`, hasActiveFilters: Boolean(filterValue) }}
emptyText="There are no internal transactions for this address."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Box } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import getQueryParamString from 'lib/router/getQueryParamString';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import LogItem from 'ui/shared/logs/LogItem';
import LogSkeleton from 'ui/shared/logs/LogSkeleton';
import Pagination from 'ui/shared/Pagination';
......@@ -20,35 +19,26 @@ const AddressLogs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>
scrollRef,
});
if (isError) {
return <DataFetchAlert/>;
}
const bar = isPaginationVisible ? (
const actionBar = isPaginationVisible ? (
<ActionBar mt={ -6 } showShadow>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
) : null;
if (isLoading) {
return (
<Box>
{ bar }
<LogSkeleton/>
<LogSkeleton/>
</Box>
);
}
const content = data?.items ? data.items.map((item, index) => <LogItem key={ index } { ...item } type="address"/>) : null;
if (data.items.length === 0) {
return <span>There are no logs for this address.</span>;
}
const skeleton = <><LogSkeleton/><LogSkeleton/></>;
return (
<>
{ bar }
{ data.items.map((item, index) => <LogItem key={ index } { ...item } type="address"/>) }
</>
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
emptyText="There are no logs for this address."
content={ content }
actionBar={ actionBar }
skeletonProps={{ customSkeleton: skeleton }}
/>
);
};
......
......@@ -20,13 +20,10 @@ import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import TOKEN_TYPE from 'lib/token/tokenTypes';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import HashStringShorten from 'ui/shared/HashStringShorten';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import TokenLogo from 'ui/shared/TokenLogo';
import { flattenTotal } from 'ui/shared/TokenTransfer/helpers';
......@@ -164,34 +161,8 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
const numActiveFilters = (filters.type?.length || 0) + (filters.filter ? 1 : 0);
const isActionBarHidden = !tokenFilter && !numActiveFilters && !data?.items.length && !currentAddress;
const content = (() => {
if (isLoading) {
return (
<>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '44px', '185px', '160px', '25%', '25%', '25%', '25%' ] } isLong/>
</Hide>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
);
}
if (isError) {
return <DataFetchAlert/>;
}
if (!data.items?.length && !numActiveFilters) {
return <Text as="span">There are no token transfers</Text>;
}
if (!data.items?.length) {
return <EmptySearchResult text={ `Couldn${ apos }t find any token transfer that matches your query.` }/>;
}
const items = data.items.reduce(flattenTotal, []);
return (
const items = data?.items?.reduce(flattenTotal, []);
const content = items ? (
<>
<Hide below="lg" ssr={ false }>
<TokenTransferTable
......@@ -223,8 +194,7 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
/>
</Show>
</>
);
})();
) : null;
const tokenFilterComponent = tokenFilter && (
<Flex alignItems="center" flexWrap="wrap" mb={{ base: isActionBarHidden ? 3 : 6, lg: 0 }} mr={ 4 }>
......@@ -249,7 +219,7 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
</Flex>
);
return (
const actionBar = (
<>
{ isMobile && tokenFilterComponent }
{ !isActionBarHidden && (
......@@ -269,9 +239,27 @@ const AddressTokenTransfers = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLD
{ isPaginationVisible && <Pagination ml={{ base: 'auto', lg: 8 }} { ...pagination }/> }
</ActionBar>
) }
{ content }
</>
);
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{
isLongSkeleton: true,
skeletonDesktopColumns: [ '44px', '185px', '160px', '25%', '25%', '25%', '25%' ],
}}
emptyText="There are no token transfers."
filterProps={{
emptyFilteredText: `Couldn${ apos }t find any token transfer that matches your query.`,
hasActiveFilters: Boolean(numActiveFilters),
}}
content={ content }
actionBar={ actionBar }
/>
);
};
export default AddressTokenTransfers;
import { Box, Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import { Hide, Show, Table, Tbody, Th, Tr } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -6,11 +6,9 @@ import type { AddressCoinBalanceHistoryResponse } from 'types/api/address';
import appConfig from 'configs/app/config';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import { default as Thead } from 'ui/shared/TheadSticky';
import AddressCoinBalanceListItem from './AddressCoinBalanceListItem';
......@@ -25,29 +23,7 @@ interface Props {
const AddressCoinBalanceHistory = ({ query }: Props) => {
const content = (() => {
if (query.isLoading) {
return (
<>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '25%', '25%', '25%', '25%', '120px' ] }/>
</Hide>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
);
}
if (query.isError) {
return <DataFetchAlert/>;
}
if (query.data.items.length === 0 && !query.isPaginationVisible) {
return <span>There is no coin balance history for this address</span>;
}
return (
const content = query.data?.items ? (
<>
<Hide below="lg" ssr={ false }>
<Table variant="simple" size="sm">
......@@ -73,18 +49,25 @@ const AddressCoinBalanceHistory = ({ query }: Props) => {
)) }
</Show>
</>
);
})();
) : null;
return (
<Box mt={ 8 }>
{ query.isPaginationVisible && (
const actionBar = query.isPaginationVisible ? (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...query.pagination }/>
</ActionBar>
) }
{ content }
</Box>
) : null;
return (
<DataListDisplay
mt={ 8 }
isError={ query.isError }
isLoading={ query.isLoading }
items={ query.data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '25%', '25%', '25%', '25%', '120px' ] }}
emptyText="There is no coin balance history for this address."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Grid, Skeleton, Text } from '@chakra-ui/react';
import { Grid, Skeleton } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -6,7 +6,7 @@ import type { AddressTokensResponse } from 'types/api/address';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import Pagination from 'ui/shared/Pagination';
......@@ -24,20 +24,13 @@ const TokensWithIds = ({ tokensQuery }: Props) => {
const { isError, isLoading, data, pagination, isPaginationVisible } = tokensQuery;
if (isError) {
return <DataFetchAlert/>;
}
const bar = isMobile && isPaginationVisible && (
const actionBar = isMobile && isPaginationVisible && (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
);
if (isLoading) {
return (
<>
{ bar }
const skeleton = (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
......@@ -50,17 +43,9 @@ const TokensWithIds = ({ tokensQuery }: Props) => {
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
</Grid>
</>
);
}
if (!data.items.length) {
return <Text as="span">There are no tokens of selected type.</Text>;
}
return (
<>
{ bar }
const content = data?.items ? (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
......@@ -69,7 +54,18 @@ const TokensWithIds = ({ tokensQuery }: Props) => {
>
{ data.items.map(item => <NFTItem key={ item.token.address } { ...item }/>) }
</Grid>
</>
) : null;
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
emptyText="There are no tokens of selected type."
content={ content }
actionBar={ actionBar }
skeletonProps={{ customSkeleton: skeleton }}
/>
);
};
......
import { Text, Show, Hide } from '@chakra-ui/react';
import { Show, Hide } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -6,11 +6,9 @@ import type { AddressTokensResponse } from 'types/api/address';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import TokensListItem from './TokensListItem';
import TokensTable from './TokensTable';
......@@ -27,36 +25,31 @@ const TokensWithoutIds = ({ tokensQuery }: Props) => {
const { isError, isLoading, data, pagination, isPaginationVisible } = tokensQuery;
if (isError) {
return <DataFetchAlert/>;
}
const bar = isMobile && isPaginationVisible && (
const actionBar = isMobile && isPaginationVisible && (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
);
if (isLoading) {
return (
const content = data?.items ? (
<>
{ bar }
<Hide below="lg" ssr={ false }><SkeletonTable columns={ [ '30%', '30%', '10%', '20%', '10%' ] }/></Hide>
<Show below="lg" ssr={ false }><SkeletonList/></Show>
</>
);
}
if (data.items.length === 0) {
return <Text as="span">There are no tokens of selected type.</Text>;
}
<Hide below="lg" ssr={ false }><TokensTable data={ data.items } top={ isPaginationVisible ? 72 : 0 }/></Hide>
<Show below="lg" ssr={ false }>{ data.items.map(item => <TokensListItem key={ item.token.address } { ...item }/>) }</Show></>
) : null;
return (
<>
{ bar }
<Hide below="lg" ssr={ false }><TokensTable data={ data.items } top={ isPaginationVisible ? 72 : 0 }/></Hide>
<Show below="lg" ssr={ false }>{ data.items.map(item => <TokensListItem key={ item.token.address } { ...item }/>) }</Show>
</>
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{
isLongSkeleton: true,
skeletonDesktopColumns: [ '30%', '30%', '10%', '20%', '10%' ],
}}
emptyText="There are no tokens of selected type."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Text, Show, Hide, Alert } from '@chakra-ui/react';
import { Show, Hide, Alert } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import { useQueryClient } from '@tanstack/react-query';
import React from 'react';
......@@ -13,11 +13,9 @@ import useSocketMessage from 'lib/socket/useSocketMessage';
import BlocksList from 'ui/blocks/BlocksList';
import BlocksTable from 'ui/blocks/BlocksTable';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
type QueryResult = UseQueryResult<BlocksResponse> & {
pagination: PaginationProps;
......@@ -76,29 +74,7 @@ const BlocksContent = ({ type, query }: Props) => {
handler: handleNewBlockMessage,
});
const content = (() => {
if (query.isLoading) {
return (
<>
<Show below="lg" key="skeleton-mobile" ssr={ false }>
<SkeletonList/>
</Show>
<Hide below="lg" key="skeleton-desktop" ssr={ false }>
<SkeletonTable columns={ [ '125px', '120px', '21%', '64px', '35%', '22%', '22%' ] }/>
</Hide>
</>
);
}
if (query.isError) {
return <DataFetchAlert/>;
}
if (query.data.items.length === 0) {
return <Text as="span">There are no blocks.</Text>;
}
return (
const content = query.data?.items ? (
<>
{ socketAlert && <Alert status="warning" mb={ 6 } as="a" href={ window.document.location.href }>{ socketAlert }</Alert> }
<Show below="lg" key="content-mobile" ssr={ false }>
......@@ -108,19 +84,24 @@ const BlocksContent = ({ type, query }: Props) => {
<BlocksTable data={ query.data.items } top={ query.isPaginationVisible ? 80 : 0 } page={ query.pagination.page }/>
</Hide>
</>
);
})();
) : null;
return (
<>
{ isMobile && query.isPaginationVisible && (
const actionBar = isMobile && query.isPaginationVisible ? (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...query.pagination }/>
</ActionBar>
) }
{ content }
</>
) : null;
return (
<DataListDisplay
isError={ query.isError }
isLoading={ query.isLoading }
items={ query.data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '125px', '120px', '21%', '64px', '35%', '22%', '22%' ] }}
emptyText="There are no blocks."
content={ content }
actionBar={ actionBar }
/>
);
};
......
......@@ -5,12 +5,10 @@ import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import AddressesListItem from 'ui/addresses/AddressesListItem';
import AddressesTable from 'ui/addresses/AddressesTable';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
const PAGE_SIZE = 50;
......@@ -19,32 +17,15 @@ const Accounts = () => {
resourceName: 'addresses',
});
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
const bar = isPaginationVisible && (
const actionBar = isPaginationVisible && (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
);
if (isLoading) {
return (
<>
{ bar }
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '64px', '30%', '20%', '20%', '15%', '15%' ] }/>
</>
);
}
const pageStartIndex = (pagination.page - 1) * PAGE_SIZE + 1;
return (
const content = data?.items ? (
<>
{ bar }
<Hide below="lg" ssr={ false }>
<AddressesTable
top={ isPaginationVisible ? 80 : 0 }
......@@ -66,13 +47,20 @@ const Accounts = () => {
}) }
</Show>
</>
);
})();
) : null;
return (
<Page>
<PageTitle text="Top accounts" withTextAd/>
{ content }
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '64px', '30%', '20%', '20%', '15%', '15%' ] }}
emptyText="There are no accounts."
content={ content }
actionBar={ actionBar }
/>
</Page>
);
};
......
......@@ -21,8 +21,7 @@ const hooksConfig = {
};
// FIXME: idk why mobile test doesn't work (it's ok locally)
// test('base view +@mobile +@dark-mode', async({ mount, page }) => {
test('base view +@dark-mode', async({ mount, page }) => {
test('base view +@mobile +@dark-mode', async({ mount, page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
status: 200,
body: '',
......
import { Box, Flex, Hide, Show, Text } from '@chakra-ui/react';
import { Box, Flex, Hide, Show } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -8,14 +8,11 @@ import useDebounce from 'lib/hooks/useDebounce';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { apos } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import FilterInput from 'ui/shared/filters/FilterInput';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import Sort from 'ui/shared/sort/Sort';
import type { SortField, Sort as TSort } from 'ui/verifiedContracts/utils';
import { SORT_OPTIONS, sortFn, getNextSortValue } from 'ui/verifiedContracts/utils';
......@@ -82,7 +79,7 @@ const VerifiedContracts = () => {
/>
);
const bar = (
const actionBar = (
<>
<Show below="lg" ssr={ false }>
<Flex columnGap={ 3 } mb={ 6 }>
......@@ -103,35 +100,9 @@ const VerifiedContracts = () => {
</>
);
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
const sortedData = data?.items.slice().sort(sortFn(sort));
if (isLoading) {
return (
<>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '50%', '130px', '130px', '50%', '80px', '110px' ] }/>
</Hide>
</>
);
}
if (data.items.length === 0 && !searchTerm && !type) {
return <Text as="span">There are no verified contracts</Text>;
}
if (data.items.length === 0) {
return <EmptySearchResult text={ `Couldn${ apos }t find any contract that matches your query.` }/>;
}
const sortedData = data.items.slice().sort(sortFn(sort));
return (
const content = sortedData ? (
<>
<Show below="lg" ssr={ false }>
<VerifiedContractsList data={ sortedData }/>
......@@ -140,14 +111,24 @@ const VerifiedContracts = () => {
<VerifiedContractsTable data={ sortedData } sort={ sort } onSortToggle={ handleSortToggle }/>
</Hide>
</>
);
})();
) : null;
return (
<Box>
<PageTitle text="Verified contracts" withTextAd/>
{ bar }
{ content }
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '50%', '130px', '130px', '50%', '80px', '110px' ] }}
emptyText="There are no verified contracts."
filterProps={{
emptyFilteredText: `Couldn${ apos }t find any contract that matches your query.`,
hasActiveFilters: Boolean(searchTerm || type),
}}
content={ content }
actionBar={ actionBar }
/>
</Box>
);
};
......
import { Box, Text, chakra } from '@chakra-ui/react';
import React from 'react';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import DataFetchAlert from './DataFetchAlert';
import SkeletonList from './skeletons/SkeletonList';
import SkeletonTable from './skeletons/SkeletonTable';
type SkeletonProps =
{ customSkeleton: React.ReactNode } |
{
skeletonDesktopColumns: Array<string>;
isLongSkeleton?: boolean;
}
type FilterProps = {
hasActiveFilters: boolean;
emptyFilteredText: string;
};
type Props = {
isError: boolean;
isLoading: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
items?: Array<any>;
emptyText: string;
actionBar?: React.ReactNode;
content: React.ReactNode;
className?: string;
skeletonProps: SkeletonProps;
filterProps?: FilterProps;
}
const DataListDisplay = (props: Props) => {
if (props.isError) {
return <DataFetchAlert/>;
}
if (props.isLoading) {
return (
<>
{ props.actionBar }
{ 'customSkeleton' in props.skeletonProps && props.skeletonProps.customSkeleton }
{ 'skeletonDesktopColumns' in props.skeletonProps && (
<>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable
display={{ base: 'none', lg: 'block' }}
columns={ props.skeletonProps.skeletonDesktopColumns || [] }
isLong={ props.skeletonProps.isLongSkeleton }
/>
</>
) }
</>
);
}
if (props.filterProps?.hasActiveFilters && !props.items?.length) {
return (
<>
{ props.actionBar }
<EmptySearchResult text={ props.filterProps.emptyFilteredText }/>
</>
);
}
if (!props.items?.length) {
return <Text as="span">{ props.emptyText }</Text>;
}
return (
<Box className={ props.className }>
{ props.actionBar }
{ props.content }
</Box>
);
};
export default chakra(DataListDisplay);
import { Text } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -7,10 +6,9 @@ import type { TokenHolders, TokenInfo } from 'types/api/token';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import TokenHoldersList from './TokenHoldersList';
import TokenHoldersTable from './TokenHoldersTable';
......@@ -30,36 +28,31 @@ const TokenHoldersContent = ({ holdersQuery, tokenQuery }: Props) => {
return <DataFetchAlert/>;
}
const bar = isMobile && holdersQuery.isPaginationVisible && (
const actionBar = isMobile && holdersQuery.isPaginationVisible && (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...holdersQuery.pagination }/>
</ActionBar>
);
if (holdersQuery.isLoading || tokenQuery.isLoading) {
return (
<>
{ bar }
{ isMobile && <SkeletonList/> }
{ !isMobile && (
<SkeletonTable columns={ [ '100%', '300px', '175px' ] } isLong/>
) }
</>
);
}
const items = holdersQuery.data.items;
const items = holdersQuery.data?.items;
if (!items?.length) {
return <Text as="span">There are no holders for this token.</Text>;
}
return (
const content = items && tokenQuery.data ? (
<>
{ bar }
{ !isMobile && <TokenHoldersTable data={ items } token={ tokenQuery.data } top={ holdersQuery.isPaginationVisible ? 80 : 0 }/> }
{ isMobile && <TokenHoldersList data={ items } token={ tokenQuery.data }/> }
</>
) : null;
return (
<DataListDisplay
isError={ holdersQuery.isError || tokenQuery.isError }
isLoading={ holdersQuery.isLoading || tokenQuery.isLoading }
items={ holdersQuery.data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '100%', '300px', '175px' ] }}
emptyText="There are no holders for this token."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Grid, Text, Skeleton } from '@chakra-ui/react';
import { Grid, Skeleton } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -6,7 +6,7 @@ import type { TokenInventoryResponse } from 'types/api/token';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import Pagination from 'ui/shared/Pagination';
......@@ -21,20 +21,14 @@ type Props = {
const TokenInventory = ({ inventoryQuery }: Props) => {
const isMobile = useIsMobile();
if (inventoryQuery.isError) {
return <DataFetchAlert/>;
}
const bar = isMobile && inventoryQuery.isPaginationVisible && (
const actionBar = isMobile && inventoryQuery.isPaginationVisible && (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...inventoryQuery.pagination }/>
</ActionBar>
);
if (inventoryQuery.isLoading) {
return (
<>
{ bar }
const skeleton = (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
......@@ -47,19 +41,11 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
<Skeleton w={{ base: '100%', lg: '210px' }} h="272px"/>
</Grid>
</>
);
}
const items = inventoryQuery.data.items;
if (!items?.length) {
return <Text as="span">There are no tokens.</Text>;
}
const items = inventoryQuery.data?.items;
return (
<>
{ bar }
const content = items ? (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
......@@ -67,7 +53,19 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
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 }/>) }
</Grid></>
</Grid>
) : null;
return (
<DataListDisplay
isError={ inventoryQuery.isError }
isLoading={ inventoryQuery.isLoading }
items={ items }
emptyText="There are no tokens."
content={ content }
actionBar={ actionBar }
skeletonProps={{ customSkeleton: skeleton }}
/>
);
};
......
import { Hide, Show, Text } from '@chakra-ui/react';
import { Hide, Show } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -11,11 +11,9 @@ import useIsMobile from 'lib/hooks/useIsMobile';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import { flattenTotal } from 'ui/shared/TokenTransfer/helpers';
import TokenTransferList from 'ui/token/TokenTransfer/TokenTransferList';
......@@ -61,30 +59,10 @@ const TokenTransfer = ({ transfersQuery, tokenId }: Props) => {
handler: handleNewTransfersMessage,
});
const content = (() => {
if (isLoading) {
return (
<>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '45%', '15%', '36px', '15%', '25%' ] } isLong/>
</Hide>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
);
}
if (isError) {
return <DataFetchAlert/>;
}
const items = data?.items?.reduce(flattenTotal, []);
if (!data.items?.length) {
return <Text as="span">There are no token transfers</Text>;
}
const content = items ? (
const items = data.items.reduce(flattenTotal, []);
return (
<>
<Hide below="lg" ssr={ false }>
<TokenTransferTable
......@@ -109,18 +87,27 @@ const TokenTransfer = ({ transfersQuery, tokenId }: Props) => {
<TokenTransferList data={ items } tokenId={ tokenId }/>
</Show>
</>
);
})();
) : null;
return (
<>
{ isMobile && isPaginationVisible && (
const actionBar = isMobile && isPaginationVisible ? (
<ActionBar mt={ -6 }>
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
) }
{ content }
</>
) : null;
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{
isLongSkeleton: true,
skeletonDesktopColumns: [ '45%', '15%', '36px', '15%', '25%' ],
}}
emptyText="There are no token transfers."
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Hide, HStack, Show, Text } from '@chakra-ui/react';
import { Hide, HStack, Show } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React, { useCallback } from 'react';
......@@ -9,15 +9,13 @@ import useDebounce from 'lib/hooks/useDebounce';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { apos } from 'lib/html-entities';
import TOKEN_TYPE from 'lib/token/tokenTypes';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import FilterInput from 'ui/shared/filters/FilterInput';
import PopoverFilter from 'ui/shared/filters/PopoverFilter';
import TokenTypeFilter from 'ui/shared/filters/TokenTypeFilter';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import TokensListItem from './TokensListItem';
import TokensTable from './TokensTable';
......@@ -67,7 +65,7 @@ const Tokens = () => {
/>
);
const bar = (
const actionBar = (
<>
<HStack spacing={ 3 } mb={ 6 } display={{ base: 'flex', lg: 'none' }}>
{ typeFilter }
......@@ -83,36 +81,28 @@ const Tokens = () => {
</>
);
if (isLoading) {
return (
<>
{ bar }
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '25px', '33%', '33%', '33%', '110px' ] }/>
</>
);
}
if (!data.items.length) {
if (debouncedFilter || type) {
return (
<>
{ bar }
<EmptySearchResult text={ `Couldn${ apos }t find token that matches your filter query.` }/>;
</>
);
}
return <Text as="span">There are no tokens</Text>;
}
return (
const content = data?.items ? (
<>
{ bar }
<Show below="lg" ssr={ false }>
{ data.items.map((item, index) => <TokensListItem key={ item.address } token={ item } index={ index } page={ pagination.page }/>) }
</Show>
<Hide below="lg" ssr={ false }><TokensTable items={ data.items } page={ pagination.page }/></Hide>
</>
<Hide below="lg" ssr={ false }><TokensTable items={ data.items } page={ pagination.page }/></Hide></>
) : null;
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '25px', '33%', '33%', '33%', '110px' ] }}
emptyText="There are no tokens."
filterProps={{
emptyFilteredText: `Couldn${ apos }t find token that matches your filter query.`,
hasActiveFilters: Boolean(debouncedFilter || type),
}}
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Box, Text, Show, Hide } from '@chakra-ui/react';
import { Show, Hide } from '@chakra-ui/react';
import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction';
import { SECOND } from 'lib/consts';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { apos } from 'lib/html-entities';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
// import { apos } from 'lib/html-entities';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
// import FilterInput from 'ui/shared/filters/FilterInput';
// import TxInternalsFilter from 'ui/tx/internals/TxInternalsFilter';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import TxInternalsList from 'ui/tx/internals/TxInternalsList';
import TxInternalsTable from 'ui/tx/internals/TxInternalsTable';
import type { Sort, SortField } from 'ui/tx/internals/utils';
......@@ -82,8 +78,6 @@ const TxInternals = () => {
},
});
const isMobile = useIsMobile();
// const handleFilterChange = React.useCallback((nextValue: Array<TxInternalsType>) => {
// setFilters(nextValue);
// }, []);
......@@ -98,52 +92,43 @@ const TxInternals = () => {
return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>;
}
if (isLoading || txInfo.isLoading) {
return (
<>
<Show below="lg" ssr={ false }><SkeletonList/></Show>
<Hide below="lg" ssr={ false }><SkeletonTable columns={ [ '28%', '20%', '24px', '20%', '16%', '16%' ] }/></Hide>
</>
);
}
if (isError || txInfo.isError) {
return <DataFetchAlert/>;
}
if (data.items.length === 0) {
return <Text as="span">There are no internal transactions for this transaction.</Text>;
}
const content = (() => {
const filteredData = data.items
const filteredData = data?.items
.slice()
// .filter(({ type }) => filters.length > 0 ? filters.includes(type) : true)
// .filter(searchFn(searchTerm))
.sort(sortFn(sort));
if (filteredData.length === 0) {
return <EmptySearchResult text={ `Couldn${ apos }t find any transaction that matches your query.` }/>;
}
return isMobile ?
<TxInternalsList data={ filteredData }/> :
<TxInternalsTable data={ filteredData } sort={ sort } onSortToggle={ handleSortToggle } top={ isPaginationVisible ? 80 : 0 }/>;
})();
const content = filteredData ? (
<>
<Show below="lg" ssr={ false }><TxInternalsList data={ filteredData }/></Show>
<Hide below="lg" ssr={ false }>
<TxInternalsTable data={ filteredData } sort={ sort } onSortToggle={ handleSortToggle } top={ isPaginationVisible ? 80 : 0 }/>
</Hide>
</>
) : null;
return (
<Box>
{ isPaginationVisible && (
const actionBar = isPaginationVisible ? (
<ActionBar mt={ -6 }>
{ /* <TxInternalsFilter onFilterChange={ handleFilterChange } defaultFilters={ filters } appliedFiltersNum={ filters.length }/> */ }
{ /* <FilterInput onChange={ setSearchTerm } maxW="360px" ml={ 3 } size="xs" placeholder="Search by addresses, hash, method..."/> */ }
<Pagination ml="auto" { ...pagination }/>
</ActionBar>
) }
{ /* <Flex mb={ 6 }>
<TxInternalsFilter onFilterChange={ handleFilterChange } defaultFilters={ filters } appliedFiltersNum={ filters.length }/>
<FilterInput onChange={ setSearchTerm } maxW="360px" ml={ 3 } size="xs" placeholder="Search by addresses, hash, method..."/>
</Flex> */ }
{ content }
</Box>
) : null;
return (
<DataListDisplay
isError={ isError || txInfo.isError }
isLoading={ isLoading || txInfo.isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '28%', '20%', '24px', '20%', '16%', '16%' ] }}
emptyText="There are no internal transactions for this transaction."
// filterProps={{
// emptyFilteredText: `Couldn${ apos }t find any transaction that matches your query.`.
// hasActiveFilters: Boolean(filters.length || searchTerm),
// }}
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Hide, Show, Text } from '@chakra-ui/react';
import { Hide, Show } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -9,12 +9,10 @@ import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { apos } from 'lib/html-entities';
import TOKEN_TYPE from 'lib/token/tokenTypes';
import EmptySearchResult from 'ui/apps/EmptySearchResult';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import { flattenTotal } from 'ui/shared/TokenTransfer/helpers';
import TokenTransferFilter from 'ui/shared/TokenTransfer/TokenTransferFilter';
import TokenTransferList from 'ui/shared/TokenTransfer/TokenTransferList';
......@@ -57,31 +55,9 @@ const TxTokenTransfer = () => {
const numActiveFilters = typeFilter.length;
const isActionBarHidden = !numActiveFilters && !tokenTransferQuery.data?.items.length;
const content = (() => {
if (txsInfo.isLoading || tokenTransferQuery.isLoading) {
return (
<>
<Hide below="lg" ssr={ false }>
<SkeletonTable columns={ [ '185px', '25%', '25%', '25%', '25%' ] }
/>
</Hide>
<Show below="lg" ssr={ false }>
<SkeletonList/>
</Show>
</>
);
}
if (!tokenTransferQuery.data.items?.length && !numActiveFilters) {
return <Text as="span">There are no token transfers</Text>;
}
if (!tokenTransferQuery.data.items?.length) {
return <EmptySearchResult text={ `Couldn${ apos }t find any token transfer that matches your query.` }/>;
}
const items = tokenTransferQuery.data?.items?.reduce(flattenTotal, []);
const items = tokenTransferQuery.data.items.reduce(flattenTotal, []);
return (
const content = items ? (
<>
<Hide below="lg" ssr={ false }>
<TokenTransferTable data={ items } top={ isActionBarHidden ? 0 : 80 }/>
......@@ -90,12 +66,9 @@ const TxTokenTransfer = () => {
<TokenTransferList data={ items }/>
</Show>
</>
);
})();
) : null;
return (
<>
{ !isActionBarHidden && (
const actionBar = !isActionBarHidden ? (
<ActionBar mt={ -6 }>
<TokenTransferFilter
defaultTypeFilters={ typeFilter }
......@@ -104,9 +77,25 @@ const TxTokenTransfer = () => {
/>
{ tokenTransferQuery.isPaginationVisible && <Pagination ml="auto" { ...tokenTransferQuery.pagination }/> }
</ActionBar>
) }
{ content }
</>
) : null;
return (
<DataListDisplay
isError={ txsInfo.isError || tokenTransferQuery.isError }
isLoading={ txsInfo.isLoading || tokenTransferQuery.isLoading }
items={ tokenTransferQuery.data?.items }
skeletonProps={{
isLongSkeleton: true,
skeletonDesktopColumns: [ '185px', '25%', '25%', '25%', '25%' ],
}}
emptyText="There are no token transfers."
filterProps={{
emptyFilteredText: `Couldn${ apos }t find any token transfer that matches your query.`,
hasActiveFilters: Boolean(numActiveFilters),
}}
content={ content }
actionBar={ actionBar }
/>
);
};
......
import { Text, Box, Show, Hide } from '@chakra-ui/react';
import { Box, Show, Hide } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';
......@@ -6,10 +6,8 @@ import type { TxsResponse } from 'types/api/transaction';
import useIsMobile from 'lib/hooks/useIsMobile';
import AddressCsvExportLink from 'ui/address/AddressCsvExportLink';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import type { Props as PaginationProps } from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import TxsHeaderMobile from './TxsHeaderMobile';
......@@ -50,35 +48,7 @@ const TxsContent = ({
const { data, isLoading, isError, setSortByField, setSortByValue, sorting } = useTxsSort(query);
const isMobile = useIsMobile();
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
if (isLoading) {
return (
<>
<Show below="lg" ssr={ false }><SkeletonList/></Show>
<Hide below="lg" ssr={ false }>
<SkeletonTable
columns={ showBlockInfo ?
[ '32px', '22%', '160px', '20%', '18%', '292px', '20%', '20%' ] :
[ '32px', '22%', '160px', '20%', '292px', '20%', '20%' ]
}
isLong={ hasLongSkeleton }
/>
</Hide>
</>
);
}
const txs = data.items;
if (!txs.length) {
return <Text as="span">There are no transactions.</Text>;
}
return (
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
<Box>
......@@ -92,7 +62,7 @@ const TxsContent = ({
{ ({ content }) => <Box>{ content }</Box> }
</SocketNewItemsNotice>
) }
{ txs.map(tx => (
{ data.items.map(tx => (
<TxsListItem
tx={ tx }
key={ tx.hash }
......@@ -105,7 +75,7 @@ const TxsContent = ({
</Show>
<Hide below="lg" ssr={ false }>
<TxsTable
txs={ txs }
txs={ data.items }
sort={ setSortByField }
sorting={ sorting }
showBlockInfo={ showBlockInfo }
......@@ -118,12 +88,9 @@ const TxsContent = ({
/>
</Hide>
</>
);
})();
) : null;
return (
<>
{ isMobile && (
const actionBar = isMobile ? (
<TxsHeaderMobile
mt={ -6 }
sorting={ sorting }
......@@ -133,9 +100,23 @@ const TxsContent = ({
filterComponent={ filter }
linkSlot={ currentAddress ? <AddressCsvExportLink address={ currentAddress } type="transactions" ml={ 2 }/> : null }
/>
) }
{ content }
</>
) : null;
return (
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{
isLongSkeleton: hasLongSkeleton,
skeletonDesktopColumns: showBlockInfo ?
[ '32px', '22%', '160px', '20%', '18%', '292px', '20%', '20%' ] :
[ '32px', '22%', '160px', '20%', '292px', '20%', '20%' ],
}}
emptyText="There are no transactions."
content={ content }
actionBar={ actionBar }
/>
);
};
......
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