Cleaner home page loading!
This commit is contained in:
		
							parent
							
								
									dc0b6dc6a6
								
							
						
					
					
						commit
						b0b1d72ba6
					
				|  | @ -8,12 +8,14 @@ import { | ||||||
|   getUserBetContracts, |   getUserBetContracts, | ||||||
|   getUserBetContractsQuery, |   getUserBetContractsQuery, | ||||||
|   listAllContracts, |   listAllContracts, | ||||||
|   trendingContractsQuery, |  | ||||||
| } from 'web/lib/firebase/contracts' | } from 'web/lib/firebase/contracts' | ||||||
| import { QueryClient, useQuery, useQueryClient } from 'react-query' | import { QueryClient, useQuery, useQueryClient } from 'react-query' | ||||||
| import { MINUTE_MS, sleep } from 'common/util/time' | import { MINUTE_MS, sleep } from 'common/util/time' | ||||||
| import { query, limit } from 'firebase/firestore' | import { | ||||||
| import { dailyScoreIndex } from 'web/lib/service/algolia' |   dailyScoreIndex, | ||||||
|  |   newIndex, | ||||||
|  |   trendingIndex, | ||||||
|  | } from 'web/lib/service/algolia' | ||||||
| import { CPMMBinaryContract } from 'common/contract' | import { CPMMBinaryContract } from 'common/contract' | ||||||
| import { zipObject } from 'lodash' | import { zipObject } from 'lodash' | ||||||
| 
 | 
 | ||||||
|  | @ -27,16 +29,50 @@ export const useContracts = () => { | ||||||
|   return contracts |   return contracts | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export const useTrendingContracts = (maxContracts: number) => { | ||||||
|  |   const { data } = useQuery(['trending-contracts', maxContracts], () => | ||||||
|  |     trendingIndex.search<CPMMBinaryContract>('', { | ||||||
|  |       facetFilters: ['isResolved:false'], | ||||||
|  |       hitsPerPage: maxContracts, | ||||||
|  |     }) | ||||||
|  |   ) | ||||||
|  |   if (!data) return undefined | ||||||
|  |   return data.hits | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const useNewContracts = (maxContracts: number) => { | ||||||
|  |   const { data } = useQuery(['newest-contracts', maxContracts], () => | ||||||
|  |     newIndex.search<CPMMBinaryContract>('', { | ||||||
|  |       facetFilters: ['isResolved:false'], | ||||||
|  |       hitsPerPage: maxContracts, | ||||||
|  |     }) | ||||||
|  |   ) | ||||||
|  |   if (!data) return undefined | ||||||
|  |   return data.hits | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const useContractsByDailyScoreNotBetOn = ( | ||||||
|  |   userId: string | null | undefined, | ||||||
|  |   maxContracts: number | ||||||
|  | ) => { | ||||||
|  |   const { data } = useQuery(['daily-score', userId, maxContracts], () => | ||||||
|  |     dailyScoreIndex.search<CPMMBinaryContract>('', { | ||||||
|  |       facetFilters: ['isResolved:false', `uniqueBettors:-${userId}`], | ||||||
|  |       hitsPerPage: maxContracts, | ||||||
|  |     }) | ||||||
|  |   ) | ||||||
|  |   if (!userId || !data) return undefined | ||||||
|  |   return data.hits.filter((c) => c.dailyScore) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export const useContractsByDailyScoreGroups = ( | export const useContractsByDailyScoreGroups = ( | ||||||
|   groupSlugs: string[] | undefined |   groupSlugs: string[] | undefined | ||||||
| ) => { | ) => { | ||||||
|   const facetFilters = ['isResolved:false'] |  | ||||||
| 
 |  | ||||||
|   const { data } = useQuery(['daily-score', groupSlugs], () => |   const { data } = useQuery(['daily-score', groupSlugs], () => | ||||||
|     Promise.all( |     Promise.all( | ||||||
|       (groupSlugs ?? []).map((slug) => |       (groupSlugs ?? []).map((slug) => | ||||||
|         dailyScoreIndex.search<CPMMBinaryContract>('', { |         dailyScoreIndex.search<CPMMBinaryContract>('', { | ||||||
|           facetFilters: [...facetFilters, `groupLinks.slug:${slug}`], |           facetFilters: ['isResolved:false', `groupLinks.slug:${slug}`], | ||||||
|         }) |         }) | ||||||
|       ) |       ) | ||||||
|     ) |     ) | ||||||
|  | @ -56,14 +92,6 @@ export const getCachedContracts = async () => | ||||||
|     staleTime: Infinity, |     staleTime: Infinity, | ||||||
|   }) |   }) | ||||||
| 
 | 
 | ||||||
| export const useTrendingContracts = (maxContracts: number) => { |  | ||||||
|   const result = useFirestoreQueryData( |  | ||||||
|     ['trending-contracts', maxContracts], |  | ||||||
|     query(trendingContractsQuery, limit(maxContracts)) |  | ||||||
|   ) |  | ||||||
|   return result.data |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export const useInactiveContracts = () => { | export const useInactiveContracts = () => { | ||||||
|   const [contracts, setContracts] = useState<Contract[] | undefined>() |   const [contracts, setContracts] = useState<Contract[] | undefined>() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,6 +14,8 @@ export const getIndexName = (sort: string) => { | ||||||
|   return `${indexPrefix}contracts-${sort}` |   return `${indexPrefix}contracts-${sort}` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export const trendingIndex = searchClient.initIndex(getIndexName('score')) | ||||||
|  | export const newIndex = searchClient.initIndex(getIndexName('newest')) | ||||||
| export const probChangeDescendingIndex = searchClient.initIndex( | export const probChangeDescendingIndex = searchClient.initIndex( | ||||||
|   getIndexName('prob-change-day') |   getIndexName('prob-change-day') | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ import { Dictionary, sortBy, sum } from 'lodash' | ||||||
| 
 | 
 | ||||||
| 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 { ContractSearch, SORTS } from 'web/components/contract-search' |  | ||||||
| import { User } from 'common/user' | import { User } from 'common/user' | ||||||
| import { useTracking } from 'web/hooks/use-tracking' | import { useTracking } from 'web/hooks/use-tracking' | ||||||
| import { track } from 'web/lib/service/analytics' | import { track } from 'web/lib/service/analytics' | ||||||
|  | @ -43,7 +42,12 @@ import { isArray, keyBy } from 'lodash' | ||||||
| import { usePrefetch } from 'web/hooks/use-prefetch' | import { usePrefetch } from 'web/hooks/use-prefetch' | ||||||
| import { Title } from 'web/components/title' | import { Title } from 'web/components/title' | ||||||
| import { CPMMBinaryContract } from 'common/contract' | import { CPMMBinaryContract } from 'common/contract' | ||||||
| import { useContractsByDailyScoreGroups } from 'web/hooks/use-contracts' | import { | ||||||
|  |   useContractsByDailyScoreNotBetOn, | ||||||
|  |   useContractsByDailyScoreGroups, | ||||||
|  |   useTrendingContracts, | ||||||
|  |   useNewContracts, | ||||||
|  | } from 'web/hooks/use-contracts' | ||||||
| import { ProfitBadge } from 'web/components/profit-badge' | import { ProfitBadge } from 'web/components/profit-badge' | ||||||
| import { LoadingIndicator } from 'web/components/loading-indicator' | import { LoadingIndicator } from 'web/components/loading-indicator' | ||||||
| 
 | 
 | ||||||
|  | @ -71,12 +75,18 @@ export default function Home() { | ||||||
|     } |     } | ||||||
|   }, [user, sections]) |   }, [user, sections]) | ||||||
| 
 | 
 | ||||||
|   const groups = useMemberGroupsSubscription(user) |   const trendingContracts = useTrendingContracts(6) | ||||||
|  |   const newContracts = useNewContracts(6) | ||||||
|  |   const dailyTrendingContracts = useContractsByDailyScoreNotBetOn(user?.id, 6) | ||||||
| 
 | 
 | ||||||
|  |   const groups = useMemberGroupsSubscription(user) | ||||||
|   const groupContracts = useContractsByDailyScoreGroups( |   const groupContracts = useContractsByDailyScoreGroups( | ||||||
|     groups?.map((g) => g.slug) |     groups?.map((g) => g.slug) | ||||||
|   ) |   ) | ||||||
| 
 | 
 | ||||||
|  |   const isLoading = | ||||||
|  |     !user || !trendingContracts || !newContracts || !dailyTrendingContracts | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Page> |     <Page> | ||||||
|       <Toaster /> |       <Toaster /> | ||||||
|  | @ -90,11 +100,15 @@ export default function Home() { | ||||||
|           <DailyStats user={user} /> |           <DailyStats user={user} /> | ||||||
|         </Row> |         </Row> | ||||||
| 
 | 
 | ||||||
|         {!user ? ( |         {isLoading ? ( | ||||||
|           <LoadingIndicator /> |           <LoadingIndicator /> | ||||||
|         ) : ( |         ) : ( | ||||||
|           <> |           <> | ||||||
|             {sections.map((section) => renderSection(section, user))} |             {renderSections(user, sections, { | ||||||
|  |               score: trendingContracts, | ||||||
|  |               newest: newContracts, | ||||||
|  |               'daily-trending': dailyTrendingContracts, | ||||||
|  |             })} | ||||||
| 
 | 
 | ||||||
|             <TrendingGroupsSection user={user} /> |             <TrendingGroupsSection user={user} /> | ||||||
| 
 | 
 | ||||||
|  | @ -118,8 +132,8 @@ export default function Home() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const HOME_SECTIONS = [ | const HOME_SECTIONS = [ | ||||||
|   { label: 'Daily movers', id: 'daily-movers' }, |  | ||||||
|   { label: 'Daily trending', id: 'daily-trending' }, |   { label: 'Daily trending', id: 'daily-trending' }, | ||||||
|  |   { label: 'Daily movers', id: 'daily-movers' }, | ||||||
|   { label: 'Trending', id: 'score' }, |   { label: 'Trending', id: 'score' }, | ||||||
|   { label: 'New', id: 'newest' }, |   { label: 'New', id: 'newest' }, | ||||||
| ] | ] | ||||||
|  | @ -128,11 +142,7 @@ export const getHomeItems = (sections: string[]) => { | ||||||
|   // Accommodate old home sections.
 |   // Accommodate old home sections.
 | ||||||
|   if (!isArray(sections)) sections = [] |   if (!isArray(sections)) sections = [] | ||||||
| 
 | 
 | ||||||
|   const items: { id: string; label: string; group?: Group }[] = [ |   const itemsById = keyBy(HOME_SECTIONS, 'id') | ||||||
|     ...HOME_SECTIONS, |  | ||||||
|   ] |  | ||||||
|   const itemsById = keyBy(items, 'id') |  | ||||||
| 
 |  | ||||||
|   const sectionItems = filterDefined(sections.map((id) => itemsById[id])) |   const sectionItems = filterDefined(sections.map((id) => itemsById[id])) | ||||||
| 
 | 
 | ||||||
|   // Add new home section items to the top.
 |   // Add new home section items to the top.
 | ||||||
|  | @ -140,7 +150,9 @@ export const getHomeItems = (sections: string[]) => { | ||||||
|     ...HOME_SECTIONS.filter((item) => !sectionItems.includes(item)) |     ...HOME_SECTIONS.filter((item) => !sectionItems.includes(item)) | ||||||
|   ) |   ) | ||||||
|   // Add unmentioned items to the end.
 |   // Add unmentioned items to the end.
 | ||||||
|   sectionItems.push(...items.filter((item) => !sectionItems.includes(item))) |   sectionItems.push( | ||||||
|  |     ...HOME_SECTIONS.filter((item) => !sectionItems.includes(item)) | ||||||
|  |   ) | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     sections: sectionItems, |     sections: sectionItems, | ||||||
|  | @ -148,28 +160,46 @@ export const getHomeItems = (sections: string[]) => { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function renderSection(section: { id: string; label: string }, user: User) { | function renderSections( | ||||||
|   const { id, label } = section |   user: User, | ||||||
|   if (id === 'daily-movers') { |   sections: { id: string; label: string }[], | ||||||
|     return <DailyMoversSection key={id} userId={user.id} /> |   sectionContracts: { | ||||||
|  |     'daily-trending': CPMMBinaryContract[] | ||||||
|  |     newest: CPMMBinaryContract[] | ||||||
|  |     score: CPMMBinaryContract[] | ||||||
|   } |   } | ||||||
|   if (id === 'daily-trending') | ) { | ||||||
|     return ( |   return ( | ||||||
|       <SearchSection |     <> | ||||||
|         key={id} |       {sections.map((s) => { | ||||||
|         label={label} |         const { id, label } = s | ||||||
|         sort={'daily-score'} |         if (id === 'daily-movers') { | ||||||
|         pill="personal" |           return <DailyMoversSection key={id} userId={user.id} /> | ||||||
|         user={user} |         } | ||||||
|       /> |         if (id === 'daily-trending') { | ||||||
|     ) |           return ( | ||||||
|   const sort = SORTS.find((sort) => sort.value === id) |             <ContractsSection | ||||||
|   if (sort) |               key={id} | ||||||
|     return ( |               label={label} | ||||||
|       <SearchSection key={id} label={label} sort={sort.value} user={user} /> |               contracts={sectionContracts[id]} | ||||||
|     ) |               sort="daily-score" | ||||||
| 
 |               showProbChange | ||||||
|   return null |             /> | ||||||
|  |           ) | ||||||
|  |         } | ||||||
|  |         const contracts = | ||||||
|  |           sectionContracts[s.id as keyof typeof sectionContracts] | ||||||
|  |         return ( | ||||||
|  |           <ContractsSection | ||||||
|  |             key={id} | ||||||
|  |             label={label} | ||||||
|  |             contracts={contracts} | ||||||
|  |             sort={id === 'daily-trending' ? 'daily-score' : (id as Sort)} | ||||||
|  |           /> | ||||||
|  |         ) | ||||||
|  |       })} | ||||||
|  |     </> | ||||||
|  |   ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function renderGroupSections( | function renderGroupSections( | ||||||
|  | @ -237,13 +267,14 @@ function SectionHeader(props: { | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function SearchSection(props: { | function ContractsSection(props: { | ||||||
|   label: string |   label: string | ||||||
|   user: User |   contracts: CPMMBinaryContract[] | ||||||
|   sort: Sort |   sort: Sort | ||||||
|   pill?: string |   pill?: string | ||||||
|  |   showProbChange?: boolean | ||||||
| }) { | }) { | ||||||
|   const { label, user, sort, pill } = props |   const { label, contracts, sort, pill, showProbChange } = props | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Col> |     <Col> | ||||||
|  | @ -251,14 +282,7 @@ function SearchSection(props: { | ||||||
|         label={label} |         label={label} | ||||||
|         href={`/search?s=${sort}${pill ? `&p=${pill}` : ''}`} |         href={`/search?s=${sort}${pill ? `&p=${pill}` : ''}`} | ||||||
|       /> |       /> | ||||||
|       <ContractSearch |       <ContractsGrid contracts={contracts} cardUIOptions={{ showProbChange }} /> | ||||||
|         user={user} |  | ||||||
|         defaultSort={sort} |  | ||||||
|         defaultPill={pill} |  | ||||||
|         noControls |  | ||||||
|         maxResults={6} |  | ||||||
|         persistPrefix={`home-${sort}`} |  | ||||||
|       /> |  | ||||||
|     </Col> |     </Col> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user