Skip to content

Commit

Permalink
Prettify loading bets
Browse files Browse the repository at this point in the history
  • Loading branch information
IanPhilips committed Nov 28, 2024
1 parent 6255d0a commit 79ed1cd
Showing 1 changed file with 75 additions and 62 deletions.
137 changes: 75 additions & 62 deletions web/components/bet/user-bets-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { OrderTable } from 'web/components/bet/order-book'
import { Button, IconButton } from 'web/components/buttons/button'
import { PillButton } from 'web/components/buttons/pill-button'
import { ContractStatusLabel } from 'web/components/contract/contracts-table'
import { Row } from 'web/components/layout/row'
import { OutcomeLabel } from 'web/components/outcome-label'
import { ProfitBadge } from 'web/components/profit-badge'
import { RelativeTimestamp } from 'web/components/relative-timestamp'
Expand All @@ -50,15 +49,15 @@ import { getUserContractsMetricsWithContracts } from 'web/lib/api/api'
import { User } from 'web/lib/firebase/users'
import { SweepiesCoin } from 'web/public/custom-components/sweepiesCoin'
import DropdownMenu from '../comments/dropdown-menu'
import { Col } from '../layout/col'
import { Modal, MODAL_CLASS } from '../layout/modal'
import { SweepsToggle } from '../sweeps/sweeps-toggle'
import { useSweepstakes } from '../sweepstakes-provider'
import { LoadingIndicator } from '../widgets/loading-indicator'
import { linkClass } from '../widgets/site-link'
import { Tooltip } from '../widgets/tooltip'
import { floatingEqual } from 'common/util/math'

import { Col } from '../layout/col'
import { Row } from '../layout/row'
type BetSort =
| 'newest'
| 'profit'
Expand Down Expand Up @@ -87,7 +86,7 @@ export function UserBetsTable(props: { user: User }) {
Dictionary<ContractMetric> | undefined
>(undefined, `user-contract-metrics-${user.id}`)

const [initialContracts, setInitialContracts] = usePersistentInMemoryState<
const [contracts, setContracts] = usePersistentInMemoryState<
Contract[] | undefined
>(undefined, `user-contract-metrics-contracts-${user.id}`)

Expand All @@ -105,7 +104,7 @@ export function UserBetsTable(props: { user: User }) {
}).then((res) => {
const { contracts, metricsByContract } = res
setMetricsByContract(metricsByContract)
setInitialContracts((c) =>
setContracts((c) =>
uniqBy(buildArray([...(c ?? []), ...contracts]), 'id')
)
})
Expand All @@ -123,11 +122,11 @@ export function UserBetsTable(props: { user: User }) {
}).then((betsWithContracts) => {
const { contracts, betsByContract } = betsWithContracts
setOpenLimitBetsByContract(betsByContract)
setInitialContracts((c) =>
setContracts((c) =>
uniqBy(buildArray([...(c ?? []), ...contracts]), 'id')
)
})
}, [setInitialContracts, setOpenLimitBetsByContract, user.id, isAuth])
}, [setContracts, setOpenLimitBetsByContract, user.id, isAuth])

const [filter, setFilter] = usePersistentLocalState<BetFilter>(
'open',
Expand All @@ -151,13 +150,11 @@ export function UserBetsTable(props: { user: User }) {
}

const nullableMetricsByContract = useMemo(() => {
if (!metricsByContract || !initialContracts) {
if (!metricsByContract || !contracts) {
return undefined
}
// check if we have any contracts that don't have contractMetrics, if so, add them in as getContractBetNullMetrics
const missingContracts = initialContracts.filter(
(c) => !metricsByContract[c.id]
)
const missingContracts = contracts.filter((c) => !metricsByContract[c.id])
const missingMetrics = Object.fromEntries(
missingContracts.map((c) => [c.id, getContractBetNullMetrics()])
)
Expand All @@ -166,23 +163,13 @@ export function UserBetsTable(props: { user: User }) {
...metricsByContract,
...missingMetrics,
}
}, [JSON.stringify(initialContracts), metricsByContract])

if (
!nullableMetricsByContract ||
!openLimitBetsByContract ||
!initialContracts
) {
return <LoadingIndicator />
}
if (Object.keys(nullableMetricsByContract).length === 0)
return <NoBets user={user} />
}, [JSON.stringify(contracts), metricsByContract])

const contracts = query
? initialContracts.filter((c) =>
const queriedContracts = query
? contracts?.filter((c) =>
searchInAny(query, c.question, c.creatorName, c.creatorUsername)
)
: initialContracts
: contracts

const FILTERS: Record<BetFilter, (c: Contract) => boolean> = {
resolved: (c) => !!c.resolutionTime,
Expand All @@ -193,25 +180,29 @@ export function UserBetsTable(props: { user: User }) {
sold: () => true,
limit_bet: (c) => FILTERS.open(c),
}

const filteredContracts = contracts
.filter(FILTERS[filter])
.filter((c) => {
if (filter === 'all') return true
const { totalShares } = nullableMetricsByContract[c.id]
// The hasShares wasn't properly set for null metrics for a while, so using totalShares instead
const hasShares = Object.values(totalShares).some(
(s) => !floatingEqual(s, 0)
)
if (filter === 'sold') return !hasShares
if (filter === 'limit_bet')
return openLimitBetsByContract[c.id]?.length > 0
return hasShares
})
.filter((c) => {
if (!prefersPlay) return c.token === 'CASH'
else return c.token === 'MANA' || !c.token
})
const loaded =
nullableMetricsByContract && openLimitBetsByContract && contracts

const filteredContracts = loaded
? queriedContracts
?.filter(FILTERS[filter])
.filter((c) => {
if (filter === 'all') return true
const { totalShares } = nullableMetricsByContract[c.id]
// The hasShares wasn't properly set for null metrics for a while, so using totalShares instead
const hasShares = Object.values(totalShares).some(
(s) => !floatingEqual(s, 0)
)
if (filter === 'sold') return !hasShares
if (filter === 'limit_bet')
return openLimitBetsByContract[c.id]?.length > 0
return hasShares
})
.filter((c) => {
if (!prefersPlay) return c.token === 'CASH'
else return c.token === 'MANA' || !c.token
})
: []

return (
<Col>
Expand Down Expand Up @@ -257,24 +248,26 @@ export function UserBetsTable(props: { user: User }) {
</Col>
</div>

<Col className="divide-ink-300 mt-2 divide-y">
{filteredContracts.length === 0 ? (
<NoMatchingBets />
) : (
nullableMetricsByContract && (
<BetsTable
contracts={filteredContracts as CPMMContract[]}
metricsByContractId={nullableMetricsByContract}
openLimitBetsByContract={openLimitBetsByContract}
page={page}
user={user}
setPage={setPage}
filter={filter}
signedInUser={signedInUser}
/>
)
)}
</Col>
{!loaded ? (
<Col className="divide-ink-300 mt-6 divide-y">
<LoadingMetricRow />
<LoadingMetricRow />
<LoadingMetricRow />
</Col>
) : Object.keys(nullableMetricsByContract).length === 0 ? (
<NoBets user={user} />
) : (
<BetsTable
contracts={filteredContracts as CPMMContract[]}
metricsByContractId={nullableMetricsByContract}
openLimitBetsByContract={openLimitBetsByContract}
page={page}
user={user}
setPage={setPage}
filter={filter}
signedInUser={signedInUser}
/>
)}
</Col>
)
}
Expand Down Expand Up @@ -930,3 +923,23 @@ const Header = (props: {
</Row>
)
}

function LoadingMetricRow() {
return (
<div className="animate-pulse py-4">
<Row className="mb-2 items-center gap-2">
<div className="h-6 w-6 rounded-full bg-gray-200" />
<div className="h-4 w-48 rounded bg-gray-200 sm:w-96" />
</Row>

<Row className="mt-2 justify-between gap-4">
<div className="h-4 w-16 rounded bg-gray-200" />
<div className="h-4 w-20 rounded bg-gray-200" />
<div className="h-4 w-20 rounded bg-gray-200" />
<div className="h-4 w-16 rounded bg-gray-200" />
<div className="h-4 w-16 rounded bg-gray-200" />
<div className="h-4 w-16 rounded bg-gray-200" />
</Row>
</div>
)
}

0 comments on commit 79ed1cd

Please sign in to comment.