diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx index 57d4a60c..6c2cab1f 100644 --- a/web/components/bet-panel.tsx +++ b/web/components/bet-panel.tsx @@ -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(undefined) const [error, setError] = useState() @@ -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 ( - + <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)} -   <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)} +   <span>(+{currentReturnPercent})</span> + </div> + </> + )} <Spacer h={6} /> diff --git a/web/components/bet-row.tsx b/web/components/bet-row.tsx index 689aab8f..cca31b64 100644 --- a/web/components/bet-row.tsx +++ b/web/components/bet-row.tsx @@ -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 diff --git a/web/components/yes-no-selector.tsx b/web/components/yes-no-selector.tsx index 0fcde422..a44bedf5 100644 --- a/web/components/yes-no-selector.tsx +++ b/web/components/yes-no-selector.tsx @@ -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> ) }