Split BuyAmountInput out of AmountInput

This commit is contained in:
James Grugett 2022-03-19 16:38:05 -05:00
parent a3c72214b8
commit 49bb74cc0d
6 changed files with 105 additions and 63 deletions

View File

@ -10,6 +10,74 @@ import { InfoTooltip } from './info-tooltip'
import { Spacer } from './layout/spacer'
export function AmountInput(props: {
amount: number | undefined
onChange: (newAmount: number | undefined) => void
error: string | undefined
disabled?: boolean
className?: string
inputClassName?: string
// Needed to focus the amount input
inputRef?: React.MutableRefObject<any>
children?: any
}) {
const {
amount,
onChange,
error,
disabled,
className,
inputClassName,
inputRef,
children,
} = props
const onAmountChange = (str: string) => {
if (str.includes('-')) {
onChange(undefined)
return
}
const amount = parseInt(str.replace(/[^\d]/, ''))
if (str && isNaN(amount)) return
if (amount >= 10 ** 9) return
onChange(str ? amount : undefined)
}
return (
<Col className={className}>
<label className="input-group">
<span className="bg-gray-200 text-sm">M$</span>
<input
className={clsx(
'input input-bordered',
error && 'input-error',
inputClassName
)}
ref={inputRef}
type="number"
placeholder="0"
maxLength={9}
value={amount ?? ''}
disabled={disabled}
onChange={(e) => onAmountChange(e.target.value)}
/>
</label>
<Spacer h={4} />
{error && (
<div className="mb-2 mr-auto self-center whitespace-nowrap text-xs font-medium tracking-wide text-red-500">
{error}
</div>
)}
{children}
</Col>
)
}
export function BuyAmountInput(props: {
amount: number | undefined
onChange: (newAmount: number | undefined) => void
error: string | undefined
@ -45,62 +113,36 @@ export function AmountInput(props: {
? Math.min(amount ?? 0, MAX_LOAN_PER_CONTRACT - prevLoanAmount)
: 0
const onAmountChange = (str: string) => {
if (str.includes('-')) {
onChange(undefined)
return
}
const amount = parseInt(str.replace(/[^\d]/, ''))
if (str && isNaN(amount)) return
if (amount >= 10 ** 9) return
onChange(str ? amount : undefined)
const loanAmount = contractIdForLoan
? Math.min(amount, MAX_LOAN_PER_CONTRACT - prevLoanAmount)
: 0
const amountNetLoan = amount - loanAmount
if (user && user.balance < amountNetLoan) {
setError('Insufficient balance')
} else if (minimumAmount && amount < minimumAmount) {
setError('Minimum amount: ' + formatMoney(minimumAmount))
} else {
setError(undefined)
}
}
const amountNetLoan = (amount ?? 0) - loanAmount
const remainingBalance = Math.max(0, (user?.balance ?? 0) - amountNetLoan)
const onAmountChange = (amount: number | undefined) => {
onChange(amount)
// Check for errors.
if (amount !== undefined) {
const amountNetLoan = amount - loanAmount
if (user && user.balance < amountNetLoan) {
setError('Insufficient balance')
} else if (minimumAmount && amount < minimumAmount) {
setError('Minimum amount: ' + formatMoney(minimumAmount))
} else {
setError(undefined)
}
}
}
return (
<Col className={className}>
<label className="input-group">
<span className="bg-gray-200 text-sm">M$</span>
<input
className={clsx(
'input input-bordered',
error && 'input-error',
inputClassName
)}
ref={inputRef}
type="number"
placeholder="0"
maxLength={9}
value={amount ?? ''}
disabled={disabled}
onChange={(e) => onAmountChange(e.target.value)}
/>
</label>
<Spacer h={4} />
{error && (
<div className="mb-2 mr-auto self-center whitespace-nowrap text-xs font-medium tracking-wide text-red-500">
{error}
</div>
)}
<AmountInput
amount={amount}
onChange={onAmountChange}
error={error}
disabled={disabled}
className={className}
inputClassName={inputClassName}
inputRef={inputRef}
>
{user && (
<Col className="gap-3 text-sm">
{contractIdForLoan && (
@ -124,6 +166,6 @@ export function AmountInput(props: {
</Row>
</Col>
)}
</Col>
</AmountInput>
)
}

View File

@ -5,7 +5,7 @@ import { XIcon } from '@heroicons/react/solid'
import { Answer } from '../../../common/answer'
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
import { AmountInput } from '../amount-input'
import { BuyAmountInput } from '../amount-input'
import { Col } from '../layout/col'
import { placeBet } from '../../lib/firebase/api-call'
import { Row } from '../layout/row'
@ -114,7 +114,7 @@ export function AnswerBetPanel(props: {
)}
</Row>
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
<AmountInput
<BuyAmountInput
inputClassName="w-full"
amount={betAmount}
onChange={setBetAmount}

View File

@ -4,7 +4,7 @@ import { useState } from 'react'
import Textarea from 'react-expanding-textarea'
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
import { AmountInput } from '../amount-input'
import { BuyAmountInput } from '../amount-input'
import { Col } from '../layout/col'
import { createAnswer } from '../../lib/firebase/api-call'
import { Row } from '../layout/row'
@ -97,7 +97,7 @@ export function CreateAnswerPanel(props: {
<>
<Col className="mt-1 gap-2">
<div className="text-sm text-gray-500">Buy amount</div>
<AmountInput
<BuyAmountInput
amount={betAmount}
onChange={setBetAmount}
error={amountError}

View File

@ -16,7 +16,7 @@ import { Title } from './title'
import { firebaseLogin } from '../lib/firebase/users'
import { Bet } from '../../common/bet'
import { placeBet } from '../lib/firebase/api-call'
import { AmountInput } from './amount-input'
import { BuyAmountInput } from './amount-input'
import { InfoTooltip } from './info-tooltip'
import { OutcomeLabel } from './outcome-label'
import {
@ -144,7 +144,7 @@ export function BetPanel(props: {
/>
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
<AmountInput
<BuyAmountInput
inputClassName="w-full"
amount={betAmount}
onChange={onBetChange}

View File

@ -8,7 +8,7 @@ import { Spacer } from '../components/layout/spacer'
import { useUser } from '../hooks/use-user'
import { Contract, contractPath } from '../lib/firebase/contracts'
import { createContract } from '../lib/firebase/api-call'
import { AmountInput } from '../components/amount-input'
import { BuyAmountInput } from '../components/amount-input'
import { MINIMUM_ANTE } from '../../common/antes'
import { InfoTooltip } from '../components/info-tooltip'
import { CREATOR_FEE } from '../../common/fees'
@ -241,7 +241,7 @@ export function NewContract(props: { question: string; tag?: string }) {
text={`Provide liquidity to encourage traders to participate.`}
/>
</label>
<AmountInput
<BuyAmountInput
amount={ante ?? undefined}
minimumAmount={MINIMUM_ANTE}
onChange={setAnte}

View File

@ -7,7 +7,7 @@ import Textarea from 'react-expanding-textarea'
import { getProbability } from '../../common/calculate'
import { Binary, CPMM, DPM, FullContract } from '../../common/contract'
import { parseWordsAsTags } from '../../common/util/parse'
import { AmountInput } from '../components/amount-input'
import { BuyAmountInput } from '../components/amount-input'
import { InfoTooltip } from '../components/info-tooltip'
import { Col } from '../components/layout/col'
import { Row } from '../components/layout/row'
@ -241,7 +241,7 @@ ${TEST_VALUE}
You earn ${0.01 * 100}% of trading volume.`}
/>
</label>
<AmountInput
<BuyAmountInput
amount={ante}
minimumAmount={10}
onChange={setAnte}