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
className?: string
title?: string
selected?: 'YES' | 'NO'
}) {
useEffect(() => {
// warm up cloud function
placeBet({}).catch()
}, [])
const { contract, className, title } = props
const { contract, className, title, selected } = props
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 [error, setError] = useState<string | undefined>()
@ -92,14 +93,14 @@ export function BetPanel(props: {
const resultProb = getProbabilityAfterBet(
contract.totalShares,
betChoice,
betChoice || 'YES',
betAmount ?? 0
)
const shares = calculateShares(
contract.totalShares,
betAmount ?? 0,
betChoice
betChoice || 'YES'
)
const currentPayout = betAmount
@ -112,12 +113,16 @@ export function BetPanel(props: {
const currentReturn = betAmount ? (currentPayout - betAmount) / betAmount : 0
const currentReturnPercent = (currentReturn * 100).toFixed() + '%'
const panelTitle = title ?? `Buy ${betChoice || 'shares'}`
return (
<Col
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>
<YesNoSelector
@ -145,22 +150,27 @@ export function BetPanel(props: {
<div>{formatPercent(resultProb)}</div>
</Row>
<Row className="mt-2 mb-1 items-center gap-2 text-sm text-gray-500">
Payout if <OutcomeLabel outcome={betChoice} />
<InfoTooltip
text={`Current payout for ${formatWithCommas(
shares
)} / ${formatWithCommas(
shares +
contract.totalShares[betChoice] -
contract.phantomShares[betChoice]
)} ${betChoice} shares`}
/>
</Row>
<div>
{formatMoney(currentPayout)}
&nbsp; <span>(+{currentReturnPercent})</span>
</div>
{betChoice && (
<>
<Spacer h={4} />
<Row className="mt-2 mb-1 items-center gap-2 text-sm text-gray-500">
Payout if <OutcomeLabel outcome={betChoice} />
<InfoTooltip
text={`Current payout for ${formatWithCommas(
shares
)} / ${formatWithCommas(
shares +
contract.totalShares[betChoice] -
contract.phantomShares[betChoice]
)} ${betChoice} shares`}
/>
</Row>
<div>
{formatMoney(currentPayout)}
&nbsp; <span>(+{currentReturnPercent})</span>
</div>
</>
)}
<Spacer h={6} />

View File

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

View File

@ -5,7 +5,7 @@ import { Col } from './layout/col'
import { Row } from './layout/row'
export function YesNoSelector(props: {
selected: 'YES' | 'NO'
selected?: 'YES' | 'NO'
onSelect: (selected: 'YES' | 'NO') => void
className?: string
}) {
@ -13,19 +13,28 @@ export function YesNoSelector(props: {
return (
<Row className={clsx('space-x-3', className)}>
<Button
color={selected === 'YES' ? 'green' : 'gray'}
<button
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')}
>
YES
</Button>
<Button
color={selected === 'NO' ? 'red' : 'gray'}
</button>
<button
className={clsx(
'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')}
>
NO
</Button>
</button>
</Row>
)
}