Skip to content

Commit

Permalink
Feat: change the pagination to cursor and add sorter --- NFT collecti…
Browse files Browse the repository at this point in the history
…ons (#737)

change the pagination to cursor and add sorter
  • Loading branch information
alexsupa597 authored Mar 23, 2023
1 parent c31cc49 commit 703b622
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 26 deletions.
2 changes: 1 addition & 1 deletion cypress/integration/tokens/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
142 changes: 117 additions & 25 deletions pages/nft-collections/index.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<GraphQLSchema.NftCollectionListItem>
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
Expand All @@ -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<NftCollectionListProps['erc721_udts']> =>
client
.request<NftCollectionListProps>(erc721ListQuery, variables)
Expand All @@ -72,27 +90,79 @@ const fetchErc721List = (variables: Variables): Promise<NftCollectionListProps['
},
}
})

const FILTER_KEYS = ['name']

const NftCollectionList = () => {
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<HTMLOrSVGElement>, type) => {
const {
dataset: { order },
} = e.currentTarget
push(handleUrlForPush({ type, order: order === 'DESC' ? 'ASC' : 'DESC' }))
}

const headers = ['token', 'address', 'holder_count', 'minted_count']

return (
<>
<SubpageHead subtitle={title} />
Expand All @@ -111,15 +181,37 @@ const NftCollectionList = () => {
<Table>
<thead>
<tr>
<th>
{t('token')}
<span>
<FilterMenu filterKeys={[FILTER_KEYS[0]]} />
</span>
</th>
<th>{t('address')} </th>
<th>{t('holder_count')} </th>
<th>{t('minted_count')}</th>
{headers.map(item => (
<th key={item}>
<span className={styles['header-name']}>{t(item)}</span>
{item === 'token' ? (
<>
<span className={styles['token-sorter']}>
<SortIcon
onClick={e => handleSorterClick(e, SortTypesEnum.name_sort)}
data-order={name_sort}
className={styles.sorter}
/>
</span>
<FilterMenu filterKeys={[FILTER_KEYS[0]]} />
</>
) : null}
{item === 'holder_count' ? (
<SortIcon
onClick={e => handleSorterClick(e, SortTypesEnum.holder_count_sort)}
data-order={holder_count_sort}
className={styles.sorter}
/>
) : null}
{item === 'minted_count' ? (
<SortIcon
onClick={e => handleSorterClick(e, SortTypesEnum.minted_count_sort)}
data-order={minted_count_sort}
className={styles.sorter}
/>
) : null}
</th>
))}
</tr>
</thead>
<tbody>
Expand Down
8 changes: 8 additions & 0 deletions pages/nft-collections/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,11 @@
.noRecords {
@include empty-list;
}

.header-name {
padding-right: 4px;
}

.token-sorter {
padding-right: 8px;
}

0 comments on commit 703b622

Please sign in to comment.