Split BuyAmountInput out of AmountInput
This commit is contained in:
parent
a3c72214b8
commit
49bb74cc0d
|
@ -10,6 +10,74 @@ import { InfoTooltip } from './info-tooltip'
|
||||||
import { Spacer } from './layout/spacer'
|
import { Spacer } from './layout/spacer'
|
||||||
|
|
||||||
export function AmountInput(props: {
|
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
|
amount: number | undefined
|
||||||
onChange: (newAmount: number | undefined) => void
|
onChange: (newAmount: number | undefined) => void
|
||||||
error: string | undefined
|
error: string | undefined
|
||||||
|
@ -45,62 +113,36 @@ export function AmountInput(props: {
|
||||||
? Math.min(amount ?? 0, MAX_LOAN_PER_CONTRACT - prevLoanAmount)
|
? Math.min(amount ?? 0, MAX_LOAN_PER_CONTRACT - prevLoanAmount)
|
||||||
: 0
|
: 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 amountNetLoan = (amount ?? 0) - loanAmount
|
||||||
const remainingBalance = Math.max(0, (user?.balance ?? 0) - amountNetLoan)
|
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 (
|
return (
|
||||||
<Col className={className}>
|
<AmountInput
|
||||||
<label className="input-group">
|
amount={amount}
|
||||||
<span className="bg-gray-200 text-sm">M$</span>
|
onChange={onAmountChange}
|
||||||
<input
|
error={error}
|
||||||
className={clsx(
|
disabled={disabled}
|
||||||
'input input-bordered',
|
className={className}
|
||||||
error && 'input-error',
|
inputClassName={inputClassName}
|
||||||
inputClassName
|
inputRef={inputRef}
|
||||||
)}
|
>
|
||||||
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>
|
|
||||||
)}
|
|
||||||
{user && (
|
{user && (
|
||||||
<Col className="gap-3 text-sm">
|
<Col className="gap-3 text-sm">
|
||||||
{contractIdForLoan && (
|
{contractIdForLoan && (
|
||||||
|
@ -124,6 +166,6 @@ export function AmountInput(props: {
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</AmountInput>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { XIcon } from '@heroicons/react/solid'
|
||||||
|
|
||||||
import { Answer } from '../../../common/answer'
|
import { Answer } from '../../../common/answer'
|
||||||
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
|
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
|
||||||
import { AmountInput } from '../amount-input'
|
import { BuyAmountInput } from '../amount-input'
|
||||||
import { Col } from '../layout/col'
|
import { Col } from '../layout/col'
|
||||||
import { placeBet } from '../../lib/firebase/api-call'
|
import { placeBet } from '../../lib/firebase/api-call'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
|
@ -114,7 +114,7 @@ export function AnswerBetPanel(props: {
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
|
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
|
||||||
<AmountInput
|
<BuyAmountInput
|
||||||
inputClassName="w-full"
|
inputClassName="w-full"
|
||||||
amount={betAmount}
|
amount={betAmount}
|
||||||
onChange={setBetAmount}
|
onChange={setBetAmount}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { useState } from 'react'
|
||||||
import Textarea from 'react-expanding-textarea'
|
import Textarea from 'react-expanding-textarea'
|
||||||
|
|
||||||
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
|
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
|
||||||
import { AmountInput } from '../amount-input'
|
import { BuyAmountInput } from '../amount-input'
|
||||||
import { Col } from '../layout/col'
|
import { Col } from '../layout/col'
|
||||||
import { createAnswer } from '../../lib/firebase/api-call'
|
import { createAnswer } from '../../lib/firebase/api-call'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
|
@ -97,7 +97,7 @@ export function CreateAnswerPanel(props: {
|
||||||
<>
|
<>
|
||||||
<Col className="mt-1 gap-2">
|
<Col className="mt-1 gap-2">
|
||||||
<div className="text-sm text-gray-500">Buy amount</div>
|
<div className="text-sm text-gray-500">Buy amount</div>
|
||||||
<AmountInput
|
<BuyAmountInput
|
||||||
amount={betAmount}
|
amount={betAmount}
|
||||||
onChange={setBetAmount}
|
onChange={setBetAmount}
|
||||||
error={amountError}
|
error={amountError}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Title } from './title'
|
||||||
import { firebaseLogin } from '../lib/firebase/users'
|
import { firebaseLogin } from '../lib/firebase/users'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
import { placeBet } from '../lib/firebase/api-call'
|
import { placeBet } from '../lib/firebase/api-call'
|
||||||
import { AmountInput } from './amount-input'
|
import { BuyAmountInput } from './amount-input'
|
||||||
import { InfoTooltip } from './info-tooltip'
|
import { InfoTooltip } from './info-tooltip'
|
||||||
import { OutcomeLabel } from './outcome-label'
|
import { OutcomeLabel } from './outcome-label'
|
||||||
import {
|
import {
|
||||||
|
@ -144,7 +144,7 @@ export function BetPanel(props: {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
|
<div className="my-3 text-left text-sm text-gray-500">Amount </div>
|
||||||
<AmountInput
|
<BuyAmountInput
|
||||||
inputClassName="w-full"
|
inputClassName="w-full"
|
||||||
amount={betAmount}
|
amount={betAmount}
|
||||||
onChange={onBetChange}
|
onChange={onBetChange}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { Spacer } from '../components/layout/spacer'
|
||||||
import { useUser } from '../hooks/use-user'
|
import { useUser } from '../hooks/use-user'
|
||||||
import { Contract, contractPath } from '../lib/firebase/contracts'
|
import { Contract, contractPath } from '../lib/firebase/contracts'
|
||||||
import { createContract } from '../lib/firebase/api-call'
|
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 { MINIMUM_ANTE } from '../../common/antes'
|
||||||
import { InfoTooltip } from '../components/info-tooltip'
|
import { InfoTooltip } from '../components/info-tooltip'
|
||||||
import { CREATOR_FEE } from '../../common/fees'
|
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.`}
|
text={`Provide liquidity to encourage traders to participate.`}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<AmountInput
|
<BuyAmountInput
|
||||||
amount={ante ?? undefined}
|
amount={ante ?? undefined}
|
||||||
minimumAmount={MINIMUM_ANTE}
|
minimumAmount={MINIMUM_ANTE}
|
||||||
onChange={setAnte}
|
onChange={setAnte}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Textarea from 'react-expanding-textarea'
|
||||||
import { getProbability } from '../../common/calculate'
|
import { getProbability } from '../../common/calculate'
|
||||||
import { Binary, CPMM, DPM, FullContract } from '../../common/contract'
|
import { Binary, CPMM, DPM, FullContract } from '../../common/contract'
|
||||||
import { parseWordsAsTags } from '../../common/util/parse'
|
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 { InfoTooltip } from '../components/info-tooltip'
|
||||||
import { Col } from '../components/layout/col'
|
import { Col } from '../components/layout/col'
|
||||||
import { Row } from '../components/layout/row'
|
import { Row } from '../components/layout/row'
|
||||||
|
@ -241,7 +241,7 @@ ${TEST_VALUE}
|
||||||
You earn ${0.01 * 100}% of trading volume.`}
|
You earn ${0.01 * 100}% of trading volume.`}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<AmountInput
|
<BuyAmountInput
|
||||||
amount={ante}
|
amount={ante}
|
||||||
minimumAmount={10}
|
minimumAmount={10}
|
||||||
onChange={setAnte}
|
onChange={setAnte}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user