Extract bet amount input to component.

This commit is contained in:
jahooma 2022-01-10 21:41:42 -06:00
parent 6ef48af085
commit 7fbecbc102
4 changed files with 107 additions and 87 deletions

View File

@ -18,7 +18,7 @@ export function AddFundsButton(props: { className?: string }) {
<label
htmlFor="add-funds"
className={clsx(
'btn btn-sm normal-case modal-button bg-gradient-to-r from-teal-500 to-green-500 hover:from-teal-600 hover:to-green-600 font-normal border-none',
'btn btn-xs normal-case modal-button bg-gradient-to-r from-teal-500 to-green-500 hover:from-teal-600 hover:to-green-600 font-normal border-none',
className
)}
>

View File

@ -0,0 +1,79 @@
import clsx from 'clsx'
import { useUser } from '../hooks/use-user'
import { formatMoney } from '../lib/util/format'
import { AddFundsButton } from './add-funds-button'
import { Col } from './layout/col'
import { Row } from './layout/row'
export function AmountInput(props: {
amount: number | undefined
onChange: (newAmount: number | undefined) => void
error: string | undefined
setError: (error: string | undefined) => void
disabled?: boolean
className?: string
inputClassName?: string
}) {
const {
amount,
onChange,
error,
setError,
disabled,
className,
inputClassName,
} = props
const user = useUser()
const onAmountChange = (str: string) => {
const amount = parseInt(str.replace(/[^\d]/, ''))
if (str && isNaN(amount)) return
onChange(str ? amount : undefined)
if (user && user.balance < amount) setError('Insufficient balance')
else setError(undefined)
}
const remainingBalance = (user?.balance ?? 0) - (amount ?? 0)
return (
<Col className={className}>
<label className="input-group">
<span className="text-sm bg-gray-200">M$</span>
<input
className={clsx(
'input input-bordered',
error && 'input-error',
inputClassName
)}
type="text"
placeholder="0"
maxLength={9}
value={amount ?? ''}
disabled={disabled}
onChange={(e) => onAmountChange(e.target.value)}
/>
</label>
{user && (
<Row className="text-sm text-gray-500 justify-between mt-3 gap-4 items-end">
{error ? (
<div className="font-medium tracking-wide text-red-500 text-xs whitespace-nowrap mr-auto self-center">
{error}
</div>
) : (
<Col>
<div className="whitespace-nowrap">Remaining balance</div>
<div className="text-neutral mt-1">
{formatMoney(Math.floor(remainingBalance))}
</div>
</Col>
)}
{user.balance !== 1000 && <AddFundsButton className="mt-1" />}
</Row>
)}
</Col>
)
}

View File

@ -20,11 +20,11 @@ import {
calculatePayoutAfterCorrectBet,
} from '../../common/calculate'
import { firebaseLogin } from '../lib/firebase/users'
import { AddFundsButton } from './add-funds-button'
import { OutcomeLabel } from './outcome-label'
import { AdvancedPanel } from './advanced-panel'
import { Bet } from '../../common/bet'
import { placeBet } from '../lib/firebase/api-call'
import { AmountInput } from './amount-input'
export function BetPanel(props: { contract: Contract; className?: string }) {
useEffect(() => {
@ -48,17 +48,9 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
setWasSubmitted(false)
}
function onBetChange(str: string) {
function onBetChange(newAmount: number | undefined) {
setWasSubmitted(false)
const amount = parseInt(str.replace(/[^\d]/, ''))
if (str && isNaN(amount)) return
setBetAmount(str ? amount : undefined)
if (user && user.balance < amount) setError('Insufficient balance')
else setError(undefined)
setBetAmount(newAmount)
}
async function submitBet() {
@ -106,8 +98,6 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
: 0
const estimatedReturnPercent = (estimatedReturn * 100).toFixed() + '%'
const remainingBalance = (user?.balance || 0) - (betAmount || 0)
return (
<Col
className={clsx('bg-gray-100 shadow-md px-8 py-6 rounded-md', className)}
@ -121,41 +111,17 @@ export function BetPanel(props: { contract: Contract; className?: string }) {
onSelect={(choice) => onBetChoice(choice)}
/>
<div className="mt-3 mb-1 text-sm text-gray-500">
Amount{' '}
{user && (
<span className="float-right">
{formatMoney(
remainingBalance > 0 ? Math.floor(remainingBalance) : 0
)}{' '}
left
</span>
)}
</div>
<Col className="my-2">
<label className="input-group">
<span className="text-sm bg-gray-200">M$</span>
<input
className={clsx(
'input input-bordered w-full',
error && 'input-error'
)}
type="text"
placeholder="0"
maxLength={9}
value={betAmount ?? ''}
onChange={(e) => onBetChange(e.target.value)}
/>
</label>
{error && (
<div className="font-medium tracking-wide text-red-500 text-xs mt-3">
{error}
</div>
)}
{user && user.balance !== 1000 && (
<AddFundsButton className="self-end mt-3" />
)}
</Col>
<div className="my-3 text-sm text-gray-500">Amount </div>
<AmountInput
inputClassName="w-full"
amount={betAmount}
onChange={onBetChange}
error={error}
setError={setError}
disabled={isSubmitting}
/>
<Spacer h={4} />
<div className="mt-2 mb-1 text-sm text-gray-500">Implied probability</div>
<Row>

View File

@ -10,10 +10,10 @@ import { Title } from '../components/title'
import { useUser } from '../hooks/use-user'
import { Contract, path } from '../lib/firebase/contracts'
import { Page } from '../components/page'
import { formatMoney } from '../lib/util/format'
import { AdvancedPanel } from '../components/advanced-panel'
import { createContract } from '../lib/firebase/api-call'
import { Row } from '../components/layout/row'
import { AmountInput } from '../components/amount-input'
// Allow user to create a new contract
export default function NewContract() {
@ -33,7 +33,7 @@ export default function NewContract() {
const [description, setDescription] = useState('')
const [ante, setAnte] = useState<number | undefined>(0)
const [anteError, setAnteError] = useState('')
const [anteError, setAnteError] = useState<string | undefined>()
const [closeDate, setCloseDate] = useState('')
const [isSubmitting, setIsSubmitting] = useState(false)
@ -75,17 +75,6 @@ export default function NewContract() {
await router.push(path(result.contract as Contract))
}
function onAnteChange(str: string) {
const amount = parseInt(str.replace(/[^\d]/, ''))
if (str && isNaN(amount)) return
setAnte(str ? amount : undefined)
if (user && user.balance < amount) setAnteError('Insufficient balance')
else setAnteError('')
}
const descriptionPlaceholder = `e.g. This market will resolve to “Yes” if, by June 2, 2021, 11:59:59 PM ET, Paxlovid (also known under PF-07321332)...`
if (!creator) return <></>
@ -166,33 +155,19 @@ export default function NewContract() {
<label className="label">
<span className="mb-1">Subsidize your market</span>
</label>
<label className="input-group">
<span className="text-sm ">M$</span>
<input
className={clsx(
'input input-bordered',
anteError && 'input-error'
)}
type="text"
placeholder="0"
maxLength={9}
value={ante ?? ''}
disabled={isSubmitting}
onChange={(e) => onAnteChange(e.target.value)}
/>
</label>
<label>
<span className="label-text text-gray-500 ml-1">
Remaining balance:{' '}
{formatMoney(remainingBalance > 0 ? remainingBalance : 0)}
</span>
</label>
<AmountInput
className="items-start"
amount={ante}
onChange={setAnte}
error={anteError}
setError={setAnteError}
disabled={isSubmitting}
/>
</div>
<Spacer h={4} />
<div className="form-control">
<div className="form-control items-start mb-1">
<label className="label">
<span className="mb-1">Close date</span>
</label>
@ -208,8 +183,8 @@ export default function NewContract() {
</div>
<label>
<span className="label-text text-gray-500 ml-1">
No new trades will be allowed after{' '}
{closeDate ? formattedCloseTime : 'this time'}
No trades allowed after this date
{/* {closeDate ? formattedCloseTime : 'this date'} */}
</span>
</label>
</AdvancedPanel>