Replace the popup with a YES/NO selector
This commit is contained in:
parent
54d15dede2
commit
82fa464e58
|
@ -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)}
|
||||||
<span>(+{currentReturnPercent})</span>
|
<span>(+{currentReturnPercent})</span>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<Spacer h={6} />
|
<Spacer h={6} />
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user