Rewrite useQueryAndSortParams
machinery to be faster/simpler/better (#758)
* Rewrite useQueryAndSortParams machinery to be faster/simpler/better * Politely debounce Algolia querying * Tidy some stuff up * Style changes suggested by James
This commit is contained in:
parent
5d14d79e6e
commit
972f215f0c
|
@ -4,11 +4,7 @@ import { SearchOptions } from '@algolia/client-search'
|
||||||
|
|
||||||
import { Contract } from 'common/contract'
|
import { Contract } from 'common/contract'
|
||||||
import { User } from 'common/user'
|
import { User } from 'common/user'
|
||||||
import {
|
import { Sort, useQuery, useSort } from '../hooks/use-sort-and-query-params'
|
||||||
QuerySortOptions,
|
|
||||||
Sort,
|
|
||||||
useQueryAndSortParams,
|
|
||||||
} from '../hooks/use-sort-and-query-params'
|
|
||||||
import {
|
import {
|
||||||
ContractHighlightOptions,
|
ContractHighlightOptions,
|
||||||
ContractsGrid,
|
ContractsGrid,
|
||||||
|
@ -24,11 +20,25 @@ import ContractSearchFirestore from 'web/pages/contract-search-firestore'
|
||||||
import { useMemberGroups } from 'web/hooks/use-group'
|
import { useMemberGroups } from 'web/hooks/use-group'
|
||||||
import { NEW_USER_GROUP_SLUGS } from 'common/group'
|
import { NEW_USER_GROUP_SLUGS } from 'common/group'
|
||||||
import { PillButton } from './buttons/pill-button'
|
import { PillButton } from './buttons/pill-button'
|
||||||
import { sortBy } from 'lodash'
|
import { debounce, sortBy } from 'lodash'
|
||||||
import { DEFAULT_CATEGORY_GROUPS } from 'common/categories'
|
import { DEFAULT_CATEGORY_GROUPS } from 'common/categories'
|
||||||
import { Col } from './layout/col'
|
import { Col } from './layout/col'
|
||||||
|
import { safeLocalStorage } from 'web/lib/util/local'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
|
// TODO: this obviously doesn't work with SSR, common sense would suggest
|
||||||
|
// that we should save things like this in cookies so the server has them
|
||||||
|
|
||||||
|
const MARKETS_SORT = 'markets_sort'
|
||||||
|
|
||||||
|
function setSavedSort(s: Sort) {
|
||||||
|
safeLocalStorage()?.setItem(MARKETS_SORT, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSavedSort() {
|
||||||
|
return safeLocalStorage()?.getItem(MARKETS_SORT) as Sort | null | undefined
|
||||||
|
}
|
||||||
|
|
||||||
const searchClient = algoliasearch(
|
const searchClient = algoliasearch(
|
||||||
'GJQPAYENIF',
|
'GJQPAYENIF',
|
||||||
'75c28fc084a80e1129d427d470cf41a3'
|
'75c28fc084a80e1129d427d470cf41a3'
|
||||||
|
@ -47,7 +57,6 @@ const sortOptions = [
|
||||||
{ label: 'Close date', value: 'close-date' },
|
{ label: 'Close date', value: 'close-date' },
|
||||||
{ label: 'Resolve date', value: 'resolve-date' },
|
{ label: 'Resolve date', value: 'resolve-date' },
|
||||||
]
|
]
|
||||||
export const DEFAULT_SORT = 'score'
|
|
||||||
|
|
||||||
type filter = 'personal' | 'open' | 'closed' | 'resolved' | 'all'
|
type filter = 'personal' | 'open' | 'closed' | 'resolved' | 'all'
|
||||||
|
|
||||||
|
@ -68,7 +77,8 @@ type AdditionalFilter = {
|
||||||
|
|
||||||
export function ContractSearch(props: {
|
export function ContractSearch(props: {
|
||||||
user?: User | null
|
user?: User | null
|
||||||
querySortOptions?: { defaultFilter?: filter } & QuerySortOptions
|
defaultSort?: Sort
|
||||||
|
defaultFilter?: filter
|
||||||
additionalFilter?: AdditionalFilter
|
additionalFilter?: AdditionalFilter
|
||||||
highlightOptions?: ContractHighlightOptions
|
highlightOptions?: ContractHighlightOptions
|
||||||
onContractClick?: (contract: Contract) => void
|
onContractClick?: (contract: Contract) => void
|
||||||
|
@ -79,10 +89,13 @@ export function ContractSearch(props: {
|
||||||
hideQuickBet?: boolean
|
hideQuickBet?: boolean
|
||||||
}
|
}
|
||||||
headerClassName?: string
|
headerClassName?: string
|
||||||
|
useQuerySortLocalStorage?: boolean
|
||||||
|
useQuerySortUrlParams?: boolean
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
querySortOptions,
|
defaultSort,
|
||||||
|
defaultFilter,
|
||||||
additionalFilter,
|
additionalFilter,
|
||||||
onContractClick,
|
onContractClick,
|
||||||
overrideGridClassName,
|
overrideGridClassName,
|
||||||
|
@ -90,6 +103,8 @@ export function ContractSearch(props: {
|
||||||
cardHideOptions,
|
cardHideOptions,
|
||||||
highlightOptions,
|
highlightOptions,
|
||||||
headerClassName,
|
headerClassName,
|
||||||
|
useQuerySortLocalStorage,
|
||||||
|
useQuerySortUrlParams,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const [numPages, setNumPages] = useState(1)
|
const [numPages, setNumPages] = useState(1)
|
||||||
|
@ -132,31 +147,33 @@ export function ContractSearch(props: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onSearchParametersChanged = useRef(
|
||||||
|
debounce((params) => {
|
||||||
|
searchParameters.current = params
|
||||||
|
performQuery(true)
|
||||||
|
}, 100)
|
||||||
|
).current
|
||||||
|
|
||||||
const contracts = pages
|
const contracts = pages
|
||||||
.flat()
|
.flat()
|
||||||
.filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id))
|
.filter((c) => !additionalFilter?.excludeContractIds?.includes(c.id))
|
||||||
|
|
||||||
if (IS_PRIVATE_MANIFOLD || process.env.NEXT_PUBLIC_FIREBASE_EMULATE) {
|
if (IS_PRIVATE_MANIFOLD || process.env.NEXT_PUBLIC_FIREBASE_EMULATE) {
|
||||||
return (
|
return <ContractSearchFirestore additionalFilter={additionalFilter} />
|
||||||
<ContractSearchFirestore
|
|
||||||
querySortOptions={querySortOptions}
|
|
||||||
additionalFilter={additionalFilter}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col className="h-full">
|
<Col className="h-full">
|
||||||
<ContractSearchControls
|
<ContractSearchControls
|
||||||
className={headerClassName}
|
className={headerClassName}
|
||||||
|
defaultSort={defaultSort}
|
||||||
|
defaultFilter={defaultFilter}
|
||||||
additionalFilter={additionalFilter}
|
additionalFilter={additionalFilter}
|
||||||
hideOrderSelector={hideOrderSelector}
|
hideOrderSelector={hideOrderSelector}
|
||||||
querySortOptions={querySortOptions}
|
useQuerySortLocalStorage={useQuerySortLocalStorage}
|
||||||
|
useQuerySortUrlParams={useQuerySortUrlParams}
|
||||||
user={user}
|
user={user}
|
||||||
onSearchParametersChanged={(params) => {
|
onSearchParametersChanged={onSearchParametersChanged}
|
||||||
searchParameters.current = params
|
|
||||||
performQuery(true)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<ContractsGrid
|
<ContractsGrid
|
||||||
contracts={pages.length === 0 ? undefined : contracts}
|
contracts={pages.length === 0 ? undefined : contracts}
|
||||||
|
@ -173,23 +190,40 @@ export function ContractSearch(props: {
|
||||||
|
|
||||||
function ContractSearchControls(props: {
|
function ContractSearchControls(props: {
|
||||||
className?: string
|
className?: string
|
||||||
|
defaultSort?: Sort
|
||||||
|
defaultFilter?: filter
|
||||||
additionalFilter?: AdditionalFilter
|
additionalFilter?: AdditionalFilter
|
||||||
hideOrderSelector?: boolean
|
hideOrderSelector?: boolean
|
||||||
onSearchParametersChanged: (params: SearchParameters) => void
|
onSearchParametersChanged: (params: SearchParameters) => void
|
||||||
querySortOptions?: { defaultFilter?: filter } & QuerySortOptions
|
useQuerySortLocalStorage?: boolean
|
||||||
|
useQuerySortUrlParams?: boolean
|
||||||
user?: User | null
|
user?: User | null
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
className,
|
className,
|
||||||
|
defaultSort,
|
||||||
|
defaultFilter,
|
||||||
additionalFilter,
|
additionalFilter,
|
||||||
hideOrderSelector,
|
hideOrderSelector,
|
||||||
onSearchParametersChanged,
|
onSearchParametersChanged,
|
||||||
querySortOptions,
|
useQuerySortLocalStorage,
|
||||||
|
useQuerySortUrlParams,
|
||||||
user,
|
user,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const { query, setQuery, sort, setSort } =
|
const savedSort = useQuerySortLocalStorage ? getSavedSort() : null
|
||||||
useQueryAndSortParams(querySortOptions)
|
const initialSort = savedSort ?? defaultSort ?? 'score'
|
||||||
|
const querySortOpts = { useUrl: !!useQuerySortUrlParams }
|
||||||
|
const [sort, setSort] = useSort(initialSort, querySortOpts)
|
||||||
|
const [query, setQuery] = useQuery('', querySortOpts)
|
||||||
|
const [filter, setFilter] = useState<filter>(defaultFilter ?? 'open')
|
||||||
|
const [pillFilter, setPillFilter] = useState<string | undefined>(undefined)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (useQuerySortLocalStorage) {
|
||||||
|
setSavedSort(sort)
|
||||||
|
}
|
||||||
|
}, [sort])
|
||||||
|
|
||||||
const follows = useFollows(user?.id)
|
const follows = useFollows(user?.id)
|
||||||
const memberGroups = (useMemberGroups(user?.id) ?? []).filter(
|
const memberGroups = (useMemberGroups(user?.id) ?? []).filter(
|
||||||
|
@ -208,12 +242,6 @@ function ContractSearchControls(props: {
|
||||||
const pillGroups: { name: string; slug: string }[] =
|
const pillGroups: { name: string; slug: string }[] =
|
||||||
memberPillGroups.length > 0 ? memberPillGroups : DEFAULT_CATEGORY_GROUPS
|
memberPillGroups.length > 0 ? memberPillGroups : DEFAULT_CATEGORY_GROUPS
|
||||||
|
|
||||||
const [filter, setFilter] = useState<filter>(
|
|
||||||
querySortOptions?.defaultFilter ?? 'open'
|
|
||||||
)
|
|
||||||
|
|
||||||
const [pillFilter, setPillFilter] = useState<string | undefined>(undefined)
|
|
||||||
|
|
||||||
const additionalFilters = [
|
const additionalFilters = [
|
||||||
additionalFilter?.creatorId
|
additionalFilter?.creatorId
|
||||||
? `creatorId:${additionalFilter.creatorId}`
|
? `creatorId:${additionalFilter.creatorId}`
|
||||||
|
|
|
@ -106,11 +106,8 @@ export function CreatorContractsList(props: {
|
||||||
return (
|
return (
|
||||||
<ContractSearch
|
<ContractSearch
|
||||||
user={user}
|
user={user}
|
||||||
querySortOptions={{
|
defaultSort="newest"
|
||||||
defaultSort: 'newest',
|
defaultFilter="all"
|
||||||
defaultFilter: 'all',
|
|
||||||
shouldLoadFromStorage: false,
|
|
||||||
}}
|
|
||||||
additionalFilter={{
|
additionalFilter={{
|
||||||
creatorId: creator.id,
|
creatorId: creator.id,
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -69,7 +69,6 @@ export function MarketModal(props: {
|
||||||
'flex grid grid-cols-1 sm:grid-cols-2 flex-col gap-3 p-1'
|
'flex grid grid-cols-1 sm:grid-cols-2 flex-col gap-3 p-1'
|
||||||
}
|
}
|
||||||
cardHideOptions={{ hideGroupLink: true, hideQuickBet: true }}
|
cardHideOptions={{ hideGroupLink: true, hideQuickBet: true }}
|
||||||
querySortOptions={{ disableQueryString: true }}
|
|
||||||
highlightOptions={{
|
highlightOptions={{
|
||||||
contractIds: contracts.map((c) => c.id),
|
contractIds: contracts.map((c) => c.id),
|
||||||
highlightClassName:
|
highlightClassName:
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import { debounce } from 'lodash'
|
import { useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { NextRouter, useRouter } from 'next/router'
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
|
||||||
import { DEFAULT_SORT } from 'web/components/contract-search'
|
|
||||||
|
|
||||||
const MARKETS_SORT = 'markets_sort'
|
|
||||||
|
|
||||||
export type Sort =
|
export type Sort =
|
||||||
| 'newest'
|
| 'newest'
|
||||||
|
@ -15,92 +11,55 @@ export type Sort =
|
||||||
| 'last-updated'
|
| 'last-updated'
|
||||||
| 'score'
|
| 'score'
|
||||||
|
|
||||||
export function getSavedSort() {
|
type UpdatedQueryParams = { [k: string]: string }
|
||||||
// TODO: this obviously doesn't work with SSR, common sense would suggest
|
type QuerySortOpts = { useUrl: boolean }
|
||||||
// that we should save things like this in cookies so the server has them
|
|
||||||
if (typeof window !== 'undefined') {
|
function withURLParams(location: Location, params: UpdatedQueryParams) {
|
||||||
return localStorage.getItem(MARKETS_SORT) as Sort | null
|
const newParams = new URLSearchParams(location.search)
|
||||||
} else {
|
for (const [k, v] of Object.entries(params)) {
|
||||||
return null
|
if (!v) {
|
||||||
|
newParams.delete(k)
|
||||||
|
} else {
|
||||||
|
newParams.set(k, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
const newUrl = new URL(location.href)
|
||||||
|
newUrl.search = newParams.toString()
|
||||||
|
return newUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QuerySortOptions {
|
function updateURL(params: UpdatedQueryParams) {
|
||||||
defaultSort?: Sort
|
// see relevant discussion here https://github.com/vercel/next.js/discussions/18072
|
||||||
shouldLoadFromStorage?: boolean
|
const url = withURLParams(window.location, params).toString()
|
||||||
/** Use normal react state instead of url query string */
|
const updatedState = { ...window.history.state, as: url, url }
|
||||||
disableQueryString?: boolean
|
window.history.replaceState(updatedState, '', url)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useQueryAndSortParams({
|
function getStringURLParam(router: NextRouter, k: string) {
|
||||||
defaultSort = DEFAULT_SORT,
|
const v = router.query[k]
|
||||||
shouldLoadFromStorage = true,
|
return typeof v === 'string' ? v : null
|
||||||
disableQueryString,
|
}
|
||||||
}: QuerySortOptions = {}) {
|
|
||||||
|
export function useQuery(defaultQuery: string, opts?: QuerySortOpts) {
|
||||||
|
const useUrl = opts?.useUrl ?? false
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const initialQuery = useUrl ? getStringURLParam(router, 'q') : null
|
||||||
const { s: sort, q: query } = router.query as {
|
const [query, setQuery] = useState(initialQuery ?? defaultQuery)
|
||||||
q?: string
|
if (!useUrl) {
|
||||||
s?: Sort
|
return [query, setQuery] as const
|
||||||
}
|
} else {
|
||||||
|
return [query, (q: string) => (setQuery(q), updateURL({ q }))] as const
|
||||||
const setSort = (sort: Sort | undefined) => {
|
}
|
||||||
router.replace({ query: { ...router.query, s: sort } }, undefined, {
|
}
|
||||||
shallow: true,
|
|
||||||
})
|
export function useSort(defaultSort: Sort, opts?: QuerySortOpts) {
|
||||||
if (shouldLoadFromStorage) {
|
const useUrl = opts?.useUrl ?? false
|
||||||
localStorage.setItem(MARKETS_SORT, sort || '')
|
const router = useRouter()
|
||||||
}
|
const initialSort = useUrl ? (getStringURLParam(router, 's') as Sort) : null
|
||||||
}
|
const [sort, setSort] = useState(initialSort ?? defaultSort)
|
||||||
|
if (!useUrl) {
|
||||||
const [queryState, setQueryState] = useState(query)
|
return [sort, setSort] as const
|
||||||
|
} else {
|
||||||
useEffect(() => {
|
return [sort, (s: Sort) => (setSort(s), updateURL({ s }))] as const
|
||||||
setQueryState(query)
|
|
||||||
}, [query])
|
|
||||||
|
|
||||||
// Debounce router query update.
|
|
||||||
const pushQuery = useMemo(
|
|
||||||
() =>
|
|
||||||
debounce((query: string | undefined) => {
|
|
||||||
const queryObj = { ...router.query, q: query }
|
|
||||||
if (!query) delete queryObj.q
|
|
||||||
router.replace({ query: queryObj }, undefined, {
|
|
||||||
shallow: true,
|
|
||||||
})
|
|
||||||
}, 100),
|
|
||||||
[router]
|
|
||||||
)
|
|
||||||
|
|
||||||
const setQuery = (query: string | undefined) => {
|
|
||||||
setQueryState(query)
|
|
||||||
if (!disableQueryString) {
|
|
||||||
pushQuery(query)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// If there's no sort option, then set the one from localstorage
|
|
||||||
if (router.isReady && !sort && shouldLoadFromStorage) {
|
|
||||||
const localSort = localStorage.getItem(MARKETS_SORT) as Sort
|
|
||||||
if (localSort && localSort !== defaultSort) {
|
|
||||||
// Use replace to not break navigating back.
|
|
||||||
router.replace(
|
|
||||||
{ query: { ...router.query, s: localSort } },
|
|
||||||
undefined,
|
|
||||||
{ shallow: true }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// use normal state if querydisableQueryString
|
|
||||||
const [sortState, setSortState] = useState(defaultSort)
|
|
||||||
|
|
||||||
return {
|
|
||||||
sort: disableQueryString ? sortState : sort ?? defaultSort,
|
|
||||||
query: queryState ?? '',
|
|
||||||
setSort: disableQueryString ? setSortState : setSort,
|
|
||||||
setQuery,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,11 @@ import { searchInAny } from 'common/util/parse'
|
||||||
import { sortBy } from 'lodash'
|
import { sortBy } from 'lodash'
|
||||||
import { ContractsGrid } from 'web/components/contract/contracts-grid'
|
import { ContractsGrid } from 'web/components/contract/contracts-grid'
|
||||||
import { useContracts } from 'web/hooks/use-contracts'
|
import { useContracts } from 'web/hooks/use-contracts'
|
||||||
import {
|
import { Sort, useQuery, useSort } from 'web/hooks/use-sort-and-query-params'
|
||||||
QuerySortOptions,
|
|
||||||
Sort,
|
|
||||||
useQueryAndSortParams,
|
|
||||||
} from 'web/hooks/use-sort-and-query-params'
|
|
||||||
|
|
||||||
const MAX_CONTRACTS_RENDERED = 100
|
const MAX_CONTRACTS_RENDERED = 100
|
||||||
|
|
||||||
export default function ContractSearchFirestore(props: {
|
export default function ContractSearchFirestore(props: {
|
||||||
querySortOptions?: QuerySortOptions
|
|
||||||
additionalFilter?: {
|
additionalFilter?: {
|
||||||
creatorId?: string
|
creatorId?: string
|
||||||
tag?: string
|
tag?: string
|
||||||
|
@ -21,10 +16,9 @@ export default function ContractSearchFirestore(props: {
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
const contracts = useContracts()
|
const contracts = useContracts()
|
||||||
const { querySortOptions, additionalFilter } = props
|
const { additionalFilter } = props
|
||||||
|
const [query, setQuery] = useQuery('', { useUrl: true })
|
||||||
const { query, setQuery, sort, setSort } =
|
const [sort, setSort] = useSort('score', { useUrl: true })
|
||||||
useQueryAndSortParams(querySortOptions)
|
|
||||||
|
|
||||||
let matches = (contracts ?? []).filter((c) =>
|
let matches = (contracts ?? []).filter((c) =>
|
||||||
searchInAny(
|
searchInAny(
|
||||||
|
|
|
@ -31,7 +31,6 @@ import { CreateQuestionButton } from 'web/components/create-question-button'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { LoadingIndicator } from 'web/components/loading-indicator'
|
import { LoadingIndicator } from 'web/components/loading-indicator'
|
||||||
import { Modal } from 'web/components/layout/modal'
|
import { Modal } from 'web/components/layout/modal'
|
||||||
import { getSavedSort } from 'web/hooks/use-sort-and-query-params'
|
|
||||||
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
import { ChoicesToggleGroup } from 'web/components/choices-toggle-group'
|
||||||
import { toast } from 'react-hot-toast'
|
import { toast } from 'react-hot-toast'
|
||||||
import { useCommentsOnGroup } from 'web/hooks/use-comments'
|
import { useCommentsOnGroup } from 'web/hooks/use-comments'
|
||||||
|
@ -196,11 +195,8 @@ export default function GroupPage(props: {
|
||||||
const questionsTab = (
|
const questionsTab = (
|
||||||
<ContractSearch
|
<ContractSearch
|
||||||
user={user}
|
user={user}
|
||||||
querySortOptions={{
|
defaultSort={'newest'}
|
||||||
shouldLoadFromStorage: true,
|
defaultFilter={'open'}
|
||||||
defaultSort: getSavedSort() ?? 'newest',
|
|
||||||
defaultFilter: 'open',
|
|
||||||
}}
|
|
||||||
additionalFilter={{ groupSlug: group.slug }}
|
additionalFilter={{ groupSlug: group.slug }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,8 +4,7 @@ import { PlusSmIcon } from '@heroicons/react/solid'
|
||||||
|
|
||||||
import { Page } from 'web/components/page'
|
import { Page } from 'web/components/page'
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
import { getSavedSort } from 'web/hooks/use-sort-and-query-params'
|
import { ContractSearch } from 'web/components/contract-search'
|
||||||
import { ContractSearch, DEFAULT_SORT } from 'web/components/contract-search'
|
|
||||||
import { Contract } from 'common/contract'
|
import { Contract } from 'common/contract'
|
||||||
import { User } from 'common/user'
|
import { User } from 'common/user'
|
||||||
import { ContractPageContent } from './[username]/[contractSlug]'
|
import { ContractPageContent } from './[username]/[contractSlug]'
|
||||||
|
@ -35,10 +34,8 @@ const Home = (props: { auth: { user: User } }) => {
|
||||||
<Col className="mx-auto w-full p-2">
|
<Col className="mx-auto w-full p-2">
|
||||||
<ContractSearch
|
<ContractSearch
|
||||||
user={user}
|
user={user}
|
||||||
querySortOptions={{
|
useQuerySortLocalStorage={true}
|
||||||
shouldLoadFromStorage: true,
|
useQuerySortUrlParams={true}
|
||||||
defaultSort: getSavedSort() ?? DEFAULT_SORT,
|
|
||||||
}}
|
|
||||||
onContractClick={(c) => {
|
onContractClick={(c) => {
|
||||||
// Show contract without navigating to contract page.
|
// Show contract without navigating to contract page.
|
||||||
setContract(c)
|
setContract(c)
|
||||||
|
|
|
@ -15,11 +15,8 @@ export default function TagPage() {
|
||||||
<Title text={`#${tag}`} />
|
<Title text={`#${tag}`} />
|
||||||
<ContractSearch
|
<ContractSearch
|
||||||
user={user}
|
user={user}
|
||||||
querySortOptions={{
|
defaultSort="newest"
|
||||||
defaultSort: 'newest',
|
defaultFilter="all"
|
||||||
defaultFilter: 'all',
|
|
||||||
shouldLoadFromStorage: true,
|
|
||||||
}}
|
|
||||||
additionalFilter={{ tag }}
|
additionalFilter={{ tag }}
|
||||||
/>
|
/>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user