Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
Disable claim review on zero or not approved (#2250)
Browse files Browse the repository at this point in the history
* Added redux boilerplate for storing invest errors

* Storing invest errors on redux rather than locally

* Disable review button when there's any error on investment approval

* Disable review button if all options are not approved or some is zero

* Fix zero input error and add currency to InsufficientBalance error msg

* Update some logic after develop merge

* Added quite some changes in the InvestOption code

* Small update

* Updated useEffect dependencies

* Reset percentage on error

* Refactor function call

Co-authored-by: Leandro <[email protected]>
Co-authored-by: Leandro Boscariol <[email protected]>
  • Loading branch information
3 people authored Jan 22, 2022
1 parent 6499a5b commit 4603884
Showing 1 changed file with 82 additions and 66 deletions.
148 changes: 82 additions & 66 deletions src/custom/pages/Claim/InvestmentFlow/InvestOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import { tryParseAmount } from 'state/swap/hooks'
import { calculateInvestmentAmounts, calculatePercentage } from 'state/claim/hooks/utils'
import { AMOUNT_PRECISION, PERCENTAGE_PRECISION } from 'constants/index'

enum ErrorMsgs {
InsufficientBalance = 'Insufficient balance to cover investment amount',
OverMaxInvestment = `Your investment amount can't be above the maximum investment allowed`,
const ErrorMsgs = {
InsufficientBalance: (symbol = '') => `Insufficient ${symbol} balance to cover investment amount`,
OverMaxInvestment: `Your investment amount can't be above the maximum investment allowed`,
InvestmentIsZero: `Your investment amount can't be zero`,
NotApproved: (symbol = '') => `Please approve ${symbol} token`,
}

export default function InvestOption({ approveData, claim, optionIndex }: InvestOptionProps) {
Expand Down Expand Up @@ -61,58 +63,18 @@ export default function InvestOption({ approveData, claim, optionIndex }: Invest
const isSelfClaiming = account === activeClaimAccount
const noBalance = !balance || balance.equalTo('0')

const isApproved = approveData?.approveState === ApprovalState.APPROVED
const isNative = token?.isNative

// on invest max amount click handler
const setMaxAmount = useCallback(() => {
if (!maxCost || noBalance) {
return
}

const value = maxCost.greaterThan(balance) ? balance : maxCost
const amount = value.quotient.toString()

setInvestedAmount(amount)
setTypedValue(value.toExact() || '')
resetInputError()

setPercentage(_formatPercentage(calculatePercentage(balance, maxCost)))
}, [balance, maxCost, noBalance, resetInputError, setInvestedAmount])

// on input field change handler
const onInputChange = useCallback(
(value: string) => {
setTypedValue(value)
resetInputError()

// parse to CurrencyAmount
const parsedAmount = tryParseAmount(value, token)

// no amount/necessary params, return 0
if (!parsedAmount || !maxCost || !balance || !token) {
setInvestedAmount('0')
setPercentage('0')
return
}

let errorMsg = null

if (parsedAmount.greaterThan(maxCost)) errorMsg = ErrorMsgs.OverMaxInvestment
else if (parsedAmount.greaterThan(balance)) errorMsg = ErrorMsgs.InsufficientBalance

if (errorMsg) {
setInputError(errorMsg)
setInvestedAmount('0')
setPercentage('0')
return
}

// update redux state with new investAmount value
setInvestedAmount(parsedAmount.quotient.toString())

// update the local state with percentage value
setPercentage(_formatPercentage(calculatePercentage(parsedAmount, maxCost)))
},
[balance, maxCost, resetInputError, setInputError, setInvestedAmount, token]
)
}, [balance, maxCost, noBalance])

// Cache approveData methods
const approveCallback = approveData?.approveCallback
Expand Down Expand Up @@ -142,32 +104,86 @@ export default function InvestOption({ approveData, claim, optionIndex }: Invest
[claim, investedAmount]
)

// if its claiming for someone else we will set values to max
// if there is not enough balance then we will set an error
// if there is investmentAmount in redux state for this option set it as typedValue
useEffect(() => {
if (!isSelfClaiming) {
if (!balance || !maxCost) {
return
}
const { investmentCost } = calculateInvestmentAmounts(claim, investedAmount)

if (balance.lessThan(maxCost)) {
setInputError(ErrorMsgs.InsufficientBalance)
} else {
setMaxAmount()
}
if (!investmentCost) {
return
}
}, [balance, isSelfClaiming, maxCost, optionIndex, setInputError, setMaxAmount])

// this will set input and percentage value if you go back from the review page
useEffect(() => {
const { investmentCost } = calculateInvestmentAmounts(claim, investedAmount)

if (investmentCost) {
onInputChange(investmentCost?.toExact())
if (!investmentCost?.equalTo(0)) {
setTypedValue(investmentCost?.toExact())
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

// if we are claiming for someone else we will set values to max
useEffect(() => {
if (!balance || !maxCost) {
return
}

if (!isSelfClaiming && !balance.lessThan(maxCost)) {
setMaxAmount()
}
}, [balance, isSelfClaiming, maxCost, setMaxAmount])

// handle input value change
useEffect(() => {
let error = null

const parsedAmount = tryParseAmount(typedValue, token)

if (!maxCost || !balance) {
return
}

// set different errors in order of importance
if (balance.lessThan(maxCost) && !isSelfClaiming) {
error = ErrorMsgs.InsufficientBalance(token?.symbol)
} else if (!isNative && !isApproved) {
error = ErrorMsgs.NotApproved(token?.symbol)
} else if (!parsedAmount) {
error = ErrorMsgs.InvestmentIsZero
} else if (parsedAmount.greaterThan(maxCost)) {
error = ErrorMsgs.OverMaxInvestment
} else if (parsedAmount.greaterThan(balance)) {
error = ErrorMsgs.InsufficientBalance(token?.symbol)
}

if (error) {
// if there is error set it in redux
setInputError(error)
setPercentage('0')
} else {
if (!parsedAmount) {
return
}
// basically the magic happens in this block

// update redux state to remove errro for this field
resetInputError()

// update redux state with new investAmount value
setInvestedAmount(parsedAmount.quotient.toString())

// update the local state with percentage value
setPercentage(_formatPercentage(calculatePercentage(parsedAmount, maxCost)))
}
}, [
balance,
typedValue,
isSelfClaiming,
token,
isNative,
isApproved,
maxCost,
setInputError,
resetInputError,
setInvestedAmount,
])

return (
<InvestTokenGroup>
<div>
Expand Down Expand Up @@ -258,7 +274,7 @@ export default function InvestOption({ approveData, claim, optionIndex }: Invest
)}
</span>
<StyledNumericalInput
onUserInput={onInputChange}
onUserInput={setTypedValue}
disabled={noBalance || !isSelfClaiming}
placeholder="0"
$loading={false}
Expand Down

0 comments on commit 4603884

Please sign in to comment.