Replace the popup with a YES/NO selector

This commit is contained in:
Austin Chen 2022-01-26 11:50:14 -06:00
parent 54d15dede2
commit 82fa464e58
3 changed files with 75 additions and 40 deletions

View File

@ -30,17 +30,18 @@ export function BetPanel(props: {
contract: Contract contract: Contract
className?: string className?: string
title?: string title?: string
selected?: 'YES' | 'NO'
}) { }) {
useEffect(() => { useEffect(() => {
// warm up cloud function // warm up cloud function
placeBet({}).catch() placeBet({}).catch()
}, []) }, [])
const { contract, className, title } = props const { contract, className, title, selected } = props
const user = useUser() const user = useUser()
const [betChoice, setBetChoice] = useState<'YES' | 'NO'>('YES') const [betChoice, setBetChoice] = useState<'YES' | 'NO' | undefined>(selected)
const [betAmount, setBetAmount] = useState<number | undefined>(undefined) const [betAmount, setBetAmount] = useState<number | undefined>(undefined)
const [error, setError] = useState<string | undefined>() const [error, setError] = useState<string | undefined>()
@ -92,14 +93,14 @@ export function BetPanel(props: {
const resultProb = getProbabilityAfterBet( const resultProb = getProbabilityAfterBet(
contract.totalShares, contract.totalShares,
betChoice, betChoice || 'YES',
betAmount ?? 0 betAmount ?? 0
) )
const shares = calculateShares( const shares = calculateShares(
contract.totalShares, contract.totalShares,
betAmount ?? 0, betAmount ?? 0,
betChoice betChoice || 'YES'
) )
const currentPayout = betAmount const currentPayout = betAmount
@ -112,12 +113,16 @@ export function BetPanel(props: {
const currentReturn = betAmount ? (currentPayout - betAmount) / betAmount : 0 const currentReturn = betAmount ? (currentPayout - betAmount) / betAmount : 0
const currentReturnPercent = (currentReturn * 100).toFixed() + '%' const currentReturnPercent = (currentReturn * 100).toFixed() + '%'
const panelTitle = title ?? `Buy ${betChoice || 'shares'}`
return ( return (
<Col <Col
className={clsx('bg-gray-100 shadow-md px-8 py-6 rounded-md', className)} className={clsx('bg-gray-100 shadow-md px-8 py-6 rounded-md', className)}
> >
<Title className="mt-0 text-neutral" text={title ?? `Buy ${betChoice}`} /> <Title
className={clsx('!mt-0 text-neutral', title ? '!text-xl' : '')}
text={panelTitle}
/>
<div className="mt-2 mb-1 text-sm text-gray-500">Outcome</div> <div className="mt-2 mb-1 text-sm text-gray-500">Outcome</div>
<YesNoSelector <YesNoSelector
@ -145,6 +150,9 @@ export function BetPanel(props: {
<div>{formatPercent(resultProb)}</div> <div>{formatPercent(resultProb)}</div>
</Row> </Row>
{betChoice && (
<>
<Spacer h={4} />
<Row className="mt-2 mb-1 items-center gap-2 text-sm text-gray-500"> <Row className="mt-2 mb-1 items-center gap-2 text-sm text-gray-500">
Payout if <OutcomeLabel outcome={betChoice} /> Payout if <OutcomeLabel outcome={betChoice} />
<InfoTooltip <InfoTooltip
@ -161,6 +169,8 @@ export function BetPanel(props: {
{formatMoney(currentPayout)} {formatMoney(currentPayout)}
&nbsp; <span>(+{currentReturnPercent})</span> &nbsp; <span>(+{currentReturnPercent})</span>
</div> </div>
</>
)}
<Spacer h={6} /> <Spacer h={6} />

View File

@ -1,30 +1,46 @@
/* This example requires Tailwind CSS v2.0+ */ /* This example requires Tailwind CSS v2.0+ */
import { Fragment, useState } from 'react' import { Fragment, useState } from 'react'
import { Dialog, Transition } from '@headlessui/react' import { Dialog, Transition } from '@headlessui/react'
import { CheckIcon } from '@heroicons/react/outline'
import { Contract } from '../lib/firebase/contracts' import { Contract } from '../lib/firebase/contracts'
import { BetPanel } from './bet-panel' import { BetPanel } from './bet-panel'
import { Row } from './layout/row'
import { YesNoSelector } from './yes-no-selector'
// Inline version of a bet panel. Opens BetPanel in a new modal. // Inline version of a bet panel. Opens BetPanel in a new modal.
// TODO: Hide when not appropriate
// TODO: Autofocus the bet amount input
export default function BetRow(props: { contract: Contract }) { export default function BetRow(props: { contract: Contract }) {
// Button to open the modal
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [betChoice, setBetChoice] = useState<'YES' | 'NO' | undefined>(
undefined
)
return ( return (
<> <>
<button <div className="-mt-4 text-xl pb-6 -mx-4 -mb-6">
className="flex items-center justify-center w-full h-full p-2 text-white bg-blue-500 hover:bg-blue-700 rounded-lg" <Row className="items-center gap-2 justify-center">
onClick={() => setOpen(true)} Buy
> <YesNoSelector
Trade className="w-72"
</button> onSelect={(choice) => {
setOpen(true)
setBetChoice(choice)
}}
/>
</Row>
<Modal open={open} setOpen={setOpen}> <Modal open={open} setOpen={setOpen}>
<BetPanel contract={props.contract} title={props.contract.question} /> <BetPanel
contract={props.contract}
title={props.contract.question}
selected={betChoice}
/>
</Modal> </Modal>
</div>
</> </>
) )
} }
// From https://tailwindui.com/components/application-ui/overlays/modals
export function Modal(props: { export function Modal(props: {
children: React.ReactNode children: React.ReactNode
open: boolean open: boolean

View File

@ -5,7 +5,7 @@ import { Col } from './layout/col'
import { Row } from './layout/row' import { Row } from './layout/row'
export function YesNoSelector(props: { export function YesNoSelector(props: {
selected: 'YES' | 'NO' selected?: 'YES' | 'NO'
onSelect: (selected: 'YES' | 'NO') => void onSelect: (selected: 'YES' | 'NO') => void
className?: string className?: string
}) { }) {
@ -13,19 +13,28 @@ export function YesNoSelector(props: {
return ( return (
<Row className={clsx('space-x-3', className)}> <Row className={clsx('space-x-3', className)}>
<Button <button
color={selected === 'YES' ? 'green' : 'gray'} className={clsx(
'flex-1 inline-flex justify-center items-center p-2 hover:bg-primary-focus hover:text-white rounded-lg border-primary hover:border-primary-focus border-2',
selected == 'YES'
? 'bg-primary text-white'
: 'bg-transparent text-primary'
)}
onClick={() => onSelect('YES')} onClick={() => onSelect('YES')}
> >
YES YES
</Button> </button>
<button
<Button className={clsx(
color={selected === 'NO' ? 'red' : 'gray'} 'flex-1 inline-flex justify-center items-center p-2 hover:bg-red-500 hover:text-white rounded-lg border-red-400 hover:border-red-500 border-2',
selected == 'NO'
? 'bg-red-400 text-white'
: 'bg-transparent text-red-400'
)}
onClick={() => onSelect('NO')} onClick={() => onSelect('NO')}
> >
NO NO
</Button> </button>
</Row> </Row>
) )
} }