Extract bet amount input to component.
This commit is contained in:
parent
6ef48af085
commit
7fbecbc102
|
@ -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
|
||||
)}
|
||||
>
|
||||
|
|
79
web/components/amount-input.tsx
Normal file
79
web/components/amount-input.tsx
Normal 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>
|
||||
)
|
||||
}
|
|
@ -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)}
|
||||
<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}
|
||||
/>
|
||||
</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>
|
||||
|
||||
<Spacer h={4} />
|
||||
|
||||
<div className="mt-2 mb-1 text-sm text-gray-500">Implied probability</div>
|
||||
<Row>
|
||||
|
|
|
@ -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 ?? ''}
|
||||
<AmountInput
|
||||
className="items-start"
|
||||
amount={ante}
|
||||
onChange={setAnte}
|
||||
error={anteError}
|
||||
setError={setAnteError}
|
||||
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>
|
||||
</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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user