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