From 703b6223258a8dd43f9d509b0775a9e8352f46f4 Mon Sep 17 00:00:00 2001 From: Jun Ma Date: Thu, 23 Mar 2023 13:06:50 +0800 Subject: [PATCH] Feat: change the pagination to cursor and add sorter --- NFT collections (#737) change the pagination to cursor and add sorter --- cypress/integration/tokens/index.spec.ts | 2 +- pages/nft-collections/index.tsx | 142 +++++++++++++++++++---- pages/nft-collections/styles.module.scss | 8 ++ 3 files changed, 126 insertions(+), 26 deletions(-) diff --git a/cypress/integration/tokens/index.spec.ts b/cypress/integration/tokens/index.spec.ts index abf30517d..5c5f8435b 100644 --- a/cypress/integration/tokens/index.spec.ts +++ b/cypress/integration/tokens/index.spec.ts @@ -202,7 +202,7 @@ context('Tokens List Pages Tests', () => { .first() .find('td') .first() - .should('contain.text', 'YokaiswapNFT') + .should('contain.text', '57us test Collection(57u)') .next() .should(field => { expect(field.text()).to.match(FULL_ADDRESS_REGEX) diff --git a/pages/nft-collections/index.tsx b/pages/nft-collections/index.tsx index 16bc728f8..dcc4746b5 100644 --- a/pages/nft-collections/index.tsx +++ b/pages/nft-collections/index.tsx @@ -1,4 +1,5 @@ import type { GetStaticProps } from 'next' +import { useEffect } from 'react' import { useRouter } from 'next/router' import NextLink from 'next/link' import { useTranslation } from 'next-i18next' @@ -13,22 +14,46 @@ import Pagination from 'components/SimplePagination' import TokenLogo from 'components/TokenLogo' import HashLink from 'components/HashLink' import Address from 'components/TruncatedAddress' +import FilterMenu from 'components/FilterMenu' + import { SIZES } from 'components/PageSize' import NoDataIcon from 'assets/icons/no-data.svg' -import { client, GraphQLSchema } from 'utils' +import SortIcon from 'assets/icons/sort.svg' +import { client, GraphQLSchema, handleSorterArrayAboutPath, handleSorterArrayInOrder, sorterType } from 'utils' import styles from './styles.module.scss' -import FilterMenu from 'components/FilterMenu' +interface Variables { + name: string | null + before: string | null + after: string | null + limit: number + sorter: UdtsSorterInput[] | [] +} + +type UdtsSorterInput = { + sort_type: 'ASC' | 'DESC' + sort_value: 'EX_HOLDERS_COUNT' | 'ID' | 'NAME' | 'SUPPLY' | 'MINTED_COUNT' +} interface NftCollectionListProps { erc721_udts: { entries: Array metadata: GraphQLSchema.PageMetadata } } +enum SortTypesEnum { + holder_count_sort = 'holder_count_sort', + name_sort = 'name_sort', + minted_count_sort = 'minted_count_sort', +} +enum UdtsSorterValueEnum { + holder_count_sort = 'EX_HOLDERS_COUNT', + name_sort = 'NAME', + minted_count_sort = 'MINTED_COUNT', +} const erc721ListQuery = gql` - query ($limit: Int, $name: String, $before: String, $after: String) { - erc721_udts(input: { limit: $limit, fuzzy_name: $name, before: $before, after: $after }) { + query ($limit: Int, $name: String, $before: String, $after: String, $sorter: UdtsSorterInput) { + erc721_udts(input: { limit: $limit, fuzzy_name: $name, before: $before, after: $after, sorter: $sorter }) { entries { id name @@ -50,13 +75,6 @@ const erc721ListQuery = gql` } ` -interface Variables { - name: string | null - before: string | null - after: string | null - limit: number -} - const fetchErc721List = (variables: Variables): Promise => client .request(erc721ListQuery, variables) @@ -72,27 +90,79 @@ const fetchErc721List = (variables: Variables): Promise { - const [t] = useTranslation(['nft', 'common', 'list']) const { - query: { before = null, after = null, name = null, page_size = SIZES[1] }, + push, + asPath, + query: { + before = null, + after = null, + name = null, + page_size = SIZES[1], + holder_count_sort, + name_sort, + minted_count_sort, + ...restQuery + }, } = useRouter() - + const [t] = useTranslation(['nft', 'common', 'list']) const title = t(`nft-collections`) + + const sorters = ['holder_count_sort', 'name_sort', 'minted_count_sort'] + const DEFAULT_SORTERS: sorterType[] = [ + { type: 'name_sort', order: 'ASC' }, + { type: 'holder_count_sort', order: 'ASC' }, + { type: 'minted_count_sort', order: 'ASC' }, + ] + + const sorterArrayFromPath = handleSorterArrayAboutPath(asPath, sorters) + + // get a sorter array to query listdata from server + const sorterArrayForQuery = handleSorterArrayAboutPath(asPath, sorters, UdtsSorterValueEnum) + + const handleUrlForPush = (clickedSorter: sorterType = null) => { + const searchParams = new URLSearchParams({ + ...restQuery, + page_size: page_size as string, + }) + + const orderedSorter = handleSorterArrayInOrder(clickedSorter ? sorterArrayFromPath : DEFAULT_SORTERS, clickedSorter) + for (const item of orderedSorter) { + searchParams.append(item.type, item.order) + } + + return `${asPath.split('?')[0] ?? ''}?${searchParams}` + } + useEffect(() => { + if (!sorterArrayFromPath.length) { + push(handleUrlForPush()) + } + }, [sorterArrayFromPath]) + const { isLoading, data: list } = useQuery( - ['erc721-list', page_size, before, after, name], + ['erc721-list', page_size, before, after, name, holder_count_sort, name_sort, minted_count_sort], () => fetchErc721List({ before: before as string, after: after as string, name: name ? `${name}%` : null, limit: Number.isNaN(!page_size) ? +SIZES[1] : +page_size, + sorter: sorterArrayForQuery, }), { refetchInterval: 10000 }, ) + const handleSorterClick = (e: React.MouseEvent, type) => { + const { + dataset: { order }, + } = e.currentTarget + push(handleUrlForPush({ type, order: order === 'DESC' ? 'ASC' : 'DESC' })) + } + + const headers = ['token', 'address', 'holder_count', 'minted_count'] + return ( <> @@ -111,15 +181,37 @@ const NftCollectionList = () => { - - - - + {headers.map(item => ( + + ))} diff --git a/pages/nft-collections/styles.module.scss b/pages/nft-collections/styles.module.scss index fa187fd4a..6483d1334 100644 --- a/pages/nft-collections/styles.module.scss +++ b/pages/nft-collections/styles.module.scss @@ -95,3 +95,11 @@ .noRecords { @include empty-list; } + +.header-name { + padding-right: 4px; +} + +.token-sorter { + padding-right: 8px; +}
- {t('token')} - - - - {t('address')} {t('holder_count')} {t('minted_count')} + {t(item)} + {item === 'token' ? ( + <> + + handleSorterClick(e, SortTypesEnum.name_sort)} + data-order={name_sort} + className={styles.sorter} + /> + + + + ) : null} + {item === 'holder_count' ? ( + handleSorterClick(e, SortTypesEnum.holder_count_sort)} + data-order={holder_count_sort} + className={styles.sorter} + /> + ) : null} + {item === 'minted_count' ? ( + handleSorterClick(e, SortTypesEnum.minted_count_sort)} + data-order={minted_count_sort} + className={styles.sorter} + /> + ) : null} +