From fee36a378c3e1c403b388a3a0bb8e8f496410515 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Tue, 14 Jun 2022 02:35:51 -0700 Subject: [PATCH] Use firestore-based search for private instances --- web/components/contract-search.tsx | 7 +- web/pages/contract-search-firestore.tsx | 101 ++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 web/pages/contract-search-firestore.tsx diff --git a/web/components/contract-search.tsx b/web/components/contract-search.tsx index 34a00b76..4bdf4f53 100644 --- a/web/components/contract-search.tsx +++ b/web/components/contract-search.tsx @@ -19,7 +19,7 @@ import { ContractsGrid } from './contract/contracts-list' import { Row } from './layout/row' import { useEffect, useMemo, useRef, useState } from 'react' import { Spacer } from './layout/spacer' -import { ENV } from 'common/envs/constants' +import { ENV, IS_PRIVATE_MANIFOLD } from 'common/envs/constants' import { useUser } from 'web/hooks/use-user' import { useFollows } from 'web/hooks/use-follows' import { EditCategoriesButton } from './feed/category-selector' @@ -28,6 +28,7 @@ import { Tabs } from './layout/tabs' import { EditFollowingButton } from './following-button' import { track } from '@amplitude/analytics-browser' import { trackCallback } from 'web/lib/service/analytics' +import { ContractSearchFirestore } from 'web/pages/contract-search-firestore' const searchClient = algoliasearch( 'GJQPAYENIF', @@ -121,6 +122,10 @@ export function ContractSearch(props: { const indexName = `${indexPrefix}contracts-${sort}` + if (IS_PRIVATE_MANIFOLD) { + return + } + return ( diff --git a/web/pages/contract-search-firestore.tsx b/web/pages/contract-search-firestore.tsx new file mode 100644 index 00000000..f092d297 --- /dev/null +++ b/web/pages/contract-search-firestore.tsx @@ -0,0 +1,101 @@ +import { Answer } from 'common/answer' +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' + +export function ContractSearchFirestore(props: { + querySortOptions?: { + defaultSort: Sort + shouldLoadFromStorage?: boolean + } +}) { + const contracts = useContracts() + const { querySortOptions } = props + + const { initialSort, initialQuery } = useInitialQueryAndSort(querySortOptions) + const [sort, setSort] = useState(initialSort || 'newest') + const [query, setQuery] = useState(initialQuery) + + const queryWords = query.toLowerCase().split(' ') + function check(corpus: string) { + return queryWords.every((word) => corpus.toLowerCase().includes(word)) + } + + let matches = (contracts ?? []).filter( + (c) => + check(c.question) || + check(c.description) || + check(c.creatorName) || + check(c.creatorUsername) || + check(c.lowercaseTags.map((tag) => `#${tag}`).join(' ')) || + check( + ((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 === '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) + } + + 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} + showCloseTime={['close-date', 'closed'].includes(sort)} + /> + )} +
+ ) +}