Pull out quick bet display component

This commit is contained in:
Austin Chen 2022-05-24 08:40:43 -07:00
parent a204380f57
commit 8e746ce0cb
2 changed files with 72 additions and 68 deletions

View File

@ -25,7 +25,7 @@ import {
import { getOutcomeProbability, getTopAnswer } from 'common/calculate' import { getOutcomeProbability, getTopAnswer } from 'common/calculate'
import { AvatarDetails, MiscDetails } from './contract-details' import { AvatarDetails, MiscDetails } from './contract-details'
import { getExpectedValue, getValueFromBucket } from 'common/calculate-dpm' import { getExpectedValue, getValueFromBucket } from 'common/calculate-dpm'
import { QuickBet, QuickOutcomeView, ProbBar, getColor } from './quick-bet' import { QuickBet, ProbBar, getColor } from './quick-bet'
import { useContractWithPreload } from 'web/hooks/use-contract' import { useContractWithPreload } from 'web/hooks/use-contract'
export function ContractCard(props: { export function ContractCard(props: {
@ -90,7 +90,28 @@ export function ContractCard(props: {
<QuickBet contract={contract} /> <QuickBet contract={contract} />
) : ( ) : (
<Col className="m-auto pl-2"> <Col className="m-auto pl-2">
<QuickOutcomeView contract={contract} /> {outcomeType === 'BINARY' && (
<BinaryResolutionOrChance
className="items-center"
contract={contract}
/>
)}
{outcomeType === 'NUMERIC' && (
<NumericResolutionOrExpectation
className="items-center"
contract={contract as NumericContract}
/>
)}
{outcomeType === 'FREE_RESPONSE' && (
<FreeResponseResolutionOrChance
className="self-end text-gray-600"
contract={contract as FullContract<DPM, FreeResponse>}
truncate="long"
/>
)}
<ProbBar contract={contract} />
</Col> </Col>
)} )}
</Row> </Row>
@ -103,10 +124,8 @@ export function BinaryResolutionOrChance(props: {
contract: FullContract<DPM | CPMM, Binary> contract: FullContract<DPM | CPMM, Binary>
large?: boolean large?: boolean
className?: string className?: string
hideText?: boolean
override?: string
}) { }) {
const { contract, large, className, hideText, override } = props const { contract, large, className } = props
const { resolution } = contract const { resolution } = contract
const textColor = `text-${getColor(contract)}` const textColor = `text-${getColor(contract)}`
@ -127,13 +146,11 @@ export function BinaryResolutionOrChance(props: {
) : ( ) : (
<> <>
<div className={clsx(textColor, 'transition-all')}> <div className={clsx(textColor, 'transition-all')}>
{override ?? getBinaryProbPercent(contract)} {getBinaryProbPercent(contract)}
</div> </div>
{!hideText && (
<div className={clsx(textColor, large ? 'text-xl' : 'text-base')}> <div className={clsx(textColor, large ? 'text-xl' : 'text-base')}>
chance chance
</div> </div>
)}
</> </>
)} )}
</Col> </Col>
@ -162,10 +179,8 @@ export function FreeResponseResolutionOrChance(props: {
contract: FreeResponseContract contract: FreeResponseContract
truncate: 'short' | 'long' | 'none' truncate: 'short' | 'long' | 'none'
className?: string className?: string
hideText?: boolean
override?: string
}) { }) {
const { contract, truncate, className, hideText, override } = props const { contract, truncate, className } = props
const { resolution } = contract const { resolution } = contract
const topAnswer = getTopAnswer(contract) const topAnswer = getTopAnswer(contract)
@ -188,10 +203,9 @@ export function FreeResponseResolutionOrChance(props: {
<Row className="items-center gap-6"> <Row className="items-center gap-6">
<Col className={clsx('text-3xl', textColor)}> <Col className={clsx('text-3xl', textColor)}>
<div> <div>
{override ?? {formatPercent(getOutcomeProbability(contract, topAnswer.id))}
formatPercent(getOutcomeProbability(contract, topAnswer.id))}
</div> </div>
{!hideText && <div className="text-base">chance</div>} <div className="text-base">chance</div>
</Col> </Col>
</Row> </Row>
) )
@ -203,10 +217,8 @@ export function FreeResponseResolutionOrChance(props: {
export function NumericResolutionOrExpectation(props: { export function NumericResolutionOrExpectation(props: {
contract: NumericContract contract: NumericContract
className?: string className?: string
hideText?: boolean
override?: string
}) { }) {
const { contract, className, hideText, override } = props const { contract, className } = props
const { resolution } = contract const { resolution } = contract
const textColor = `text-${getColor(contract)}` const textColor = `text-${getColor(contract)}`
@ -223,11 +235,9 @@ export function NumericResolutionOrExpectation(props: {
) : ( ) : (
<> <>
<div className={clsx('text-3xl', textColor)}> <div className={clsx('text-3xl', textColor)}>
{override ?? formatLargeNumber(getExpectedValue(contract))} {formatLargeNumber(getExpectedValue(contract))}
</div> </div>
{!hideText && (
<div className={clsx('text-base', textColor)}>expected</div> <div className={clsx('text-base', textColor)}>expected</div>
)}
</> </>
)} )}
</Col> </Col>

View File

@ -13,14 +13,19 @@ import {
Binary, Binary,
NumericContract, NumericContract,
FreeResponse, FreeResponse,
FreeResponseContract,
} from 'common/contract' } from 'common/contract'
import { formatMoney, formatPercent } from 'common/util/format' import {
formatLargeNumber,
formatMoney,
formatPercent,
} from 'common/util/format'
import { useState } from 'react' import { useState } from 'react'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { useUser } from 'web/hooks/use-user' import { useUser } from 'web/hooks/use-user'
import { useUserContractBets } from 'web/hooks/use-user-bets' import { useUserContractBets } from 'web/hooks/use-user-bets'
import { placeBet } from 'web/lib/firebase/api-call' import { placeBet } from 'web/lib/firebase/api-call'
import { getBinaryProb } from 'web/lib/firebase/contracts' import { getBinaryProb, getBinaryProbPercent } from 'web/lib/firebase/contracts'
import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon' import TriangleDownFillIcon from 'web/lib/icons/triangle-down-fill-icon'
import TriangleFillIcon from 'web/lib/icons/triangle-fill-icon' import TriangleFillIcon from 'web/lib/icons/triangle-fill-icon'
import { Col } from '../layout/col' import { Col } from '../layout/col'
@ -71,7 +76,7 @@ export function QuickBet(props: { contract: Contract }) {
// Catch any errors from hovering on an invalid option // Catch any errors from hovering on an invalid option
} }
const color = getColor(contract) const color = getColor(contract, previewProb)
async function placeQuickBet(direction: 'UP' | 'DOWN') { async function placeQuickBet(direction: 'UP' | 'DOWN') {
const betPromise = async () => { const betPromise = async () => {
@ -170,8 +175,7 @@ export function QuickBet(props: { contract: Contract }) {
export function ProbBar(props: { contract: Contract; previewProb?: number }) { export function ProbBar(props: { contract: Contract; previewProb?: number }) {
const { contract, previewProb } = props const { contract, previewProb } = props
// TODO: Switch preview color as it changes from green to red const color = getColor(contract, previewProb)
const color = getColor(contract)
const prob = previewProb ?? getProb(contract) const prob = previewProb ?? getProb(contract)
return ( return (
<> <>
@ -195,47 +199,40 @@ export function ProbBar(props: { contract: Contract; previewProb?: number }) {
) )
} }
// TODO: just directly code in the outcomes for quick bet, rather than relying on function QuickOutcomeView(props: {
// code resuse. Too many differences anyways
export function QuickOutcomeView(props: {
contract: Contract contract: Contract
previewProb?: number previewProb?: number
caption?: 'chance' | 'expected'
}) { }) {
const { contract, previewProb } = props const { contract, previewProb, caption } = props
const { outcomeType } = contract const { outcomeType } = contract
// If there's a preview probability,
const override = const override =
previewProb === undefined ? undefined : formatPercent(previewProb) previewProb === undefined ? undefined : formatPercent(previewProb)
const textColor = `text-${getColor(contract, previewProb)}`
let display: string | undefined
switch (outcomeType) {
case 'BINARY':
display = getBinaryProbPercent(contract)
break
case 'NUMERIC':
display = formatLargeNumber(getExpectedValue(contract as NumericContract))
break
case 'FREE_RESPONSE':
const topAnswer = getTopAnswer(contract as FreeResponseContract)
display =
topAnswer &&
formatPercent(getOutcomeProbability(contract, topAnswer.id))
break
}
return ( return (
<> <Col className={clsx('items-center text-3xl', textColor)}>
{outcomeType === 'BINARY' && ( {override ?? display}
<BinaryResolutionOrChance {caption && <div className="text-base">{caption}</div>}
className="items-center"
contract={contract}
hideText
override={override}
/>
)}
{outcomeType === 'NUMERIC' && (
<NumericResolutionOrExpectation
className="items-center"
contract={contract as NumericContract}
hideText
override={override}
/>
)}
{outcomeType === 'FREE_RESPONSE' && (
<FreeResponseResolutionOrChance
className="self-end text-gray-600"
contract={contract as FullContract<DPM, FreeResponse>}
truncate="long"
hideText
override={override}
/>
)}
<ProbBar contract={contract} previewProb={previewProb} /> <ProbBar contract={contract} previewProb={previewProb} />
</> </Col>
) )
} }
@ -260,7 +257,7 @@ function getNumericScale(contract: NumericContract) {
return (ev - min) / (max - min) return (ev - min) / (max - min)
} }
export function getColor(contract: Contract) { export function getColor(contract: Contract, previewProb?: number) {
// TODO: Not sure why eg green-400 doesn't work here; try upgrading Tailwind // TODO: Not sure why eg green-400 doesn't work here; try upgrading Tailwind
// TODO: Try injecting a gradient here // TODO: Try injecting a gradient here
// return 'primary' // return 'primary'
@ -278,9 +275,6 @@ export function getColor(contract: Contract) {
} }
const marketClosed = (contract.closeTime || Infinity) < Date.now() const marketClosed = (contract.closeTime || Infinity) < Date.now()
return marketClosed const prob = previewProb ?? getProb(contract)
? 'gray-400' return marketClosed ? 'gray-400' : prob >= 0.5 ? 'primary' : 'red-400'
: getProb(contract) >= 0.5
? 'primary'
: 'red-400'
} }