Clean up rendering of user bets list (#694)
* Clean up crufty markup in bets list * Don't render bet tables in bets list until expanded * Don't look up unfilled bets for every sell button
This commit is contained in:
parent
7e4f4b9a87
commit
ad46a60c4f
|
@ -3,6 +3,7 @@ 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'
|
||||||
|
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/solid'
|
||||||
|
|
||||||
import { Bet } from 'web/lib/firebase/bets'
|
import { Bet } from 'web/lib/firebase/bets'
|
||||||
import { User } from 'web/lib/firebase/users'
|
import { User } from 'web/lib/firebase/users'
|
||||||
|
@ -277,13 +278,7 @@ function ContractBets(props: {
|
||||||
bets
|
bets
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<div
|
<div tabIndex={0} className="relative bg-white p-4 pr-6">
|
||||||
tabIndex={0}
|
|
||||||
className={clsx(
|
|
||||||
'collapse collapse-arrow relative bg-white p-4 pr-6',
|
|
||||||
collapsed ? 'collapse-close' : 'collapse-open pb-2'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Row
|
<Row
|
||||||
className="cursor-pointer flex-wrap gap-2"
|
className="cursor-pointer flex-wrap gap-2"
|
||||||
onClick={() => setCollapsed((collapsed) => !collapsed)}
|
onClick={() => setCollapsed((collapsed) => !collapsed)}
|
||||||
|
@ -300,10 +295,11 @@ function ContractBets(props: {
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Show carrot for collapsing. Hack the positioning. */}
|
{/* Show carrot for collapsing. Hack the positioning. */}
|
||||||
<div
|
{collapsed ? (
|
||||||
className="collapse-title absolute h-0 min-h-0 w-0 p-0"
|
<ChevronDownIcon className="absolute top-5 right-4 h-6 w-6" />
|
||||||
style={{ top: -10, right: 0 }}
|
) : (
|
||||||
/>
|
<ChevronUpIcon className="absolute top-5 right-4 h-6 w-6" />
|
||||||
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Row className="flex-1 items-center gap-2 text-sm text-gray-500">
|
<Row className="flex-1 items-center gap-2 text-sm text-gray-500">
|
||||||
|
@ -335,55 +331,42 @@ function ContractBets(props: {
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
<Row className="mr-5 justify-end sm:mr-8">
|
<Col className="mr-5 sm:mr-8">
|
||||||
<Col>
|
<div className="whitespace-nowrap text-right text-lg">
|
||||||
<div className="whitespace-nowrap text-right text-lg">
|
{formatMoney(metric === 'profit' ? profit : payout)}
|
||||||
{formatMoney(metric === 'profit' ? profit : payout)}
|
</div>
|
||||||
</div>
|
<ProfitBadge className="text-right" profitPercent={profitPercent} />
|
||||||
<div className="text-right">
|
</Col>
|
||||||
<ProfitBadge profitPercent={profitPercent} />
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<div
|
{!collapsed && (
|
||||||
className="collapse-content !px-0"
|
<div className="bg-white">
|
||||||
style={{ backgroundColor: 'white' }}
|
<BetsSummary
|
||||||
>
|
className="mt-8 mr-5 flex-1 sm:mr-8"
|
||||||
<Spacer h={8} />
|
contract={contract}
|
||||||
|
bets={bets}
|
||||||
|
isYourBets={isYourBets}
|
||||||
|
/>
|
||||||
|
|
||||||
<BetsSummary
|
{contract.mechanism === 'cpmm-1' && limitBets.length > 0 && (
|
||||||
className="mr-5 flex-1 sm:mr-8"
|
|
||||||
contract={contract}
|
|
||||||
bets={bets}
|
|
||||||
isYourBets={isYourBets}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Spacer h={4} />
|
|
||||||
|
|
||||||
{contract.mechanism === 'cpmm-1' && limitBets.length > 0 && (
|
|
||||||
<>
|
|
||||||
<div className="max-w-md">
|
<div className="max-w-md">
|
||||||
<div className="bg-gray-50 px-4 py-2">Limit orders</div>
|
<div className="mt-4 bg-gray-50 px-4 py-2">Limit orders</div>
|
||||||
<LimitOrderTable
|
<LimitOrderTable
|
||||||
contract={contract}
|
contract={contract}
|
||||||
limitBets={limitBets}
|
limitBets={limitBets}
|
||||||
isYou={true}
|
isYou={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
)}
|
||||||
)}
|
|
||||||
|
|
||||||
<Spacer h={4} />
|
<div className="mt-4 bg-gray-50 px-4 py-2">Bets</div>
|
||||||
|
<ContractBetsTable
|
||||||
<div className="bg-gray-50 px-4 py-2">Bets</div>
|
contract={contract}
|
||||||
<ContractBetsTable
|
bets={bets}
|
||||||
contract={contract}
|
isYourBets={isYourBets}
|
||||||
bets={bets}
|
/>
|
||||||
isYourBets={isYourBets}
|
</div>
|
||||||
/>
|
)}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -427,107 +410,92 @@ export function BetsSummary(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className={clsx('flex-wrap gap-4 sm:flex-nowrap sm:gap-6', className)}>
|
<Row className={clsx('flex-wrap gap-4 sm:flex-nowrap sm:gap-6', className)}>
|
||||||
<Row className="flex-wrap gap-4 sm:gap-6">
|
{!isCpmm && (
|
||||||
{!isCpmm && (
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Invested
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">{formatMoney(invested)}</div>
|
|
||||||
</Col>
|
|
||||||
)}
|
|
||||||
{resolution ? (
|
|
||||||
<Col>
|
|
||||||
<div className="text-sm text-gray-500">Payout</div>
|
|
||||||
<div className="whitespace-nowrap">
|
|
||||||
{formatMoney(payout)}{' '}
|
|
||||||
<ProfitBadge profitPercent={profitPercent} />
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{isBinary ? (
|
|
||||||
<>
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Payout if <YesLabel />
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">
|
|
||||||
{formatMoney(yesWinnings)}
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Payout if <NoLabel />
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">
|
|
||||||
{formatMoney(noWinnings)}
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
</>
|
|
||||||
) : isPseudoNumeric ? (
|
|
||||||
<>
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Payout if {'>='} {formatLargeNumber(contract.max)}
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">
|
|
||||||
{formatMoney(yesWinnings)}
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Payout if {'<='} {formatLargeNumber(contract.min)}
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">
|
|
||||||
{formatMoney(noWinnings)}
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Col>
|
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">
|
|
||||||
Current value
|
|
||||||
</div>
|
|
||||||
<div className="whitespace-nowrap">{formatMoney(payout)}</div>
|
|
||||||
</Col>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Col>
|
<Col>
|
||||||
<div className="whitespace-nowrap text-sm text-gray-500">Profit</div>
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Invested
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(invested)}</div>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
|
{resolution ? (
|
||||||
|
<Col>
|
||||||
|
<div className="text-sm text-gray-500">Payout</div>
|
||||||
<div className="whitespace-nowrap">
|
<div className="whitespace-nowrap">
|
||||||
{formatMoney(profit)} <ProfitBadge profitPercent={profitPercent} />
|
{formatMoney(payout)} <ProfitBadge profitPercent={profitPercent} />
|
||||||
{isYourBets &&
|
|
||||||
isCpmm &&
|
|
||||||
(isBinary || isPseudoNumeric) &&
|
|
||||||
!isClosed &&
|
|
||||||
!resolution &&
|
|
||||||
hasShares &&
|
|
||||||
sharesOutcome &&
|
|
||||||
user && (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
className="btn btn-sm ml-2"
|
|
||||||
onClick={() => setShowSellModal(true)}
|
|
||||||
>
|
|
||||||
Sell
|
|
||||||
</button>
|
|
||||||
{showSellModal && (
|
|
||||||
<SellSharesModal
|
|
||||||
contract={contract}
|
|
||||||
user={user}
|
|
||||||
userBets={bets}
|
|
||||||
shares={totalShares[sharesOutcome]}
|
|
||||||
sharesOutcome={sharesOutcome}
|
|
||||||
setOpen={setShowSellModal}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
) : isBinary ? (
|
||||||
|
<>
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Payout if <YesLabel />
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(yesWinnings)}</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Payout if <NoLabel />
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(noWinnings)}</div>
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
) : isPseudoNumeric ? (
|
||||||
|
<>
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Payout if {'>='} {formatLargeNumber(contract.max)}
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(yesWinnings)}</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Payout if {'<='} {formatLargeNumber(contract.min)}
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(noWinnings)}</div>
|
||||||
|
</Col>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">
|
||||||
|
Current value
|
||||||
|
</div>
|
||||||
|
<div className="whitespace-nowrap">{formatMoney(payout)}</div>
|
||||||
|
</Col>
|
||||||
|
)}
|
||||||
|
<Col>
|
||||||
|
<div className="whitespace-nowrap text-sm text-gray-500">Profit</div>
|
||||||
|
<div className="whitespace-nowrap">
|
||||||
|
{formatMoney(profit)} <ProfitBadge profitPercent={profitPercent} />
|
||||||
|
{isYourBets &&
|
||||||
|
isCpmm &&
|
||||||
|
(isBinary || isPseudoNumeric) &&
|
||||||
|
!isClosed &&
|
||||||
|
!resolution &&
|
||||||
|
hasShares &&
|
||||||
|
sharesOutcome &&
|
||||||
|
user && (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className="btn btn-sm ml-2"
|
||||||
|
onClick={() => setShowSellModal(true)}
|
||||||
|
>
|
||||||
|
Sell
|
||||||
|
</button>
|
||||||
|
{showSellModal && (
|
||||||
|
<SellSharesModal
|
||||||
|
contract={contract}
|
||||||
|
user={user}
|
||||||
|
userBets={bets}
|
||||||
|
shares={totalShares[sharesOutcome]}
|
||||||
|
sharesOutcome={sharesOutcome}
|
||||||
|
setOpen={setShowSellModal}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -689,7 +657,13 @@ function BetRow(props: {
|
||||||
!isClosed &&
|
!isClosed &&
|
||||||
!isSold &&
|
!isSold &&
|
||||||
!isAnte &&
|
!isAnte &&
|
||||||
!isNumeric && <SellButton contract={contract} bet={bet} />}
|
!isNumeric && (
|
||||||
|
<SellButton
|
||||||
|
contract={contract}
|
||||||
|
bet={bet}
|
||||||
|
unfilledBets={unfilledBets}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
{isCPMM && <td>{shares >= 0 ? 'BUY' : 'SELL'}</td>}
|
{isCPMM && <td>{shares >= 0 ? 'BUY' : 'SELL'}</td>}
|
||||||
<td>
|
<td>
|
||||||
|
@ -729,8 +703,12 @@ function BetRow(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SellButton(props: { contract: Contract; bet: Bet }) {
|
function SellButton(props: {
|
||||||
const { contract, bet } = props
|
contract: Contract
|
||||||
|
bet: Bet
|
||||||
|
unfilledBets: LimitBet[]
|
||||||
|
}) {
|
||||||
|
const { contract, bet, unfilledBets } = props
|
||||||
const { outcome, shares, loanAmount } = bet
|
const { outcome, shares, loanAmount } = bet
|
||||||
|
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||||
|
@ -740,8 +718,6 @@ function SellButton(props: { contract: Contract; bet: Bet }) {
|
||||||
outcome === 'NO' ? 'YES' : outcome
|
outcome === 'NO' ? 'YES' : outcome
|
||||||
)
|
)
|
||||||
|
|
||||||
const unfilledBets = useUnfilledBets(contract.id) ?? []
|
|
||||||
|
|
||||||
const outcomeProb = getProbabilityAfterSale(
|
const outcomeProb = getProbabilityAfterSale(
|
||||||
contract,
|
contract,
|
||||||
outcome,
|
outcome,
|
||||||
|
@ -787,8 +763,8 @@ function SellButton(props: { contract: Contract; bet: Bet }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function ProfitBadge(props: { profitPercent: number }) {
|
function ProfitBadge(props: { profitPercent: number; className?: string }) {
|
||||||
const { profitPercent } = props
|
const { profitPercent, className } = props
|
||||||
if (!profitPercent) return null
|
if (!profitPercent) return null
|
||||||
const colors =
|
const colors =
|
||||||
profitPercent > 0
|
profitPercent > 0
|
||||||
|
@ -799,7 +775,8 @@ function ProfitBadge(props: { profitPercent: number }) {
|
||||||
<span
|
<span
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'ml-1 inline-flex items-center rounded-full px-3 py-0.5 text-sm font-medium',
|
'ml-1 inline-flex items-center rounded-full px-3 py-0.5 text-sm font-medium',
|
||||||
colors
|
colors,
|
||||||
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{(profitPercent > 0 ? '+' : '') + profitPercent.toFixed(1) + '%'}
|
{(profitPercent > 0 ? '+' : '') + profitPercent.toFixed(1) + '%'}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user