Sort & query url params (#17)

* Sort query in progress

* Search and query url params!
This commit is contained in:
James Grugett 2022-01-02 16:46:04 -06:00 committed by GitHub
parent b375256e96
commit bad7a2b543
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 22 deletions

View File

@ -3,17 +3,13 @@ import Link from 'next/link'
import clsx from 'clsx'
import { useEffect, useState } from 'react'
import {
compute,
Contract,
listContracts,
path,
} from '../lib/firebase/contracts'
import { compute, Contract, listContracts } from '../lib/firebase/contracts'
import { User } from '../lib/firebase/users'
import { Col } from './layout/col'
import { SiteLink } from './site-link'
import { parseTags } from '../lib/util/parse'
import { ContractCard } from './contract-card'
import { Sort, useQueryAndSortParams } from '../hooks/use-sort-and-query-params'
function ContractsGrid(props: { contracts: Contract[] }) {
const [resolvedContracts, activeContracts] = _.partition(
@ -61,7 +57,7 @@ function CreatorContractsGrid(props: { contracts: Contract[] }) {
const { creatorUsername, creatorName } = byCreator[creatorId][0]
return (
<Col className="gap-4">
<Col className="gap-4" key={creatorUsername}>
<SiteLink className="text-lg" href={`/${creatorUsername}`}>
{creatorName}
</SiteLink>
@ -116,7 +112,7 @@ function TagContractsGrid(props: { contracts: Contract[] }) {
<Col className="gap-6">
{tags.map((tag) => {
return (
<Col className="gap-4">
<Col className="gap-4" key={tag}>
<SiteLink className="text-lg" href={`/tag/${tag}`}>
#{tag}
</SiteLink>
@ -152,17 +148,15 @@ function TagContractsGrid(props: { contracts: Contract[] }) {
const MAX_CONTRACTS_DISPLAYED = 99
type Sort = 'creator' | 'tag' | 'createdTime' | 'pool' | 'resolved' | 'all'
export function SearchableGrid(props: {
contracts: Contract[]
defaultSort?: Sort
query: string
setQuery: (query: string) => void
sort: Sort
setSort: (sort: Sort) => void
byOneCreator?: boolean
}) {
const { contracts, defaultSort, byOneCreator } = props
const [query, setQuery] = useState('')
const [sort, setSort] = useState(
defaultSort || (byOneCreator ? 'pool' : 'creator')
)
const { contracts, query, setQuery, sort, setSort, byOneCreator } = props
function check(corpus: String) {
return corpus.toLowerCase().includes(query.toLowerCase())
@ -175,9 +169,9 @@ export function SearchableGrid(props: {
check(c.creatorUsername)
)
if (sort === 'createdTime' || sort === 'resolved' || sort === 'all') {
if (sort === 'newest' || sort === 'resolved' || sort === 'all') {
matches.sort((a, b) => b.createdTime - a.createdTime)
} else if (sort === 'pool' || sort === 'creator' || sort === 'tag') {
} else if (sort === 'most-traded' || sort === 'creator' || sort === 'tag') {
matches.sort((a, b) => compute(b).truePool - compute(a).truePool)
}
@ -213,8 +207,8 @@ export function SearchableGrid(props: {
<option value="creator">By creator</option>
)}
<option value="tag">By tag</option>
<option value="pool">Most traded</option>
<option value="createdTime">Newest first</option>
<option value="most-traded">Most traded</option>
<option value="newest">Newest</option>
<option value="resolved">Resolved</option>
</select>
</div>
@ -234,6 +228,10 @@ export function CreatorContractsList(props: { creator: User }) {
const { creator } = props
const [contracts, setContracts] = useState<Contract[] | 'loading'>('loading')
const { query, setQuery, sort, setSort } = useQueryAndSortParams({
defaultSort: 'all',
})
useEffect(() => {
if (creator?.id) {
// TODO: stream changes from firestore
@ -243,5 +241,14 @@ export function CreatorContractsList(props: { creator: User }) {
if (contracts === 'loading') return <></>
return <SearchableGrid contracts={contracts} byOneCreator defaultSort="all" />
return (
<SearchableGrid
contracts={contracts}
byOneCreator
query={query}
setQuery={setQuery}
sort={sort}
setSort={setSort}
/>
)
}

View File

@ -0,0 +1,40 @@
import { useRouter } from 'next/router'
export type Sort =
| 'creator'
| 'tag'
| 'newest'
| 'most-traded'
| 'resolved'
| 'all'
export function useQueryAndSortParams(options?: { defaultSort: Sort }) {
const router = useRouter()
const { s: sort, q: query } = router.query as {
q?: string
s?: Sort
}
const setSort = (sort: Sort | undefined) => {
router.query.s = sort
router.push(router, undefined, { shallow: true })
}
const setQuery = (query: string | undefined) => {
if (query) {
router.query.q = query
} else {
delete router.query.q
}
router.push(router, undefined, { shallow: true })
}
return {
sort: sort ?? options?.defaultSort ?? 'creator',
query: query ?? '',
setSort,
setQuery,
}
}

View File

@ -13,6 +13,7 @@ import { SearchableGrid } from '../components/contracts-list'
import { Col } from '../components/layout/col'
import { NavBar } from '../components/nav-bar'
import Link from 'next/link'
import { useQueryAndSortParams } from '../hooks/use-sort-and-query-params'
export default function LandingPage() {
return (
@ -159,13 +160,20 @@ function FeaturesSection() {
function ExploreMarketsSection() {
const contracts = useContracts()
const { query, setQuery, sort, setSort } = useQueryAndSortParams()
return (
<div className="max-w-4xl px-4 py-8 mx-auto">
<p className="my-12 text-3xl leading-8 font-extrabold tracking-tight text-indigo-700 sm:text-4xl">
Explore our markets
</p>
<SearchableGrid contracts={contracts === 'loading' ? [] : contracts} />
<SearchableGrid
contracts={contracts === 'loading' ? [] : contracts}
query={query}
setQuery={setQuery}
sort={sort}
setSort={setSort}
/>
</div>
)
}

View File

@ -1,6 +1,7 @@
import { SearchableGrid } from '../components/contracts-list'
import { Page } from '../components/page'
import { useContracts } from '../hooks/use-contracts'
import { useQueryAndSortParams } from '../hooks/use-sort-and-query-params'
import { Contract, listAllContracts } from '../lib/firebase/contracts'
export async function getStaticProps() {
@ -17,12 +18,17 @@ export async function getStaticProps() {
export default function Markets(props: { contracts: Contract[] }) {
const contracts = useContracts()
const { query, setQuery, sort, setSort } = useQueryAndSortParams()
return (
<Page>
{(props.contracts || contracts !== 'loading') && (
<SearchableGrid
contracts={contracts === 'loading' ? props.contracts : contracts}
query={query}
setQuery={setQuery}
sort={sort}
setSort={setSort}
/>
)}
</Page>

View File

@ -3,6 +3,7 @@ import { SearchableGrid } from '../../components/contracts-list'
import { Page } from '../../components/page'
import { Title } from '../../components/title'
import { useContracts } from '../../hooks/use-contracts'
import { useQueryAndSortParams } from '../../hooks/use-sort-and-query-params'
export default function TagPage() {
const router = useRouter()
@ -18,13 +19,23 @@ export default function TagPage() {
)
}
const { query, setQuery, sort, setSort } = useQueryAndSortParams({
defaultSort: 'most-traded',
})
return (
<Page>
<Title text={`#${tag}`} />
{contracts === 'loading' ? (
<></>
) : (
<SearchableGrid contracts={contracts} />
<SearchableGrid
contracts={contracts}
query={query}
setQuery={setQuery}
sort={sort}
setSort={setSort}
/>
)}
</Page>
)