Load contracts at UserPage top level instead of in BetsList
This commit is contained in:
parent
f294189e20
commit
5e1ed17cdf
|
@ -1,5 +1,5 @@
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { uniq, groupBy, mapValues, sortBy, partition, sumBy } from 'lodash'
|
import { groupBy, mapValues, sortBy, partition, sumBy } from 'lodash'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useState } from 'react'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
@ -16,7 +16,6 @@ import { Col } from './layout/col'
|
||||||
import { Spacer } from './layout/spacer'
|
import { Spacer } from './layout/spacer'
|
||||||
import {
|
import {
|
||||||
Contract,
|
Contract,
|
||||||
getContractFromId,
|
|
||||||
contractPath,
|
contractPath,
|
||||||
getBinaryProbPercent,
|
getBinaryProbPercent,
|
||||||
} from 'web/lib/firebase/contracts'
|
} from 'web/lib/firebase/contracts'
|
||||||
|
@ -25,7 +24,6 @@ import { UserLink } from './user-page'
|
||||||
import { sellBet } from 'web/lib/firebase/api'
|
import { sellBet } from 'web/lib/firebase/api'
|
||||||
import { ConfirmationButton } from './confirmation-button'
|
import { ConfirmationButton } from './confirmation-button'
|
||||||
import { OutcomeLabel, YesLabel, NoLabel } from './outcome-label'
|
import { OutcomeLabel, YesLabel, NoLabel } from './outcome-label'
|
||||||
import { filterDefined } from 'common/util/array'
|
|
||||||
import { LoadingIndicator } from './loading-indicator'
|
import { LoadingIndicator } from './loading-indicator'
|
||||||
import { SiteLink } from './site-link'
|
import { SiteLink } from './site-link'
|
||||||
import {
|
import {
|
||||||
|
@ -56,9 +54,10 @@ const CONTRACTS_PER_PAGE = 20
|
||||||
export function BetsList(props: {
|
export function BetsList(props: {
|
||||||
user: User
|
user: User
|
||||||
bets: Bet[] | undefined
|
bets: Bet[] | undefined
|
||||||
|
contractsById: { [id: string]: Contract } | undefined
|
||||||
hideBetsBefore?: number
|
hideBetsBefore?: number
|
||||||
}) {
|
}) {
|
||||||
const { user, bets: allBets, hideBetsBefore } = props
|
const { user, bets: allBets, contractsById, hideBetsBefore } = props
|
||||||
|
|
||||||
const signedInUser = useUser()
|
const signedInUser = useUser()
|
||||||
const isYourBets = user.id === signedInUser?.id
|
const isYourBets = user.id === signedInUser?.id
|
||||||
|
@ -69,7 +68,6 @@ export function BetsList(props: {
|
||||||
() => allBets?.filter((bet) => bet.createdTime >= (hideBetsBefore ?? 0)),
|
() => allBets?.filter((bet) => bet.createdTime >= (hideBetsBefore ?? 0)),
|
||||||
[allBets, hideBetsBefore]
|
[allBets, hideBetsBefore]
|
||||||
)
|
)
|
||||||
const [contracts, setContracts] = useState<Contract[] | undefined>()
|
|
||||||
|
|
||||||
const [sort, setSort] = useState<BetSort>('newest')
|
const [sort, setSort] = useState<BetSort>('newest')
|
||||||
const [filter, setFilter] = useState<BetFilter>('open')
|
const [filter, setFilter] = useState<BetFilter>('open')
|
||||||
|
@ -77,39 +75,26 @@ export function BetsList(props: {
|
||||||
const start = page * CONTRACTS_PER_PAGE
|
const start = page * CONTRACTS_PER_PAGE
|
||||||
const end = start + CONTRACTS_PER_PAGE
|
const end = start + CONTRACTS_PER_PAGE
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (bets) {
|
|
||||||
const contractIds = uniq(bets.map((bet) => bet.contractId))
|
|
||||||
|
|
||||||
let disposed = false
|
|
||||||
Promise.all(contractIds.map((id) => getContractFromId(id))).then(
|
|
||||||
(contracts) => {
|
|
||||||
if (!disposed) setContracts(filterDefined(contracts))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
disposed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [bets])
|
|
||||||
|
|
||||||
const getTime = useTimeSinceFirstRender()
|
const getTime = useTimeSinceFirstRender()
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (bets && contracts) {
|
if (bets && contractsById) {
|
||||||
trackLatency('portfolio', getTime())
|
trackLatency('portfolio', getTime())
|
||||||
}
|
}
|
||||||
}, [bets, contracts, getTime])
|
}, [bets, contractsById, getTime])
|
||||||
|
|
||||||
if (!bets || !contracts) {
|
if (!bets || !contractsById) {
|
||||||
return <LoadingIndicator />
|
return <LoadingIndicator />
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bets.length === 0) return <NoBets user={user} />
|
if (bets.length === 0) return <NoBets user={user} />
|
||||||
|
|
||||||
// Decending creation time.
|
// Decending creation time.
|
||||||
bets.sort((bet1, bet2) => bet2.createdTime - bet1.createdTime)
|
bets.sort((bet1, bet2) => bet2.createdTime - bet1.createdTime)
|
||||||
const contractBets = groupBy(bets, 'contractId')
|
const contractBets = groupBy(bets, 'contractId')
|
||||||
const contractsById = Object.fromEntries(contracts.map((c) => [c.id, c]))
|
|
||||||
|
// Keep only contracts that have bets.
|
||||||
|
const contracts = Object.values(contractsById).filter(
|
||||||
|
(c) => contractBets[c.id]
|
||||||
|
)
|
||||||
|
|
||||||
const contractsMetrics = mapValues(contractBets, (bets, contractId) => {
|
const contractsMetrics = mapValues(contractBets, (bets, contractId) => {
|
||||||
const contract = contractsById[contractId]
|
const contract = contractsById[contractId]
|
||||||
|
|
|
@ -9,16 +9,25 @@ import { UserLink } from './user-page'
|
||||||
import { User } from 'common/user'
|
import { User } from 'common/user'
|
||||||
import { Col } from './layout/col'
|
import { Col } from './layout/col'
|
||||||
import { Linkify } from './linkify'
|
import { Linkify } from './linkify'
|
||||||
|
import { groupBy } from 'lodash'
|
||||||
|
|
||||||
export function UserCommentsList(props: {
|
export function UserCommentsList(props: {
|
||||||
user: User
|
user: User
|
||||||
commentsByUniqueContracts: Map<Contract, Comment[]>
|
comments: Comment[]
|
||||||
|
contractsById: { [id: string]: Contract }
|
||||||
}) {
|
}) {
|
||||||
const { commentsByUniqueContracts } = props
|
const { comments, contractsById } = props
|
||||||
|
const commentsByContract = groupBy(comments, 'contractId')
|
||||||
|
|
||||||
|
const contractCommentPairs = Object.entries(commentsByContract)
|
||||||
|
.map(
|
||||||
|
([contractId, comments]) => [contractsById[contractId], comments] as const
|
||||||
|
)
|
||||||
|
.filter(([contract]) => contract)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col className={'bg-white'}>
|
<Col className={'bg-white'}>
|
||||||
{Array.from(commentsByUniqueContracts).map(([contract, comments]) => (
|
{contractCommentPairs.map(([contract, comments]) => (
|
||||||
<div key={contract.id} className={'border-width-1 border-b p-5'}>
|
<div key={contract.id} className={'border-width-1 border-b p-5'}>
|
||||||
<div className={'mb-2 text-sm text-indigo-700'}>
|
<div className={'mb-2 text-sm text-indigo-700'}>
|
||||||
<SiteLink href={contractPath(contract)}>
|
<SiteLink href={contractPath(contract)}>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { uniq } from 'lodash'
|
import { Dictionary, keyBy, uniq } from 'lodash'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { LinkIcon } from '@heroicons/react/solid'
|
import { LinkIcon } from '@heroicons/react/solid'
|
||||||
|
@ -39,6 +39,7 @@ import { PortfolioMetrics } from 'common/user'
|
||||||
import { ReferralsButton } from 'web/components/referrals-button'
|
import { ReferralsButton } from 'web/components/referrals-button'
|
||||||
import { GroupsButton } from 'web/components/groups/groups-button'
|
import { GroupsButton } from 'web/components/groups/groups-button'
|
||||||
import { PortfolioValueSection } from './portfolio/portfolio-value-section'
|
import { PortfolioValueSection } from './portfolio/portfolio-value-section'
|
||||||
|
import { filterDefined } from 'common/util/array'
|
||||||
|
|
||||||
export function UserLink(props: {
|
export function UserLink(props: {
|
||||||
name: string
|
name: string
|
||||||
|
@ -72,7 +73,7 @@ export function UserPage(props: {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const isCurrentUser = user.id === currentUser?.id
|
const isCurrentUser = user.id === currentUser?.id
|
||||||
const bannerUrl = user.bannerUrl ?? defaultBannerUrl(user.id)
|
const bannerUrl = user.bannerUrl ?? defaultBannerUrl(user.id)
|
||||||
const [usersComments, setUsersComments] = useState<Comment[]>([] as Comment[])
|
const [usersComments, setUsersComments] = useState<Comment[] | undefined>()
|
||||||
const [usersContracts, setUsersContracts] = useState<Contract[] | 'loading'>(
|
const [usersContracts, setUsersContracts] = useState<Contract[] | 'loading'>(
|
||||||
'loading'
|
'loading'
|
||||||
)
|
)
|
||||||
|
@ -85,9 +86,9 @@ export function UserPage(props: {
|
||||||
const [portfolioHistory, setUsersPortfolioHistory] = useState<
|
const [portfolioHistory, setUsersPortfolioHistory] = useState<
|
||||||
PortfolioMetrics[]
|
PortfolioMetrics[]
|
||||||
>([])
|
>([])
|
||||||
const [commentsByContract, setCommentsByContract] = useState<
|
const [contractsById, setContractsById] = useState<
|
||||||
Map<Contract, Comment[]> | 'loading'
|
Dictionary<Contract> | undefined
|
||||||
>('loading')
|
>()
|
||||||
const [showConfetti, setShowConfetti] = useState(false)
|
const [showConfetti, setShowConfetti] = useState(false)
|
||||||
const { width, height } = useWindowSize()
|
const { width, height } = useWindowSize()
|
||||||
|
|
||||||
|
@ -106,25 +107,21 @@ export function UserPage(props: {
|
||||||
|
|
||||||
// TODO: display comments on groups
|
// TODO: display comments on groups
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const uniqueContractIds = uniq(
|
if (usersComments && userBets) {
|
||||||
usersComments.map((comment) => comment.contractId)
|
const uniqueContractIds = uniq([
|
||||||
)
|
...usersComments.map((comment) => comment.contractId),
|
||||||
|
...(userBets?.map((bet) => bet.contractId) ?? []),
|
||||||
|
])
|
||||||
Promise.all(
|
Promise.all(
|
||||||
uniqueContractIds.map(
|
uniqueContractIds.map((contractId) =>
|
||||||
(contractId) => contractId && getContractFromId(contractId)
|
contractId ? getContractFromId(contractId) : undefined
|
||||||
)
|
)
|
||||||
).then((contracts) => {
|
).then((contracts) => {
|
||||||
const commentsByContract = new Map<Contract, Comment[]>()
|
const contractsById = keyBy(filterDefined(contracts), 'id')
|
||||||
contracts.forEach((contract) => {
|
setContractsById(contractsById)
|
||||||
if (!contract) return
|
|
||||||
commentsByContract.set(
|
|
||||||
contract,
|
|
||||||
usersComments.filter((comment) => comment.contractId === contract.id)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
setCommentsByContract(commentsByContract)
|
}
|
||||||
})
|
}, [userBets, usersComments])
|
||||||
}, [usersComments])
|
|
||||||
|
|
||||||
const yourFollows = useFollows(currentUser?.id)
|
const yourFollows = useFollows(currentUser?.id)
|
||||||
const isFollowing = yourFollows?.includes(user.id)
|
const isFollowing = yourFollows?.includes(user.id)
|
||||||
|
@ -265,7 +262,7 @@ export function UserPage(props: {
|
||||||
|
|
||||||
<Spacer h={10} />
|
<Spacer h={10} />
|
||||||
|
|
||||||
{usersContracts !== 'loading' && commentsByContract != 'loading' ? (
|
{usersContracts !== 'loading' && contractsById && usersComments ? (
|
||||||
<Tabs
|
<Tabs
|
||||||
currentPageForAnalytics={'profile'}
|
currentPageForAnalytics={'profile'}
|
||||||
labelClassName={'pb-2 pt-1 '}
|
labelClassName={'pb-2 pt-1 '}
|
||||||
|
@ -296,7 +293,8 @@ export function UserPage(props: {
|
||||||
content: (
|
content: (
|
||||||
<UserCommentsList
|
<UserCommentsList
|
||||||
user={user}
|
user={user}
|
||||||
commentsByUniqueContracts={commentsByContract}
|
contractsById={contractsById}
|
||||||
|
comments={usersComments}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
tabIcon: (
|
tabIcon: (
|
||||||
|
@ -314,6 +312,7 @@ export function UserPage(props: {
|
||||||
user={user}
|
user={user}
|
||||||
bets={userBets}
|
bets={userBets}
|
||||||
hideBetsBefore={isCurrentUser ? 0 : JUNE_1_2022}
|
hideBetsBefore={isCurrentUser ? 0 : JUNE_1_2022}
|
||||||
|
contractsById={contractsById}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user