diff --git a/src/custom/pages/Claim/InvestmentFlow/InvestOption.tsx b/src/custom/pages/Claim/InvestmentFlow/InvestOption.tsx
index cc8951628..765e7c983 100644
--- a/src/custom/pages/Claim/InvestmentFlow/InvestOption.tsx
+++ b/src/custom/pages/Claim/InvestmentFlow/InvestOption.tsx
@@ -1,10 +1,10 @@
import { useCallback, useMemo, useState } from 'react'
import styled from 'styled-components/macro'
import CowProtocolLogo from 'components/CowProtocolLogo'
-import { formatUnits, parseUnits } from '@ethersproject/units'
-import { CurrencyAmount } from '@uniswap/sdk-core'
+import { formatUnits } from '@ethersproject/units'
+import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
-import { InvestTokenGroup, TokenLogo, InvestSummary, InvestInput } from '../styled'
+import { InvestTokenGroup, TokenLogo, InvestSummary, InvestInput, InvestAvailableBar } from '../styled'
import { formatSmart } from 'utils/format'
import Row from 'components/Row'
import { CheckCircle } from 'react-feather'
@@ -12,6 +12,7 @@ import { InvestOptionProps } from '.'
import { ApprovalState } from 'hooks/useApproveCallback'
import { useCurrencyBalance } from 'state/wallet/hooks'
import { useActiveWeb3React } from 'hooks/web3'
+import { useClaimDispatchers, useClaimState } from 'state/claim/hooks'
import { ButtonConfirmed } from 'components/Button'
import { ButtonSize } from 'theme'
@@ -29,14 +30,28 @@ const RangeStep = styled.button`
border: none;
font-size: 0.8rem;
cursor: pointer;
- color: blue;
+ color: ${({ theme }) => theme.primary1};
padding: 0;
`
-const INVESTMENT_STEPS = [0, 25, 50, 75, 100]
+const INVESTMENT_STEPS = ['0', '25', '50', '75', '100']
-export default function InvestOption({ approveData, updateInvestAmount, claim }: InvestOptionProps) {
- const { currencyAmount, price, cost: maxCost, investedAmount } = claim
+function _scaleValue(maxValue: CurrencyAmount, value: string) {
+ // parse percent to string, example 25% -> 4 or 50% -> 2
+ const parsedValue = new Fraction(value, '100')
+
+ // divide maxValue with parsed value to get invest amount
+ return maxValue.multiply(parsedValue).asFraction
+}
+
+export default function InvestOption({ approveData, claim, optionIndex }: InvestOptionProps) {
+ const { currencyAmount, price, cost: maxCost } = claim
+ const { updateInvestAmount } = useClaimDispatchers()
+ const { investFlowData } = useClaimState()
+
+ const investedAmount = useMemo(() => investFlowData[optionIndex].investedAmount, [investFlowData, optionIndex])
+
+ const [percentage, setPercentage] = useState(INVESTMENT_STEPS[0])
const { account } = useActiveWeb3React()
@@ -44,13 +59,21 @@ export default function InvestOption({ approveData, updateInvestAmount, claim }:
const balance = useCurrencyBalance(account || undefined, token)
- const handlePercentChange = (event: React.ChangeEvent) => {
- console.log(event.target.value)
- }
+ const decimals = balance?.currency?.decimals
- const handleStepChange = (value: number) => {
- console.log(value)
- }
+ const handleStepChange = useCallback(
+ (value: string) => {
+ if (!maxCost || !balance) {
+ return
+ }
+
+ const scaledCurrencyAmount = _scaleValue(maxCost, value)
+
+ updateInvestAmount({ index: optionIndex, amount: scaledCurrencyAmount.quotient.toString() })
+ setPercentage(value)
+ },
+ [balance, maxCost, optionIndex, updateInvestAmount]
+ )
const onMaxClick = useCallback(() => {
if (!maxCost || !balance) {
@@ -58,11 +81,10 @@ export default function InvestOption({ approveData, updateInvestAmount, claim }:
}
const amount = maxCost.greaterThan(balance) ? balance : maxCost
- // store the value as a string to prevent unnecessary re-renders
- const investAmount = formatUnits(amount.quotient.toString(), balance.currency.decimals)
- updateInvestAmount(claim.index, investAmount)
- }, [balance, claim.index, maxCost, updateInvestAmount])
+ updateInvestAmount({ index: optionIndex, amount: amount.quotient.toString() })
+ setPercentage(INVESTMENT_STEPS[INVESTMENT_STEPS.length - 1])
+ }, [balance, maxCost, optionIndex, updateInvestAmount])
// Cache approveData methods
const approveCallback = approveData?.approveCallback
@@ -84,11 +106,11 @@ export default function InvestOption({ approveData, updateInvestAmount, claim }:
}, [approveCallback, token?.symbol])
const vCowAmount = useMemo(() => {
- if (!token || !price) {
+ if (!token || !price || !investedAmount) {
return
}
- const investA = CurrencyAmount.fromRawAmount(token, parseUnits(investedAmount, token.decimals).toString())
+ const investA = CurrencyAmount.fromRawAmount(token, investedAmount)
return investA.multiply(price)
}, [investedAmount, price, token])
@@ -162,21 +184,14 @@ export default function InvestOption({ approveData, updateInvestAmount, claim }:
- {INVESTMENT_STEPS.map((step: number) => (
+ {INVESTMENT_STEPS.map((step: string) => (
handleStepChange(step)} key={step}>
{step}%
))}
-
+
@@ -194,7 +209,7 @@ export default function InvestOption({ approveData, updateInvestAmount, claim }:
{currencyAmount?.currency?.symbol}
diff --git a/src/custom/pages/Claim/InvestmentFlow/index.tsx b/src/custom/pages/Claim/InvestmentFlow/index.tsx
index 571ad517c..14ea94758 100644
--- a/src/custom/pages/Claim/InvestmentFlow/index.tsx
+++ b/src/custom/pages/Claim/InvestmentFlow/index.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState, useCallback } from 'react'
+import { useEffect, useMemo } from 'react'
import {
InvestFlow,
InvestContent,
@@ -7,20 +7,16 @@ import {
StepIndicator,
Steps,
} from 'pages/Claim/styled'
-import { ClaimType, useClaimState, useUserEnhancedClaimData } from 'state/claim/hooks'
+import { ClaimType, useClaimState, useUserEnhancedClaimData, useClaimDispatchers } from 'state/claim/hooks'
import { ClaimCommonTypes, EnhancedUserClaimData } from '../types'
import { ClaimStatus } from 'state/claim/actions'
import { useActiveWeb3React } from 'hooks/web3'
import { ApprovalState, OptionalApproveCallbackParams } from 'hooks/useApproveCallback'
import InvestOption from './InvestOption'
-export type InvestmentClaimProps = EnhancedUserClaimData & {
- investedAmount: string
-}
-
export type InvestOptionProps = {
- claim: InvestmentClaimProps
- updateInvestAmount: (idx: number, investAmount: string) => void
+ claim: EnhancedUserClaimData
+ optionIndex: number
approveData:
| { approveState: ApprovalState; approveCallback: (optionalParams?: OptionalApproveCallbackParams) => void }
| undefined
@@ -51,33 +47,18 @@ function _claimToTokenApproveData(claimType: ClaimType, tokenApproveData: TokenA
export default function InvestmentFlow({ hasClaims, isAirdropOnly, ...tokenApproveData }: InvestmentFlowProps) {
const { account } = useActiveWeb3React()
- const { activeClaimAccount, claimStatus, isInvestFlowActive, investFlowStep, selected } = useClaimState()
-
+ const { selected, activeClaimAccount, claimStatus, isInvestFlowActive, investFlowStep } = useClaimState()
+ const { initInvestFlowData } = useClaimDispatchers()
const claimData = useUserEnhancedClaimData(activeClaimAccount)
- const [investData, setInvestData] = useState([])
+ const selectedClaims = useMemo(() => {
+ return claimData.filter(({ index }) => selected.includes(index))
+ }, [claimData, selected])
useEffect(() => {
- if (claimData) {
- const data = claimData.reduce((acc, claim) => {
- if (selected.includes(claim.index)) {
- acc.push({ ...claim, investedAmount: '0' })
- }
-
- return acc
- }, [])
-
- setInvestData(data)
- }
- }, [selected, claimData])
-
- const updateInvestAmount = useCallback(
- (idx: number, investedAmount: string) => {
- const update = investData.map((claim) => (claim.index === idx ? { ...claim, investedAmount } : claim))
- setInvestData(update)
- },
- [investData]
- )
+ initInvestFlowData()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isInvestFlowActive])
if (
!activeClaimAccount || // no connected account
@@ -113,11 +94,11 @@ export default function InvestmentFlow({ hasClaims, isAirdropOnly, ...tokenAppro
up to a predefined maximum amount of tokens{' '}
- {investData.map((claim) => (
+ {selectedClaims.map((claim, index) => (
))}
diff --git a/src/custom/pages/Claim/styled.ts b/src/custom/pages/Claim/styled.ts
index c57d8e40e..2d921bdf5 100644
--- a/src/custom/pages/Claim/styled.ts
+++ b/src/custom/pages/Claim/styled.ts
@@ -917,17 +917,23 @@ export const InvestAvailableBar = styled.div<{ percentage?: number }>`
&::before {
content: '';
display: block;
- background: color: ${({ theme }) => theme.primary1};
+ background-color: ${({ theme }) => theme.primary1};
height: 100%;
border-radius: 24px;
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ transition: width 0.3s ease-in;
width: ${({ percentage }) => (percentage ? `${percentage}%` : '0%')};
}
&::after {
content: ${({ percentage }) => (percentage ? `'${percentage}%'` : '0%')};
display: inline-block;
- font-size: 13px;
- color: ${({ theme }) => theme.primary1};
+ font-size: 11px;
+ color: white;
+ transform: translate(-120%, -20%);
}
`
diff --git a/src/custom/state/claim/actions.ts b/src/custom/state/claim/actions.ts
index d6152753d..47fbcc4ab 100644
--- a/src/custom/state/claim/actions.ts
+++ b/src/custom/state/claim/actions.ts
@@ -12,14 +12,20 @@ export type ClaimActions = {
setInputAddress: (payload: string) => void
setActiveClaimAccount: (payload: string) => void
setActiveClaimAccountENS: (payload: string) => void
+
// search
setIsSearchUsed: (payload: boolean) => void
+
// claiming
setClaimStatus: (payload: ClaimStatus) => void
setClaimedAmount: (payload: number) => void
+
// investing
setIsInvestFlowActive: (payload: boolean) => void
setInvestFlowStep: (payload: number) => void
+ initInvestFlowData: () => void
+ updateInvestAmount: (payload: { index: number; amount: string }) => void
+
// claim row selection
setSelected: (payload: number[]) => void
setSelectedAll: (payload: boolean) => void
@@ -40,6 +46,11 @@ export const setClaimStatus = createAction('claim/setClaimStatus')
// investing
export const setIsInvestFlowActive = createAction('claim/setIsInvestFlowActive')
export const setInvestFlowStep = createAction('claim/setInvestFlowStep')
+export const initInvestFlowData = createAction('claim/initInvestFlowData')
+export const updateInvestAmount = createAction<{
+ index: number
+ amount: string
+}>('claim/updateInvestAmount')
// claim row selection
export const setSelected = createAction('claim/setSelected')
diff --git a/src/custom/state/claim/hooks/index.ts b/src/custom/state/claim/hooks/index.ts
index 030ecacfb..75c034a53 100644
--- a/src/custom/state/claim/hooks/index.ts
+++ b/src/custom/state/claim/hooks/index.ts
@@ -46,6 +46,8 @@ import {
setClaimedAmount,
setIsInvestFlowActive,
setInvestFlowStep,
+ initInvestFlowData,
+ updateInvestAmount,
setSelected,
setSelectedAll,
ClaimStatus,
@@ -723,6 +725,8 @@ export function useClaimDispatchers() {
// investing
setIsInvestFlowActive: (payload: boolean) => dispatch(setIsInvestFlowActive(payload)),
setInvestFlowStep: (payload: number) => dispatch(setInvestFlowStep(payload)),
+ initInvestFlowData: () => dispatch(initInvestFlowData()),
+ updateInvestAmount: (payload: { index: number; amount: string }) => dispatch(updateInvestAmount(payload)),
// claim row selection
setSelected: (payload: number[]) => dispatch(setSelected(payload)),
setSelectedAll: (payload: boolean) => dispatch(setSelectedAll(payload)),
diff --git a/src/custom/state/claim/reducer.ts b/src/custom/state/claim/reducer.ts
index 5f26481e6..3f8c42e9c 100644
--- a/src/custom/state/claim/reducer.ts
+++ b/src/custom/state/claim/reducer.ts
@@ -1,4 +1,4 @@
-import { createReducer } from '@reduxjs/toolkit'
+import { createReducer, current } from '@reduxjs/toolkit'
import {
setActiveClaimAccount,
setActiveClaimAccountENS,
@@ -7,6 +7,8 @@ import {
setInputAddress,
setInvestFlowStep,
setIsInvestFlowActive,
+ initInvestFlowData,
+ updateInvestAmount,
setIsSearchUsed,
setSelected,
setSelectedAll,
@@ -27,11 +29,19 @@ export const initialState: ClaimState = {
// investment
isInvestFlowActive: false,
investFlowStep: 0,
+ investFlowData: [],
// table select change
selected: [],
selectedAll: false,
}
+export type InvestClaim = {
+ index: number
+ inputAmount?: string
+ investedAmount?: string
+ vCowAmount?: string
+}
+
export type ClaimState = {
// address/ENS address
inputAddress: string
@@ -46,6 +56,7 @@ export type ClaimState = {
// investment
isInvestFlowActive: boolean
investFlowStep: number
+ investFlowData: InvestClaim[]
// table select change
selected: number[]
selectedAll: boolean
@@ -77,6 +88,20 @@ export default createReducer(initialState, (builder) =>
.addCase(setInvestFlowStep, (state, { payload }) => {
state.investFlowStep = payload
})
+ .addCase(initInvestFlowData, (state) => {
+ const { selected, isInvestFlowActive } = current(state)
+
+ const data = selected.map((index) => ({ index, investedAmount: '0' }))
+
+ if (isInvestFlowActive) {
+ state.investFlowData.push(...data)
+ } else {
+ state.investFlowData.length = 0
+ }
+ })
+ .addCase(updateInvestAmount, (state, { payload: { index, amount } }) => {
+ state.investFlowData[index].investedAmount = amount
+ })
.addCase(setSelected, (state, { payload }) => {
state.selected = payload
})