manifold/web/components/probability-input.tsx
James Grugett 3b953a7c21
Range limit orders (#655)
* Prototype range limit order UI

* Conditionally show YES or NO max payout

* Range bet executes both bets immediately.

* Validate lowLimitProb < highLimitProb

* Show error if low limit is higher than high limit

* Update range order UI

* Revert "Validate lowLimitProb < highLimitProb"

This reverts commit c261fc2743.

* Revert "Range bet executes both bets immediately."

This reverts commit 30b95d75d9.

* Buy panel only non-limit orders

* Bet choice => outcome

* More iterating on range UI

* betChoice => outcome

* Lighten placeholder text
2022-07-22 00:57:56 -05:00

95 lines
2.6 KiB
TypeScript

import clsx from 'clsx'
import { CPMMBinaryContract, PseudoNumericContract } from 'common/contract'
import { getPseudoProbability } from 'common/pseudo-numeric'
import { BucketInput } from './bucket-input'
import { Col } from './layout/col'
import { Spacer } from './layout/spacer'
export function ProbabilityInput(props: {
prob: number | undefined
onChange: (newProb: number | undefined) => void
disabled?: boolean
placeholder?: string
className?: string
inputClassName?: string
}) {
const { prob, onChange, disabled, placeholder, className, inputClassName } =
props
const onProbChange = (str: string) => {
let prob = parseInt(str.replace(/\D/g, ''))
const isInvalid = !str || isNaN(prob)
if (prob.toString().length > 2) {
if (prob === 100) prob = 99
else if (prob < 1) prob = 1
else prob = +prob.toString().slice(-2)
}
onChange(isInvalid ? undefined : prob)
}
return (
<Col className={className}>
<label className="input-group">
<input
className={clsx(
'input input-bordered max-w-[200px] text-lg placeholder:text-gray-400',
inputClassName
)}
type="number"
max={99}
min={1}
pattern="[0-9]*"
inputMode="numeric"
placeholder={placeholder ?? '0'}
maxLength={2}
value={prob ?? ''}
disabled={disabled}
onChange={(e) => onProbChange(e.target.value)}
/>
<span className="bg-gray-200 text-sm">%</span>
</label>
<Spacer h={4} />
</Col>
)
}
export function ProbabilityOrNumericInput(props: {
contract: CPMMBinaryContract | PseudoNumericContract
prob: number | undefined
setProb: (prob: number | undefined) => void
isSubmitting: boolean
placeholder?: string
}) {
const { contract, prob, setProb, isSubmitting, placeholder } = props
const isPseudoNumeric = contract.outcomeType === 'PSEUDO_NUMERIC'
return isPseudoNumeric ? (
<BucketInput
contract={contract}
onBucketChange={(value) =>
setProb(
value === undefined
? undefined
: 100 *
getPseudoProbability(
value,
contract.min,
contract.max,
contract.isLogScale
)
)
}
isSubmitting={isSubmitting}
placeholder={placeholder}
/>
) : (
<ProbabilityInput
inputClassName="w-full max-w-none"
prob={prob}
onChange={setProb}
disabled={isSubmitting}
placeholder={placeholder}
/>
)
}