Clean up some stuff with SellPanel and AmountInput (#232)
* Hoist SellAmountInput logic into SellPanel * Ditch now-unnecessary SellAmountInput * Clean up sale proceeds markup * Clean unused imports * BuyPanel doesn't need userBets
This commit is contained in:
		
							parent
							
								
									d5cc6d5067
								
							
						
					
					
						commit
						aafd2a226f
					
				|  | @ -1,13 +1,8 @@ | ||||||
| import clsx from 'clsx' | import clsx from 'clsx' | ||||||
| import _ from 'lodash' |  | ||||||
| import { useUser } from 'web/hooks/use-user' | import { useUser } from 'web/hooks/use-user' | ||||||
| import { formatMoney, formatWithCommas } from 'common/util/format' | import { formatMoney } from 'common/util/format' | ||||||
| import { Col } from './layout/col' | import { Col } from './layout/col' | ||||||
| import { Row } from './layout/row' |  | ||||||
| import { Bet } from 'common/bet' |  | ||||||
| import { Spacer } from './layout/spacer' | import { Spacer } from './layout/spacer' | ||||||
| import { calculateCpmmSale } from 'common/calculate-cpmm' |  | ||||||
| import { Binary, CPMM, FullContract } from 'common/contract' |  | ||||||
| import { SiteLink } from './site-link' | import { SiteLink } from './site-link' | ||||||
| 
 | 
 | ||||||
| export function AmountInput(props: { | export function AmountInput(props: { | ||||||
|  | @ -20,7 +15,6 @@ export function AmountInput(props: { | ||||||
|   inputClassName?: string |   inputClassName?: string | ||||||
|   // Needed to focus the amount input
 |   // Needed to focus the amount input
 | ||||||
|   inputRef?: React.MutableRefObject<any> |   inputRef?: React.MutableRefObject<any> | ||||||
|   children?: any |  | ||||||
| }) { | }) { | ||||||
|   const { |   const { | ||||||
|     amount, |     amount, | ||||||
|  | @ -31,7 +25,6 @@ export function AmountInput(props: { | ||||||
|     className, |     className, | ||||||
|     inputClassName, |     inputClassName, | ||||||
|     inputRef, |     inputRef, | ||||||
|     children, |  | ||||||
|   } = props |   } = props | ||||||
| 
 | 
 | ||||||
|   const onAmountChange = (str: string) => { |   const onAmountChange = (str: string) => { | ||||||
|  | @ -78,8 +71,6 @@ export function AmountInput(props: { | ||||||
|           )} |           )} | ||||||
|         </div> |         </div> | ||||||
|       )} |       )} | ||||||
| 
 |  | ||||||
|       {children} |  | ||||||
|     </Col> |     </Col> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | @ -138,88 +129,3 @@ export function BuyAmountInput(props: { | ||||||
|     /> |     /> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| export function SellAmountInput(props: { |  | ||||||
|   contract: FullContract<CPMM, Binary> |  | ||||||
|   amount: number | undefined |  | ||||||
|   onChange: (newAmount: number | undefined) => void |  | ||||||
|   userBets: Bet[] |  | ||||||
|   error: string | undefined |  | ||||||
|   setError: (error: string | undefined) => void |  | ||||||
|   disabled?: boolean |  | ||||||
|   className?: string |  | ||||||
|   inputClassName?: string |  | ||||||
|   // Needed to focus the amount input
 |  | ||||||
|   inputRef?: React.MutableRefObject<any> |  | ||||||
| }) { |  | ||||||
|   const { |  | ||||||
|     contract, |  | ||||||
|     amount, |  | ||||||
|     onChange, |  | ||||||
|     userBets, |  | ||||||
|     error, |  | ||||||
|     setError, |  | ||||||
|     disabled, |  | ||||||
|     className, |  | ||||||
|     inputClassName, |  | ||||||
|     inputRef, |  | ||||||
|   } = props |  | ||||||
| 
 |  | ||||||
|   const user = useUser() |  | ||||||
| 
 |  | ||||||
|   const openUserBets = userBets.filter((bet) => !bet.isSold && !bet.sale) |  | ||||||
|   const [yesBets, noBets] = _.partition( |  | ||||||
|     openUserBets, |  | ||||||
|     (bet) => bet.outcome === 'YES' |  | ||||||
|   ) |  | ||||||
|   const [yesShares, noShares] = [ |  | ||||||
|     _.sumBy(yesBets, (bet) => bet.shares), |  | ||||||
|     _.sumBy(noBets, (bet) => bet.shares), |  | ||||||
|   ] |  | ||||||
| 
 |  | ||||||
|   const sellOutcome = yesShares ? 'YES' : noShares ? 'NO' : undefined |  | ||||||
|   const shares = Math.round(yesShares) || Math.round(noShares) |  | ||||||
| 
 |  | ||||||
|   const sharesSold = Math.min(amount ?? 0, shares) |  | ||||||
| 
 |  | ||||||
|   const { saleValue } = calculateCpmmSale( |  | ||||||
|     contract, |  | ||||||
|     sharesSold, |  | ||||||
|     sellOutcome as 'YES' | 'NO' |  | ||||||
|   ) |  | ||||||
| 
 |  | ||||||
|   const onAmountChange = (amount: number | undefined) => { |  | ||||||
|     onChange(amount) |  | ||||||
| 
 |  | ||||||
|     // Check for errors.
 |  | ||||||
|     if (amount !== undefined) { |  | ||||||
|       if (amount > shares) { |  | ||||||
|         setError(`Maximum ${formatWithCommas(Math.floor(shares))} shares`) |  | ||||||
|       } else { |  | ||||||
|         setError(undefined) |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return ( |  | ||||||
|     <AmountInput |  | ||||||
|       amount={amount} |  | ||||||
|       onChange={onAmountChange} |  | ||||||
|       label="Qty" |  | ||||||
|       error={error} |  | ||||||
|       disabled={disabled} |  | ||||||
|       className={className} |  | ||||||
|       inputClassName={inputClassName} |  | ||||||
|       inputRef={inputRef} |  | ||||||
|     > |  | ||||||
|       {user && ( |  | ||||||
|         <Col className="gap-3 text-sm"> |  | ||||||
|           <Row className="items-center justify-between gap-2 text-gray-500"> |  | ||||||
|             Sale proceeds{' '} |  | ||||||
|             <span className="text-neutral">{formatMoney(saleValue)}</span> |  | ||||||
|           </Row> |  | ||||||
|         </Col> |  | ||||||
|       )} |  | ||||||
|     </AmountInput> |  | ||||||
|   ) |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| import clsx from 'clsx' | import clsx from 'clsx' | ||||||
|  | import _ from 'lodash' | ||||||
| import React, { useEffect, useState } from 'react' | import React, { useEffect, useState } from 'react' | ||||||
| 
 | 
 | ||||||
| import { useUser } from 'web/hooks/use-user' | import { useUser } from 'web/hooks/use-user' | ||||||
|  | @ -16,7 +17,7 @@ import { Title } from './title' | ||||||
| import { firebaseLogin, User } from 'web/lib/firebase/users' | import { firebaseLogin, User } from 'web/lib/firebase/users' | ||||||
| import { Bet } from 'common/bet' | import { Bet } from 'common/bet' | ||||||
| import { placeBet, sellShares } from 'web/lib/firebase/api-call' | import { placeBet, sellShares } from 'web/lib/firebase/api-call' | ||||||
| import { BuyAmountInput, SellAmountInput } from './amount-input' | import { AmountInput, BuyAmountInput } from './amount-input' | ||||||
| import { InfoTooltip } from './info-tooltip' | import { InfoTooltip } from './info-tooltip' | ||||||
| import { BinaryOutcomeLabel } from './outcome-label' | import { BinaryOutcomeLabel } from './outcome-label' | ||||||
| import { | import { | ||||||
|  | @ -66,7 +67,7 @@ export function BetPanel(props: { | ||||||
|         <div className="mb-6 text-2xl">Place your bet</div> |         <div className="mb-6 text-2xl">Place your bet</div> | ||||||
|         {/* <Title className={clsx('!mt-0 text-neutral')} text="Place a trade" /> */} |         {/* <Title className={clsx('!mt-0 text-neutral')} text="Place a trade" /> */} | ||||||
| 
 | 
 | ||||||
|         <BuyPanel contract={contract} user={user} userBets={userBets ?? []} /> |         <BuyPanel contract={contract} user={user} /> | ||||||
| 
 | 
 | ||||||
|         {user === null && ( |         {user === null && ( | ||||||
|           <button |           <button | ||||||
|  | @ -177,7 +178,6 @@ export function BetPanelSwitcher(props: { | ||||||
|           <BuyPanel |           <BuyPanel | ||||||
|             contract={contract} |             contract={contract} | ||||||
|             user={user} |             user={user} | ||||||
|             userBets={userBets ?? []} |  | ||||||
|             selected={selected} |             selected={selected} | ||||||
|             onBuySuccess={onBetSuccess} |             onBuySuccess={onBetSuccess} | ||||||
|           /> |           /> | ||||||
|  | @ -199,11 +199,10 @@ export function BetPanelSwitcher(props: { | ||||||
| function BuyPanel(props: { | function BuyPanel(props: { | ||||||
|   contract: FullContract<DPM | CPMM, Binary> |   contract: FullContract<DPM | CPMM, Binary> | ||||||
|   user: User | null | undefined |   user: User | null | undefined | ||||||
|   userBets: Bet[] |  | ||||||
|   selected?: 'YES' | 'NO' |   selected?: 'YES' | 'NO' | ||||||
|   onBuySuccess?: () => void |   onBuySuccess?: () => void | ||||||
| }) { | }) { | ||||||
|   const { contract, user, userBets, selected, onBuySuccess } = props |   const { contract, user, selected, onBuySuccess } = props | ||||||
| 
 | 
 | ||||||
|   const [betChoice, setBetChoice] = useState<'YES' | 'NO' | undefined>(selected) |   const [betChoice, setBetChoice] = useState<'YES' | 'NO' | undefined>(selected) | ||||||
|   const [betAmount, setBetAmount] = useState<number | undefined>(undefined) |   const [betAmount, setBetAmount] = useState<number | undefined>(undefined) | ||||||
|  | @ -437,11 +436,43 @@ export function SellPanel(props: { | ||||||
|   ) |   ) | ||||||
|   const resultProb = getCpmmProbability(newPool, contract.p) |   const resultProb = getCpmmProbability(newPool, contract.p) | ||||||
| 
 | 
 | ||||||
|  |   const openUserBets = userBets.filter((bet) => !bet.isSold && !bet.sale) | ||||||
|  |   const [yesBets, noBets] = _.partition( | ||||||
|  |     openUserBets, | ||||||
|  |     (bet) => bet.outcome === 'YES' | ||||||
|  |   ) | ||||||
|  |   const [yesShares, noShares] = [ | ||||||
|  |     _.sumBy(yesBets, (bet) => bet.shares), | ||||||
|  |     _.sumBy(noBets, (bet) => bet.shares), | ||||||
|  |   ] | ||||||
|  | 
 | ||||||
|  |   const sellOutcome = yesShares ? 'YES' : noShares ? 'NO' : undefined | ||||||
|  |   const ownedShares = Math.round(yesShares) || Math.round(noShares) | ||||||
|  | 
 | ||||||
|  |   const sharesSold = Math.min(amount ?? 0, ownedShares) | ||||||
|  | 
 | ||||||
|  |   const { saleValue } = calculateCpmmSale( | ||||||
|  |     contract, | ||||||
|  |     sharesSold, | ||||||
|  |     sellOutcome as 'YES' | 'NO' | ||||||
|  |   ) | ||||||
|  | 
 | ||||||
|  |   const onAmountChange = (amount: number | undefined) => { | ||||||
|  |     setAmount(amount) | ||||||
|  | 
 | ||||||
|  |     // Check for errors.
 | ||||||
|  |     if (amount !== undefined) { | ||||||
|  |       if (amount > ownedShares) { | ||||||
|  |         setError(`Maximum ${formatWithCommas(Math.floor(ownedShares))} shares`) | ||||||
|  |       } else { | ||||||
|  |         setError(undefined) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <SellAmountInput |       <AmountInput | ||||||
|         inputClassName="w-full" |  | ||||||
|         contract={contract} |  | ||||||
|         amount={ |         amount={ | ||||||
|           amount |           amount | ||||||
|             ? Math.round(amount) === 0 |             ? Math.round(amount) === 0 | ||||||
|  | @ -449,15 +480,19 @@ export function SellPanel(props: { | ||||||
|               : Math.floor(amount) |               : Math.floor(amount) | ||||||
|             : undefined |             : undefined | ||||||
|         } |         } | ||||||
|         onChange={setAmount} |         onChange={onAmountChange} | ||||||
|         userBets={userBets} |         label="Qty" | ||||||
|         error={error} |         error={error} | ||||||
|         setError={setError} |  | ||||||
|         disabled={isSubmitting} |         disabled={isSubmitting} | ||||||
|  |         inputClassName="w-full" | ||||||
|       /> |       /> | ||||||
| 
 | 
 | ||||||
|       <Col className="mt-3 w-full gap-3"> |       <Col className="mt-3 w-full gap-3 text-sm"> | ||||||
|         <Row className="items-center justify-between text-sm"> |         <Row className="items-center justify-between gap-2 text-gray-500"> | ||||||
|  |           Sale proceeds | ||||||
|  |           <span className="text-neutral">{formatMoney(saleValue)}</span> | ||||||
|  |         </Row> | ||||||
|  |         <Row className="items-center justify-between"> | ||||||
|           <div className="text-gray-500">Probability</div> |           <div className="text-gray-500">Probability</div> | ||||||
|           <div> |           <div> | ||||||
|             {formatPercent(initialProb)} |             {formatPercent(initialProb)} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user