import { Answer } from 'common/answer' import { searchInAny } from 'common/util/parse' import { sortBy } from 'lodash' import { useState } from 'react' import { ContractsGrid } from 'web/components/contract/contracts-list' import { LoadingIndicator } from 'web/components/loading-indicator' import { useContracts } from 'web/hooks/use-contracts' import { Sort, useInitialQueryAndSort, } from 'web/hooks/use-sort-and-query-params' const MAX_CONTRACTS_RENDERED = 100 export default function ContractSearchFirestore(props: { querySortOptions?: { defaultSort: Sort shouldLoadFromStorage?: boolean } additionalFilter?: { creatorId?: string tag?: string excludeContractIds?: string[] groupSlug?: string } }) { const contracts = useContracts() const { querySortOptions, additionalFilter } = props const { initialSort, initialQuery } = useInitialQueryAndSort(querySortOptions) const [sort, setSort] = useState(initialSort || 'newest') const [query, setQuery] = useState(initialQuery) let matches = (contracts ?? []).filter((c) => searchInAny( query, c.question, c.creatorName, c.lowercaseTags.map((tag) => `#${tag}`).join(' '), ((c as any).answers ?? []).map((answer: Answer) => answer.text).join(' ') ) ) if (sort === 'newest') { matches.sort((a, b) => b.createdTime - a.createdTime) } else if (sort === 'resolve-date') { matches = sortBy(matches, (contract) => -1 * (contract.resolutionTime ?? 0)) } else if (sort === 'oldest') { matches.sort((a, b) => a.createdTime - b.createdTime) } else if (sort === 'close-date') { matches = sortBy(matches, ({ volume24Hours }) => -1 * volume24Hours) matches = sortBy( matches, (contract) => (sort === 'close-date' ? -1 : 1) * (contract.closeTime ?? Infinity) ) } else if (sort === 'most-traded') { matches.sort((a, b) => b.volume - a.volume) } else if (sort === 'score') { matches.sort((a, b) => (b.popularityScore ?? 0) - (a.popularityScore ?? 0)) } else if (sort === '24-hour-vol') { // Use lodash for stable sort, so previous sort breaks all ties. matches = sortBy(matches, ({ volume7Days }) => -1 * volume7Days) matches = sortBy(matches, ({ volume24Hours }) => -1 * volume24Hours) } if (additionalFilter) { const { creatorId, tag, groupSlug, excludeContractIds } = additionalFilter if (creatorId) { matches = matches.filter((c) => c.creatorId === creatorId) } if (tag) { matches = matches.filter((c) => c.lowercaseTags.includes(tag.toLowerCase()) ) } if (groupSlug) { matches = matches.filter((c) => c.groupSlugs?.includes(groupSlug)) } if (excludeContractIds) { matches = matches.filter((c) => !excludeContractIds.includes(c.id)) } } matches = matches.slice(0, MAX_CONTRACTS_RENDERED) const showTime = ['close-date', 'closed'].includes(sort) ? 'close-date' : sort === 'resolve-date' ? 'resolve-date' : undefined return (
{/* Show a search input next to a sort dropdown */}
setQuery(e.target.value)} placeholder="Search markets" className="input input-bordered w-full" />
{contracts === undefined ? ( ) : ( {}} hasMore={false} showTime={showTime} /> )}
) }