Sort & query url params (#17)
* Sort query in progress * Search and query url params!
This commit is contained in:
parent
b375256e96
commit
bad7a2b543
|
@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
40
web/hooks/use-sort-and-query-params.tsx
Normal file
40
web/hooks/use-sort-and-query-params.tsx
Normal 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,
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user