mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
Merge pull request #1378 from blockscout/fe-1210
Sorting in tables v0.5
This commit is contained in:
+10
-1
@@ -58,9 +58,16 @@ import type {
|
||||
} from 'types/api/token';
|
||||
import type { TokensResponse, TokensFilters, TokensSorting, TokenInstanceTransferResponse, TokensBridgedFilters } from 'types/api/tokens';
|
||||
import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer';
|
||||
import type { TransactionsResponseValidated, TransactionsResponsePending, Transaction, TransactionsResponseWatchlist } from 'types/api/transaction';
|
||||
import type {
|
||||
TransactionsResponseValidated,
|
||||
TransactionsResponsePending,
|
||||
Transaction,
|
||||
TransactionsResponseWatchlist,
|
||||
TransactionsSorting,
|
||||
} from 'types/api/transaction';
|
||||
import type { TTxsFilters } from 'types/api/txsFilters';
|
||||
import type { TxStateChanges } from 'types/api/txStateChanges';
|
||||
import type { VerifiedContractsSorting } from 'types/api/verifiedContracts';
|
||||
import type { VisualizedContract } from 'types/api/visualization';
|
||||
import type { WithdrawalsResponse, WithdrawalsCounters } from 'types/api/withdrawals';
|
||||
import type { ZkEvmL2TxnBatch, ZkEvmL2TxnBatchesItem, ZkEvmL2TxnBatchesResponse, ZkEvmL2TxnBatchTxs } from 'types/api/zkEvmL2TxnBatches';
|
||||
@@ -725,5 +732,7 @@ never;
|
||||
export type PaginationSorting<Q extends PaginatedResources> =
|
||||
Q extends 'tokens' ? TokensSorting :
|
||||
Q extends 'tokens_bridged' ? TokensSorting :
|
||||
Q extends 'verified_contracts' ? VerifiedContractsSorting :
|
||||
Q extends 'address_txs' ? TransactionsSorting :
|
||||
never;
|
||||
/* eslint-enable @typescript-eslint/indent */
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
|
||||
const sortTxs = (sorting?: Sort) => (tx1: Transaction, tx2: Transaction) => {
|
||||
switch (sorting) {
|
||||
case 'val-desc':
|
||||
return compareBns(tx1.value, tx2.value);
|
||||
case 'val-asc':
|
||||
return compareBns(tx2.value, tx1.value);
|
||||
case 'fee-desc':
|
||||
return compareBns(tx1.fee.value || 0, tx2.fee.value || 0);
|
||||
case 'fee-asc':
|
||||
return compareBns(tx2.fee.value || 0, tx1.fee.value || 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
export default sortTxs;
|
||||
@@ -117,3 +117,12 @@ export type TransactionType = 'rootstock_remasc' |
|
||||
'coin_transfer'
|
||||
|
||||
export type TxsResponse = TransactionsResponseValidated | TransactionsResponsePending | BlockTransactionsResponse;
|
||||
|
||||
export interface TransactionsSorting {
|
||||
sort: 'value' | 'fee';
|
||||
order: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export type TransactionsSortingField = TransactionsSorting['sort'];
|
||||
|
||||
export type TransactionsSortingValue = `${ TransactionsSortingField }-${ TransactionsSorting['order'] }`;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface VerifiedContractsSorting {
|
||||
sort: 'balance' | 'txs_count';
|
||||
order: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export type VerifiedContractsSortingField = VerifiedContractsSorting['sort'];
|
||||
|
||||
export type VerifiedContractsSortingValue = `${ VerifiedContractsSortingField }-${ VerifiedContractsSorting['order'] }`;
|
||||
@@ -1 +0,0 @@
|
||||
export type Sort = 'val-desc' | 'val-asc' | 'fee-desc' | 'fee-asc' | '';
|
||||
@@ -5,7 +5,7 @@ import React from 'react';
|
||||
import type { SocketMessage } from 'lib/socket/types';
|
||||
import type { AddressFromToFilter, AddressTransactionsResponse } from 'types/api/address';
|
||||
import { AddressFromToFilterValues } from 'types/api/address';
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue, TransactionsSorting } from 'types/api/transaction';
|
||||
|
||||
import { getResourceKey } from 'lib/api/useApiQuery';
|
||||
import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
|
||||
@@ -18,7 +18,10 @@ import { generateListStub } from 'stubs/utils';
|
||||
import ActionBar from 'ui/shared/ActionBar';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
import TxsWithAPISorting from 'ui/txs/TxsWithAPISorting';
|
||||
import { SORT_OPTIONS } from 'ui/txs/useTxsSort';
|
||||
|
||||
import AddressCsvExportLink from './AddressCsvExportLink';
|
||||
import AddressTxsFilter from './AddressTxsFilter';
|
||||
@@ -53,6 +56,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
|
||||
const [ socketAlert, setSocketAlert ] = React.useState('');
|
||||
const [ newItemsCount, setNewItemsCount ] = React.useState(0);
|
||||
const [ sort, setSort ] = React.useState<TransactionsSortingValue | undefined>(getSortValueFromQuery<TransactionsSortingValue>(router.query, SORT_OPTIONS));
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
const currentAddress = getQueryParamString(router.query.hash);
|
||||
@@ -63,6 +67,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
resourceName: 'address_txs',
|
||||
pathParams: { hash: currentAddress },
|
||||
filters: { filter: filterValue },
|
||||
sorting: getSortParamsFromValue<TransactionsSortingValue, TransactionsSortingField, TransactionsSorting['order']>(sort),
|
||||
scrollRef,
|
||||
options: {
|
||||
placeholderData: generateListStub<'address_txs'>(TX, 50, { next_page_params: {
|
||||
@@ -177,7 +182,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
<Pagination { ...addressTxsQuery.pagination } ml={ 8 }/>
|
||||
</ActionBar>
|
||||
) }
|
||||
<TxsContent
|
||||
<TxsWithAPISorting
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
query={ addressTxsQuery }
|
||||
@@ -187,6 +192,8 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
|
||||
socketInfoAlert={ socketAlert }
|
||||
socketInfoNum={ newItemsCount }
|
||||
top={ 80 }
|
||||
sorting={ sort }
|
||||
setSort={ setSort }
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -82,7 +82,7 @@ const BlockPageContent = () => {
|
||||
|
||||
const tabs: Array<RoutedTab> = React.useMemo(() => ([
|
||||
{ id: 'index', title: 'Details', component: <BlockDetails query={ blockQuery }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsContent query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsWithFrontendSorting query={ blockTxsQuery } showBlockInfo={ false } showSocketInfo={ false }/> },
|
||||
config.features.beaconChain.isEnabled && Boolean(blockQuery.data?.withdrawals_count) ?
|
||||
{ id: 'withdrawals', title: 'Withdrawals', component: <BlockWithdrawals blockWithdrawalsQuery={ blockWithdrawalsQuery }/> } :
|
||||
null,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { generateListStub } from 'stubs/utils';
|
||||
import AddressEntity from 'ui/shared/entities/address/AddressEntity';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const KettleTxs = () => {
|
||||
const router = useRouter();
|
||||
@@ -31,7 +31,7 @@ const KettleTxs = () => {
|
||||
<>
|
||||
<PageTitle title="Computor transactions" withTextAd/>
|
||||
<AddressEntity address={{ hash }} mb={ 6 }/>
|
||||
<TxsContent
|
||||
<TxsWithFrontendSorting
|
||||
query={ query }
|
||||
showSocketInfo={ false }
|
||||
/>
|
||||
|
||||
+6
-4
@@ -3,7 +3,7 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { TokenType } from 'types/api/token';
|
||||
import type { TokensSortingValue } from 'types/api/tokens';
|
||||
import type { TokensSortingValue, TokensSortingField, TokensSorting } from 'types/api/tokens';
|
||||
import type { RoutedTab } from 'ui/shared/Tabs/types';
|
||||
|
||||
import config from 'configs/app';
|
||||
@@ -16,11 +16,13 @@ import PopoverFilter from 'ui/shared/filters/PopoverFilter';
|
||||
import TokenTypeFilter from 'ui/shared/filters/TokenTypeFilter';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TokensList from 'ui/tokens/Tokens';
|
||||
import TokensActionBar from 'ui/tokens/TokensActionBar';
|
||||
import TokensBridgedChainsFilter from 'ui/tokens/TokensBridgedChainsFilter';
|
||||
import { getSortParamsFromValue, getSortValueFromQuery, getTokenFilterValue, getBridgedChainsFilterValue } from 'ui/tokens/utils';
|
||||
import { SORT_OPTIONS, getTokenFilterValue, getBridgedChainsFilterValue } from 'ui/tokens/utils';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -44,7 +46,7 @@ const Tokens = () => {
|
||||
const q = getQueryParamString(router.query.q);
|
||||
|
||||
const [ searchTerm, setSearchTerm ] = React.useState<string>(q ?? '');
|
||||
const [ sort, setSort ] = React.useState<TokensSortingValue | undefined>(getSortValueFromQuery(router.query));
|
||||
const [ sort, setSort ] = React.useState<TokensSortingValue | undefined>(getSortValueFromQuery<TokensSortingValue>(router.query, SORT_OPTIONS));
|
||||
const [ tokenTypes, setTokenTypes ] = React.useState<Array<TokenType> | undefined>(getTokenFilterValue(router.query.type));
|
||||
const [ bridgeChains, setBridgeChains ] = React.useState<Array<string> | undefined>(getBridgedChainsFilterValue(router.query.chain_ids));
|
||||
|
||||
@@ -53,7 +55,7 @@ const Tokens = () => {
|
||||
const tokensQuery = useQueryWithPages({
|
||||
resourceName: tab === 'bridged' ? 'tokens_bridged' : 'tokens',
|
||||
filters: tab === 'bridged' ? { q: debouncedSearchTerm, chain_ids: bridgeChains } : { q: debouncedSearchTerm, type: tokenTypes },
|
||||
sorting: getSortParamsFromValue(sort),
|
||||
sorting: getSortParamsFromValue<TokensSortingValue, TokensSortingField, TokensSorting['order']>(sort),
|
||||
options: {
|
||||
placeholderData: generateListStub<'tokens'>(
|
||||
TOKEN_INFO_ERC_20,
|
||||
|
||||
@@ -13,8 +13,8 @@ import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWatchlist from 'ui/txs/TxsWatchlist';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
const TAB_LIST_PROPS = {
|
||||
marginBottom: 0,
|
||||
@@ -60,12 +60,13 @@ const Transactions = () => {
|
||||
{
|
||||
id: 'validated',
|
||||
title: verifiedTitle,
|
||||
component: <TxsContent query={ txsQuery } showSocketInfo={ txsQuery.pagination.page === 1 } socketInfoNum={ num } socketInfoAlert={ socketAlert }/> },
|
||||
component:
|
||||
<TxsWithFrontendSorting query={ txsQuery } showSocketInfo={ txsQuery.pagination.page === 1 } socketInfoNum={ num } socketInfoAlert={ socketAlert }/> },
|
||||
{
|
||||
id: 'pending',
|
||||
title: 'Pending',
|
||||
component: (
|
||||
<TxsContent
|
||||
<TxsWithFrontendSorting
|
||||
query={ txsQuery }
|
||||
showBlockInfo={ false }
|
||||
showSocketInfo={ txsQuery.pagination.page === 1 }
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useRouter } from 'next/router';
|
||||
import React from 'react';
|
||||
|
||||
import type { VerifiedContractsFilters } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts';
|
||||
|
||||
import useDebounce from 'lib/hooks/useDebounce';
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
@@ -16,9 +17,10 @@ import FilterInput from 'ui/shared/filters/FilterInput';
|
||||
import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
import getSortValueFromQuery from 'ui/shared/sort/getSortValueFromQuery';
|
||||
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';
|
||||
import { SORT_OPTIONS } from 'ui/verifiedContracts/utils';
|
||||
import VerifiedContractsCounters from 'ui/verifiedContracts/VerifiedContractsCounters';
|
||||
import VerifiedContractsFilter from 'ui/verifiedContracts/VerifiedContractsFilter';
|
||||
import VerifiedContractsList from 'ui/verifiedContracts/VerifiedContractsList';
|
||||
@@ -28,15 +30,17 @@ const VerifiedContracts = () => {
|
||||
const router = useRouter();
|
||||
const [ searchTerm, setSearchTerm ] = React.useState(getQueryParamString(router.query.q) || undefined);
|
||||
const [ type, setType ] = React.useState(getQueryParamString(router.query.filter) as VerifiedContractsFilters['filter'] || undefined);
|
||||
const [ sort, setSort ] = React.useState<TSort>();
|
||||
const [ sort, setSort ] =
|
||||
React.useState<VerifiedContractsSortingValue | undefined>(getSortValueFromQuery<VerifiedContractsSortingValue>(router.query, SORT_OPTIONS));
|
||||
|
||||
const debouncedSearchTerm = useDebounce(searchTerm || '', 300);
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const { isError, isPlaceholderData, data, pagination, onFilterChange } = useQueryWithPages({
|
||||
const { isError, isPlaceholderData, data, pagination, onFilterChange, onSortingChange } = useQueryWithPages({
|
||||
resourceName: 'verified_contracts',
|
||||
filters: { q: debouncedSearchTerm, filter: type },
|
||||
sorting: getSortParamsFromValue<VerifiedContractsSortingValue, VerifiedContractsSortingField, VerifiedContractsSorting['order']>(sort),
|
||||
options: {
|
||||
placeholderData: generateListStub<'verified_contracts'>(
|
||||
VERIFIED_CONTRACT_INFO,
|
||||
@@ -67,11 +71,10 @@ const VerifiedContracts = () => {
|
||||
setType(filter);
|
||||
}, [ debouncedSearchTerm, onFilterChange ]);
|
||||
|
||||
const handleSortToggle = React.useCallback((field: SortField) => {
|
||||
return () => {
|
||||
setSort(getNextSortValue(field));
|
||||
};
|
||||
}, []);
|
||||
const handleSortChange = React.useCallback((value?: VerifiedContractsSortingValue) => {
|
||||
setSort(value);
|
||||
onSortingChange(getSortParamsFromValue(value));
|
||||
}, [ onSortingChange ]);
|
||||
|
||||
const typeFilter = <VerifiedContractsFilter onChange={ handleTypeChange } defaultValue={ type } isActive={ Boolean(type) }/>;
|
||||
|
||||
@@ -89,7 +92,7 @@ const VerifiedContracts = () => {
|
||||
<Sort
|
||||
options={ SORT_OPTIONS }
|
||||
sort={ sort }
|
||||
setSort={ setSort }
|
||||
setSort={ handleSortChange }
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -112,15 +115,13 @@ const VerifiedContracts = () => {
|
||||
</>
|
||||
);
|
||||
|
||||
const sortedData = data?.items.slice().sort(sortFn(sort));
|
||||
|
||||
const content = sortedData ? (
|
||||
const content = data?.items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>
|
||||
<VerifiedContractsList data={ sortedData } isLoading={ isPlaceholderData }/>
|
||||
<VerifiedContractsList data={ data.items } isLoading={ isPlaceholderData }/>
|
||||
</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<VerifiedContractsTable data={ sortedData } sort={ sort } onSortToggle={ handleSortToggle } isLoading={ isPlaceholderData }/>
|
||||
<VerifiedContractsTable data={ data.items } sort={ sort } setSorting={ handleSortChange } isLoading={ isPlaceholderData }/>
|
||||
</Hide>
|
||||
</>
|
||||
) : null;
|
||||
|
||||
@@ -14,7 +14,7 @@ import PageTitle from 'ui/shared/Page/PageTitle';
|
||||
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
|
||||
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
|
||||
import TabsSkeleton from 'ui/shared/Tabs/TabsSkeleton';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
import ZkEvmL2TxnBatchDetails from 'ui/zkEvmL2TxnBatches/ZkEvmL2TxnBatchDetails';
|
||||
|
||||
const ZkEvmL2TxnBatch = () => {
|
||||
@@ -51,7 +51,7 @@ const ZkEvmL2TxnBatch = () => {
|
||||
|
||||
const tabs: Array<RoutedTab> = React.useMemo(() => ([
|
||||
{ id: 'index', title: 'Details', component: <ZkEvmL2TxnBatchDetails query={ batchQuery }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsContent query={ batchTxsQuery } showSocketInfo={ false }/> },
|
||||
{ id: 'txs', title: 'Transactions', component: <TxsWithFrontendSorting query={ batchTxsQuery } showSocketInfo={ false }/> },
|
||||
].filter(Boolean)), [ batchQuery, batchTxsQuery ]);
|
||||
|
||||
const backLink = React.useMemo(() => {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export default function getSortParamsFromValue<SortValue extends string, SortField extends string, SortOrder extends string>(val?: SortValue) {
|
||||
if (!val) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const sortingChunks = val.split('-') as [ SortField, SortOrder ];
|
||||
return { sort: sortingChunks[0], order: sortingChunks[1] };
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type { Query } from 'nextjs-routes';
|
||||
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export default function getSortValueFromQuery<SortValue extends string>(query: Query, sortOptions: Array<Option<SortValue>>) {
|
||||
if (!query.sort || !query.order) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const str = query.sort + '-' + query.order;
|
||||
if (sortOptions.map(option => option.id).includes(str as SortValue)) {
|
||||
return str as SortValue;
|
||||
}
|
||||
}
|
||||
+1
-22
@@ -1,7 +1,5 @@
|
||||
import type { TokenType } from 'types/api/token';
|
||||
import type { TokensSortingField, TokensSortingValue, TokensSorting } from 'types/api/tokens';
|
||||
|
||||
import type { Query } from 'nextjs-routes';
|
||||
import type { TokensSortingValue } from 'types/api/tokens';
|
||||
|
||||
import config from 'configs/app';
|
||||
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
|
||||
@@ -29,22 +27,3 @@ const bridgedTokensChainIds = (() => {
|
||||
return feature.chains.map(chain => chain.id);
|
||||
})();
|
||||
export const getBridgedChainsFilterValue = (getFilterValuesFromQuery<string>).bind(null, bridgedTokensChainIds);
|
||||
|
||||
export const getSortValueFromQuery = (query: Query): TokensSortingValue | undefined => {
|
||||
if (!query.sort || !query.order) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const str = query.sort + '-' + query.order;
|
||||
if (SORT_OPTIONS.map(option => option.id).includes(str)) {
|
||||
return str as TokensSortingValue;
|
||||
}
|
||||
};
|
||||
|
||||
export const getSortParamsFromValue = (val?: TokensSortingValue): TokensSorting | undefined => {
|
||||
if (!val) {
|
||||
return undefined;
|
||||
}
|
||||
const sortingChunks = val.split('-') as [ TokensSortingField, TokensSorting['order'] ];
|
||||
return { sort: sortingChunks[0], order: sortingChunks[1] };
|
||||
};
|
||||
|
||||
+31
-11
@@ -2,17 +2,23 @@ import { Box, Show, Hide } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import useIsMobile from 'lib/hooks/useIsMobile';
|
||||
import AddressCsvExportLink from 'ui/address/AddressCsvExportLink';
|
||||
import DataListDisplay from 'ui/shared/DataListDisplay';
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
|
||||
import getNextSortValue from 'ui/shared/sort/getNextSortValue';
|
||||
|
||||
import TxsHeaderMobile from './TxsHeaderMobile';
|
||||
import TxsListItem from './TxsListItem';
|
||||
import TxsTable from './TxsTable';
|
||||
import useTxsSort from './useTxsSort';
|
||||
|
||||
const SORT_SEQUENCE: Record<TransactionsSortingField, Array<TransactionsSortingValue | undefined>> = {
|
||||
value: [ 'value-desc', 'value-asc', undefined ],
|
||||
fee: [ 'fee-desc', 'fee-asc', undefined ],
|
||||
};
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
@@ -26,12 +32,17 @@ type Props = {
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
items?: Array<Transaction>;
|
||||
isPlaceholderData: boolean;
|
||||
isError: boolean;
|
||||
setSorting: (value: TransactionsSortingValue | undefined) => void;
|
||||
sort: TransactionsSortingValue | undefined;
|
||||
}
|
||||
|
||||
const TxsContent = ({
|
||||
query,
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
@@ -39,11 +50,20 @@ const TxsContent = ({
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
items,
|
||||
isPlaceholderData,
|
||||
isError,
|
||||
setSorting,
|
||||
sort,
|
||||
}: Props) => {
|
||||
const { data, isPlaceholderData, isError, setSortByField, setSortByValue, sorting } = useTxsSort(query);
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const content = data?.items ? (
|
||||
const onSortToggle = React.useCallback((field: TransactionsSortingField) => () => {
|
||||
const value = getNextSortValue<TransactionsSortingField, TransactionsSortingValue>(SORT_SEQUENCE, field)(sort);
|
||||
setSorting(value);
|
||||
}, [ sort, setSorting ]);
|
||||
|
||||
const content = items ? (
|
||||
<>
|
||||
<Show below="lg" ssr={ false }>
|
||||
<Box>
|
||||
@@ -55,7 +75,7 @@ const TxsContent = ({
|
||||
isLoading={ isPlaceholderData }
|
||||
/>
|
||||
) }
|
||||
{ data.items.map((tx, index) => (
|
||||
{ items.map((tx, index) => (
|
||||
<TxsListItem
|
||||
key={ tx.hash + (isPlaceholderData ? index : '') }
|
||||
tx={ tx }
|
||||
@@ -69,9 +89,9 @@ const TxsContent = ({
|
||||
</Show>
|
||||
<Hide below="lg" ssr={ false }>
|
||||
<TxsTable
|
||||
txs={ data.items }
|
||||
sort={ setSortByField }
|
||||
sorting={ sorting }
|
||||
txs={ items }
|
||||
sort={ onSortToggle }
|
||||
sorting={ sort }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
@@ -88,8 +108,8 @@ const TxsContent = ({
|
||||
const actionBar = isMobile ? (
|
||||
<TxsHeaderMobile
|
||||
mt={ -6 }
|
||||
sorting={ sorting }
|
||||
setSorting={ setSortByValue }
|
||||
sorting={ sort }
|
||||
setSorting={ setSorting }
|
||||
paginationProps={ query.pagination }
|
||||
showPagination={ query.pagination.isVisible }
|
||||
filterComponent={ filter }
|
||||
@@ -107,7 +127,7 @@ const TxsContent = ({
|
||||
return (
|
||||
<DataListDisplay
|
||||
isError={ isError }
|
||||
items={ data?.items }
|
||||
items={ items }
|
||||
emptyText="There are no transactions."
|
||||
content={ content }
|
||||
actionBar={ actionBar }
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
import { HStack, chakra } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { Sort as TSort } from 'types/client/txs-sort';
|
||||
import type { TransactionsSortingValue } from 'types/api/transaction';
|
||||
import type { PaginationParams } from 'ui/shared/pagination/types';
|
||||
|
||||
// import FilterInput from 'ui/shared/filters/FilterInput';
|
||||
|
||||
import ActionBar from 'ui/shared/ActionBar';
|
||||
import Pagination from 'ui/shared/pagination/Pagination';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
import Sort from 'ui/shared/sort/Sort';
|
||||
|
||||
import { SORT_OPTIONS } from './useTxsSort';
|
||||
|
||||
// import TxsFilters from './TxsFilters';
|
||||
|
||||
const SORT_OPTIONS: Array<Option<TSort>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Value ascending', id: 'val-asc' },
|
||||
{ title: 'Value descending', id: 'val-desc' },
|
||||
{ title: 'Fee ascending', id: 'fee-asc' },
|
||||
{ title: 'Fee descending', id: 'fee-desc' },
|
||||
];
|
||||
|
||||
type Props = {
|
||||
sorting: TSort;
|
||||
setSorting: (val: TSort | undefined) => void;
|
||||
sorting: TransactionsSortingValue | undefined;
|
||||
setSorting: (val: TransactionsSortingValue | undefined) => void;
|
||||
paginationProps: PaginationParams;
|
||||
className?: string;
|
||||
showPagination?: boolean;
|
||||
|
||||
+6
-7
@@ -2,8 +2,7 @@ import { Link, Table, Tbody, Tr, Th, Icon, Show, Hide } from '@chakra-ui/react';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import React from 'react';
|
||||
|
||||
import type { Transaction } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
import type { Transaction, TransactionsSortingField, TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import config from 'configs/app';
|
||||
import rightArrowIcon from 'icons/arrows/east.svg';
|
||||
@@ -14,8 +13,8 @@ import TxsTableItem from './TxsTableItem';
|
||||
|
||||
type Props = {
|
||||
txs: Array<Transaction>;
|
||||
sort: (field: 'val' | 'fee') => () => void;
|
||||
sorting?: Sort;
|
||||
sort: (field: TransactionsSortingField) => () => void;
|
||||
sorting?: TransactionsSortingValue;
|
||||
top: number;
|
||||
showBlockInfo: boolean;
|
||||
showSocketInfo: boolean;
|
||||
@@ -58,9 +57,9 @@ const TxsTable = ({
|
||||
</Th>
|
||||
{ !config.UI.views.tx.hiddenFields?.value && (
|
||||
<Th width="20%" isNumeric>
|
||||
<Link onClick={ sort('val') } display="flex" justifyContent="end">
|
||||
{ sorting === 'val-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
|
||||
{ sorting === 'val-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
|
||||
<Link onClick={ sort('value') } display="flex" justifyContent="end">
|
||||
{ sorting === 'value-asc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(-90deg)"/> }
|
||||
{ sorting === 'value-desc' && <Icon boxSize={ 5 } as={ rightArrowIcon } transform="rotate(90deg)"/> }
|
||||
{ `Value ${ config.chain.currency.symbol }` }
|
||||
</Link>
|
||||
</Th>
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
import useRedirectForInvalidAuthToken from 'lib/hooks/useRedirectForInvalidAuthToken';
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import TxsContent from 'ui/txs/TxsContent';
|
||||
import TxsWithFrontendSorting from 'ui/txs/TxsWithFrontendSorting';
|
||||
|
||||
type Props = {
|
||||
query: QueryWithPagesResult<'txs_watchlist'>;
|
||||
@@ -10,7 +10,7 @@ type Props = {
|
||||
|
||||
const TxsWatchlist = ({ query }: Props) => {
|
||||
useRedirectForInvalidAuthToken();
|
||||
return <TxsContent query={ query } showSocketInfo={ false }/>;
|
||||
return <TxsWithFrontendSorting query={ query } showSocketInfo={ false }/>;
|
||||
};
|
||||
|
||||
export default TxsWatchlist;
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
import type { TransactionsSortingValue } from 'types/api/transaction';
|
||||
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
import getSortParamsFromValue from 'ui/shared/sort/getSortParamsFromValue';
|
||||
|
||||
import TxsContent from './TxsContent';
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
query: QueryWithPagesResult<'address_txs'>;
|
||||
showBlockInfo?: boolean;
|
||||
showSocketInfo?: boolean;
|
||||
socketInfoAlert?: string;
|
||||
socketInfoNum?: number;
|
||||
currentAddress?: string;
|
||||
filter?: React.ReactNode;
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
sorting: TransactionsSortingValue | undefined;
|
||||
setSort: (value?: TransactionsSortingValue) => void;
|
||||
}
|
||||
|
||||
const TxsWithAPISorting = ({
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
socketInfoNum,
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
sorting,
|
||||
setSort,
|
||||
}: Props) => {
|
||||
|
||||
const handleSortChange = React.useCallback((value?: TransactionsSortingValue) => {
|
||||
setSort(value);
|
||||
query.onSortingChange(getSortParamsFromValue(value));
|
||||
}, [ setSort, query ]);
|
||||
|
||||
return (
|
||||
<TxsContent
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
socketInfoNum={ socketInfoNum }
|
||||
currentAddress={ currentAddress }
|
||||
enableTimeIncrement={ enableTimeIncrement }
|
||||
top={ top }
|
||||
items={ query.data?.items }
|
||||
isPlaceholderData={ query.isPlaceholderData }
|
||||
isError={ query.isError }
|
||||
setSorting={ handleSortChange }
|
||||
sort={ sorting }
|
||||
query={ query }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxsWithAPISorting;
|
||||
@@ -0,0 +1,59 @@
|
||||
import React from 'react';
|
||||
|
||||
import type { AddressFromToFilter } from 'types/api/address';
|
||||
|
||||
import type { QueryWithPagesResult } from 'ui/shared/pagination/useQueryWithPages';
|
||||
|
||||
import TxsContent from './TxsContent';
|
||||
import useTxsSort from './useTxsSort';
|
||||
|
||||
type Props = {
|
||||
// eslint-disable-next-line max-len
|
||||
query: QueryWithPagesResult<'txs_validated' | 'txs_pending'> | QueryWithPagesResult<'txs_watchlist'> | QueryWithPagesResult<'block_txs'> | QueryWithPagesResult<'zkevm_l2_txn_batch_txs'>;
|
||||
showBlockInfo?: boolean;
|
||||
showSocketInfo?: boolean;
|
||||
socketInfoAlert?: string;
|
||||
socketInfoNum?: number;
|
||||
currentAddress?: string;
|
||||
filter?: React.ReactNode;
|
||||
filterValue?: AddressFromToFilter;
|
||||
enableTimeIncrement?: boolean;
|
||||
top?: number;
|
||||
}
|
||||
|
||||
const TxsWithFrontendSorting = ({
|
||||
filter,
|
||||
filterValue,
|
||||
query,
|
||||
showBlockInfo = true,
|
||||
showSocketInfo = true,
|
||||
socketInfoAlert,
|
||||
socketInfoNum,
|
||||
currentAddress,
|
||||
enableTimeIncrement,
|
||||
top,
|
||||
}: Props) => {
|
||||
const { data, isPlaceholderData, isError, setSortByValue, sorting } = useTxsSort(query);
|
||||
|
||||
return (
|
||||
<TxsContent
|
||||
filter={ filter }
|
||||
filterValue={ filterValue }
|
||||
showBlockInfo={ showBlockInfo }
|
||||
showSocketInfo={ showSocketInfo }
|
||||
socketInfoAlert={ socketInfoAlert }
|
||||
socketInfoNum={ socketInfoNum }
|
||||
currentAddress={ currentAddress }
|
||||
enableTimeIncrement={ enableTimeIncrement }
|
||||
top={ top }
|
||||
items={ data?.items }
|
||||
isPlaceholderData={ isPlaceholderData }
|
||||
isError={ isError }
|
||||
setSorting={ setSortByValue }
|
||||
sort={ sorting }
|
||||
query={ query }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TxsWithFrontendSorting;
|
||||
+38
-45
@@ -1,78 +1,71 @@
|
||||
import type { UseQueryResult } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
import type { TxsResponse } from 'types/api/transaction';
|
||||
import type { Sort } from 'types/client/txs-sort';
|
||||
import type { Transaction, TransactionsSortingValue, TxsResponse } from 'types/api/transaction';
|
||||
|
||||
import type { ResourceError } from 'lib/api/resources';
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
import * as cookies from 'lib/cookies';
|
||||
import sortTxs from 'lib/tx/sortTxs';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export const SORT_OPTIONS: Array<Option<TransactionsSortingValue>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Value ascending', id: 'value-asc' },
|
||||
{ title: 'Value descending', id: 'value-desc' },
|
||||
{ title: 'Fee ascending', id: 'fee-asc' },
|
||||
{ title: 'Fee descending', id: 'fee-desc' },
|
||||
];
|
||||
|
||||
type SortingValue = TransactionsSortingValue | undefined;
|
||||
|
||||
type HookResult = UseQueryResult<TxsResponse, ResourceError<unknown>> & {
|
||||
sorting: Sort;
|
||||
setSortByField: (field: 'val' | 'fee') => () => void;
|
||||
setSortByValue: (value: Sort | undefined) => void;
|
||||
sorting: SortingValue;
|
||||
setSortByValue: (value: SortingValue) => void;
|
||||
}
|
||||
|
||||
const sortTxs = (sorting: SortingValue) => (tx1: Transaction, tx2: Transaction) => {
|
||||
switch (sorting) {
|
||||
case 'value-desc':
|
||||
return compareBns(tx1.value, tx2.value);
|
||||
case 'value-asc':
|
||||
return compareBns(tx2.value, tx1.value);
|
||||
case 'fee-desc':
|
||||
return compareBns(tx1.fee.value || 0, tx2.fee.value || 0);
|
||||
case 'fee-asc':
|
||||
return compareBns(tx2.fee.value || 0, tx1.fee.value || 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
export default function useTxsSort(
|
||||
queryResult: UseQueryResult<TxsResponse, ResourceError<unknown>>,
|
||||
): HookResult {
|
||||
|
||||
const [ sorting, setSorting ] = React.useState<Sort>(cookies.get(cookies.NAMES.TXS_SORT) as Sort);
|
||||
const [ sorting, setSorting ] = React.useState<SortingValue>(cookies.get(cookies.NAMES.TXS_SORT) as SortingValue);
|
||||
|
||||
const setSortByField = React.useCallback((field: 'val' | 'fee') => () => {
|
||||
if (queryResult.isPlaceholderData) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSorting((prevVal) => {
|
||||
let newVal: Sort = '';
|
||||
if (field === 'val') {
|
||||
if (prevVal === 'val-asc') {
|
||||
newVal = '';
|
||||
} else if (prevVal === 'val-desc') {
|
||||
newVal = 'val-asc';
|
||||
} else {
|
||||
newVal = 'val-desc';
|
||||
}
|
||||
}
|
||||
if (field === 'fee') {
|
||||
if (prevVal === 'fee-asc') {
|
||||
newVal = '';
|
||||
} else if (prevVal === 'fee-desc') {
|
||||
newVal = 'fee-asc';
|
||||
} else {
|
||||
newVal = 'fee-desc';
|
||||
}
|
||||
}
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal);
|
||||
return newVal;
|
||||
});
|
||||
}, [ queryResult.isPlaceholderData ]);
|
||||
|
||||
const setSortByValue = React.useCallback((value: Sort | undefined) => {
|
||||
setSorting((prevVal: Sort) => {
|
||||
let newVal: Sort = '';
|
||||
const setSortByValue = React.useCallback((value: SortingValue) => {
|
||||
setSorting((prevVal: SortingValue) => {
|
||||
let newVal: SortingValue = undefined;
|
||||
if (value !== prevVal) {
|
||||
newVal = value as Sort;
|
||||
newVal = value as SortingValue;
|
||||
}
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal);
|
||||
cookies.set(cookies.NAMES.TXS_SORT, newVal ? newVal : '');
|
||||
return newVal;
|
||||
});
|
||||
}, []);
|
||||
|
||||
return React.useMemo(() => {
|
||||
if (queryResult.isError || queryResult.isPending) {
|
||||
return { ...queryResult, setSortByField, setSortByValue, sorting };
|
||||
return { ...queryResult, setSortByValue, sorting };
|
||||
}
|
||||
|
||||
return {
|
||||
...queryResult,
|
||||
data: { ...queryResult.data, items: queryResult.data.items.slice().sort(sortTxs(sorting)) },
|
||||
setSortByField,
|
||||
setSortByValue,
|
||||
sorting,
|
||||
};
|
||||
}, [ queryResult, setSortByField, setSortByValue, sorting ]);
|
||||
}, [ queryResult, setSortByValue, sorting ]);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,23 +2,30 @@ import { Table, Tbody, Tr, Th, Link, Icon } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { VerifiedContract } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSorting, VerifiedContractsSortingField, VerifiedContractsSortingValue } from 'types/api/verifiedContracts';
|
||||
|
||||
import config from 'configs/app';
|
||||
import arrowIcon from 'icons/arrows/east.svg';
|
||||
import getNextSortValue from 'ui/shared/sort/getNextSortValue';
|
||||
import { default as Thead } from 'ui/shared/TheadSticky';
|
||||
import { SORT_SEQUENCE } from 'ui/verifiedContracts/utils';
|
||||
|
||||
import type { Sort, SortField } from './utils';
|
||||
import VerifiedContractsTableItem from './VerifiedContractsTableItem';
|
||||
|
||||
interface Props {
|
||||
data: Array<VerifiedContract>;
|
||||
sort: Sort | undefined;
|
||||
onSortToggle: (field: SortField) => () => void;
|
||||
sort: VerifiedContractsSortingValue | undefined;
|
||||
setSorting: (val: VerifiedContractsSortingValue | undefined) => void;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const VerifiedContractsTable = ({ data, sort, onSortToggle, isLoading }: Props) => {
|
||||
const sortIconTransform = sort?.includes('asc') ? 'rotate(-90deg)' : 'rotate(90deg)';
|
||||
const VerifiedContractsTable = ({ data, sort, setSorting, isLoading }: Props) => {
|
||||
const sortIconTransform = sort?.includes('asc' as VerifiedContractsSorting['order']) ? 'rotate(-90deg)' : 'rotate(90deg)';
|
||||
|
||||
const onSortToggle = React.useCallback((field: VerifiedContractsSortingField) => () => {
|
||||
const value = getNextSortValue<VerifiedContractsSortingField, VerifiedContractsSortingValue>(SORT_SEQUENCE, field)(sort);
|
||||
setSorting(value);
|
||||
}, [ sort, setSorting ]);
|
||||
|
||||
return (
|
||||
<Table variant="simple" size="sm">
|
||||
@@ -32,8 +39,8 @@ const VerifiedContractsTable = ({ data, sort, onSortToggle, isLoading }: Props)
|
||||
</Link>
|
||||
</Th>
|
||||
<Th width="130px" isNumeric>
|
||||
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs') } columnGap={ 1 }>
|
||||
{ sort?.includes('txs') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
|
||||
<Link display="flex" alignItems="center" justifyContent="flex-end" onClick={ isLoading ? undefined : onSortToggle('txs_count') } columnGap={ 1 }>
|
||||
{ sort?.includes('txs_count') && <Icon as={ arrowIcon } boxSize={ 4 } transform={ sortIconTransform }/> }
|
||||
Txs
|
||||
</Link>
|
||||
</Th>
|
||||
|
||||
@@ -1,42 +1,16 @@
|
||||
import type { VerifiedContract } from 'types/api/contracts';
|
||||
import type { VerifiedContractsSortingValue, VerifiedContractsSortingField } from 'types/api/verifiedContracts';
|
||||
|
||||
import compareBns from 'lib/bigint/compareBns';
|
||||
import { default as getNextSortValueShared } from 'ui/shared/sort/getNextSortValue';
|
||||
import type { Option } from 'ui/shared/sort/Sort';
|
||||
|
||||
export type SortField = 'balance' | 'txs';
|
||||
export type Sort = `${ SortField }-asc` | `${ SortField }-desc`;
|
||||
|
||||
export const SORT_OPTIONS: Array<Option<Sort>> = [
|
||||
export const SORT_OPTIONS: Array<Option<VerifiedContractsSortingValue>> = [
|
||||
{ title: 'Default', id: undefined },
|
||||
{ title: 'Balance descending', id: 'balance-desc' },
|
||||
{ title: 'Balance ascending', id: 'balance-asc' },
|
||||
{ title: 'Txs count descending', id: 'txs-desc' },
|
||||
{ title: 'Txs count ascending', id: 'txs-asc' },
|
||||
{ title: 'Txs count descending', id: 'txs_count-desc' },
|
||||
{ title: 'Txs count ascending', id: 'txs_count-asc' },
|
||||
];
|
||||
|
||||
const SORT_SEQUENCE: Record<SortField, Array<Sort | undefined>> = {
|
||||
export const SORT_SEQUENCE: Record<VerifiedContractsSortingField, Array<VerifiedContractsSortingValue | undefined>> = {
|
||||
balance: [ 'balance-desc', 'balance-asc', undefined ],
|
||||
txs: [ 'txs-desc', 'txs-asc', undefined ],
|
||||
};
|
||||
|
||||
export const getNextSortValue = (getNextSortValueShared<SortField, Sort>).bind(undefined, SORT_SEQUENCE);
|
||||
|
||||
export const sortFn = (sort: Sort | undefined) => (a: VerifiedContract, b: VerifiedContract) => {
|
||||
switch (sort) {
|
||||
case 'balance-asc':
|
||||
case 'balance-desc': {
|
||||
const result = compareBns(b.coin_balance, a.coin_balance) * (sort.includes('desc') ? 1 : -1);
|
||||
return a.coin_balance === b.coin_balance ? 0 : result;
|
||||
}
|
||||
|
||||
case 'txs-asc':
|
||||
case 'txs-desc': {
|
||||
const result = ((a.tx_count || 0) > (b.tx_count || 0) ? -1 : 1) * (sort.includes('desc') ? 1 : -1);
|
||||
return a.tx_count === b.tx_count ? 0 : result;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
txs_count: [ 'txs_count-desc', 'txs_count-asc', undefined ],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user