Commit a11c7e95 authored by Jack Short's avatar Jack Short Committed by GitHub

feat: select input token for pay with any token (#5865)

* feat: select input token for pay with any token

* creating zustand state

* updating symbol

* cursor pointer
parent 31bbcae1
...@@ -3,6 +3,7 @@ import { parseEther } from '@ethersproject/units' ...@@ -3,6 +3,7 @@ import { parseEther } from '@ethersproject/units'
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics' import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, InterfaceElementName, NFTEventName } from '@uniswap/analytics-events' import { BrowserEvent, InterfaceElementName, NFTEventName } from '@uniswap/analytics-events'
import { Currency } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import Column from 'components/Column' import Column from 'components/Column'
import Loader from 'components/Loader' import Loader from 'components/Loader'
...@@ -12,6 +13,7 @@ import { SupportedChainId } from 'constants/chains' ...@@ -12,6 +13,7 @@ import { SupportedChainId } from 'constants/chains'
import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken' import { PayWithAnyTokenVariant, usePayWithAnyTokenFlag } from 'featureFlags/flags/payWithAnyToken'
import { useCurrency } from 'hooks/Tokens' import { useCurrency } from 'hooks/Tokens'
import { useBag } from 'nft/hooks/useBag' import { useBag } from 'nft/hooks/useBag'
import { useTokenInput } from 'nft/hooks/useTokenInput'
import { useWalletBalance } from 'nft/hooks/useWalletBalance' import { useWalletBalance } from 'nft/hooks/useWalletBalance'
import { BagStatus } from 'nft/types' import { BagStatus } from 'nft/types'
import { ethNumberStandardFormatter, formatWeiToDecimal } from 'nft/utils' import { ethNumberStandardFormatter, formatWeiToDecimal } from 'nft/utils'
...@@ -141,7 +143,9 @@ export const BagFooter = ({ ...@@ -141,7 +143,9 @@ export const BagFooter = ({
const { account, chainId, connector } = useWeb3React() const { account, chainId, connector } = useWeb3React()
const connected = Boolean(account && chainId) const connected = Boolean(account && chainId)
const shouldUsePayWithAnyToken = usePayWithAnyTokenFlag() === PayWithAnyTokenVariant.Enabled const shouldUsePayWithAnyToken = usePayWithAnyTokenFlag() === PayWithAnyTokenVariant.Enabled
const inputCurrency = useCurrency('ETH') const inputCurrency = useTokenInput((state) => state.inputCurrency)
const setInputCurrency = useTokenInput((state) => state.setInputCurrency)
const defaultCurrency = useCurrency('ETH')
const setBagExpanded = useBag((state) => state.setBagExpanded) const setBagExpanded = useBag((state) => state.setBagExpanded)
const [showTokenSelector, toggleTokenSelector] = useReducer((state) => !state, false) const [showTokenSelector, toggleTokenSelector] = useReducer((state) => !state, false)
...@@ -193,6 +197,7 @@ export const BagFooter = ({ ...@@ -193,6 +197,7 @@ export const BagFooter = ({
}, [bagStatus, chainId, connected, connector, fetchAssets, setBagExpanded, sufficientBalance, toggleWalletModal]) }, [bagStatus, chainId, connected, connector, fetchAssets, setBagExpanded, sufficientBalance, toggleWalletModal])
const isPending = PENDING_BAG_STATUSES.includes(bagStatus) const isPending = PENDING_BAG_STATUSES.includes(bagStatus)
const activeCurrency = inputCurrency ?? defaultCurrency
return ( return (
<FooterContainer> <FooterContainer>
...@@ -204,9 +209,9 @@ export const BagFooter = ({ ...@@ -204,9 +209,9 @@ export const BagFooter = ({
<Trans>Pay with</Trans> <Trans>Pay with</Trans>
</ThemedText.SubHeaderSmall> </ThemedText.SubHeaderSmall>
<CurrencyInput onClick={toggleTokenSelector}> <CurrencyInput onClick={toggleTokenSelector}>
<CurrencyLogo currency={inputCurrency} size="24px" /> <CurrencyLogo currency={activeCurrency} size="24px" />
<ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px"> <ThemedText.HeadlineSmall fontWeight={500} lineHeight="24px">
{inputCurrency?.symbol} {activeCurrency?.symbol}
</ThemedText.HeadlineSmall> </ThemedText.HeadlineSmall>
<ChevronDown size={20} color={theme.textSecondary} /> <ChevronDown size={20} color={theme.textSecondary} />
</CurrencyInput> </CurrencyInput>
...@@ -216,7 +221,7 @@ export const BagFooter = ({ ...@@ -216,7 +221,7 @@ export const BagFooter = ({
<Trans>Total</Trans> <Trans>Total</Trans>
</ThemedText.SubHeaderSmall> </ThemedText.SubHeaderSmall>
<ThemedText.HeadlineSmall> <ThemedText.HeadlineSmall>
{formatWeiToDecimal(totalEthPrice.toString())}&nbsp;ETH {formatWeiToDecimal(totalEthPrice.toString())}&nbsp;{activeCurrency?.symbol ?? 'ETH'}
</ThemedText.HeadlineSmall> </ThemedText.HeadlineSmall>
<ThemedText.BodySmall color="textSecondary" lineHeight="20px">{`${ethNumberStandardFormatter( <ThemedText.BodySmall color="textSecondary" lineHeight="20px">{`${ethNumberStandardFormatter(
totalUsdPrice, totalUsdPrice,
...@@ -259,7 +264,16 @@ export const BagFooter = ({ ...@@ -259,7 +264,16 @@ export const BagFooter = ({
</ActionButton> </ActionButton>
</TraceEvent> </TraceEvent>
</Footer> </Footer>
{showTokenSelector && <BagTokenSelectorModal overlayClick={toggleTokenSelector} />} {showTokenSelector && (
<BagTokenSelectorModal
selectedCurrency={activeCurrency ?? undefined}
handleCurrencySelect={(currency: Currency) => {
setInputCurrency(currency)
toggleTokenSelector()
}}
overlayClick={toggleTokenSelector}
/>
)}
</FooterContainer> </FooterContainer>
) )
} }
...@@ -47,7 +47,17 @@ const TokenSelectorContainer = styled(Column)` ...@@ -47,7 +47,17 @@ const TokenSelectorContainer = styled(Column)`
} }
` `
export const BagTokenSelectorModal = ({ overlayClick }: { overlayClick: () => void }) => { interface BagTokenSelectorModalProps {
selectedCurrency: Currency | undefined
handleCurrencySelect: (currency: Currency) => void
overlayClick: () => void
}
export const BagTokenSelectorModal = ({
selectedCurrency,
handleCurrencySelect,
overlayClick,
}: BagTokenSelectorModalProps) => {
const defaultTokens = useAllTokens() const defaultTokens = useAllTokens()
const [balances, balancesAreLoading] = useAllTokenBalances() const [balances, balancesAreLoading] = useAllTokenBalances()
const sortedTokens: Token[] = useMemo( const sortedTokens: Token[] = useMemo(
...@@ -90,7 +100,16 @@ export const BagTokenSelectorModal = ({ overlayClick }: { overlayClick: () => vo ...@@ -90,7 +100,16 @@ export const BagTokenSelectorModal = ({ overlayClick }: { overlayClick: () => vo
</TitleRow> </TitleRow>
<TokenSelectorContainer> <TokenSelectorContainer>
{currencies.map((currency) => { {currencies.map((currency) => {
return <CurrencyRow key={currency.isToken ? currency.wrapped.address : currency.name} currency={currency} /> return (
<CurrencyRow
key={currency.isToken ? currency.wrapped.address : currency.name}
currency={currency}
selected={
(!selectedCurrency && currency.isNative) || (!!selectedCurrency && selectedCurrency.equals(currency))
}
selectCurrency={handleCurrencySelect}
/>
)
})} })}
</TokenSelectorContainer> </TokenSelectorContainer>
</ModalWrapper> </ModalWrapper>
......
...@@ -4,12 +4,15 @@ import Column from 'components/Column' ...@@ -4,12 +4,15 @@ import Column from 'components/Column'
import CurrencyLogo from 'components/Logo/CurrencyLogo' import CurrencyLogo from 'components/Logo/CurrencyLogo'
import Row from 'components/Row' import Row from 'components/Row'
import useCurrencyBalance from 'lib/hooks/useCurrencyBalance' import useCurrencyBalance from 'lib/hooks/useCurrencyBalance'
import { Check } from 'react-feather'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
const TokenRow = styled(Row)` const TokenRow = styled(Row)`
padding: 8px 0px; padding: 8px 0px;
gap: 12px;
justify-content: space-between; justify-content: space-between;
cursor: pointer;
` `
const TokenInfoRow = styled(Row)` const TokenInfoRow = styled(Row)`
...@@ -24,12 +27,23 @@ const StyledBalanceText = styled(ThemedText.SubHeader)` ...@@ -24,12 +27,23 @@ const StyledBalanceText = styled(ThemedText.SubHeader)`
text-align: right; text-align: right;
` `
export const CurrencyRow = ({ currency }: { currency: Currency }) => { const StyledCheck = styled(Check)`
color: ${({ theme }) => theme.accentAction};
flex-shrink: 0;
`
interface CurrencyRowProps {
currency: Currency
selected: boolean
selectCurrency: (currency: Currency) => void
}
export const CurrencyRow = ({ currency, selected, selectCurrency }: CurrencyRowProps) => {
const { account } = useWeb3React() const { account } = useWeb3React()
const balance = useCurrencyBalance(account ?? undefined, currency) const balance = useCurrencyBalance(account ?? undefined, currency)
return ( return (
<TokenRow> <TokenRow onClick={() => selectCurrency(currency)}>
<TokenInfoRow> <TokenInfoRow>
<CurrencyLogo currency={currency} size="36px" /> <CurrencyLogo currency={currency} size="36px" />
<Column> <Column>
...@@ -42,6 +56,7 @@ export const CurrencyRow = ({ currency }: { currency: Currency }) => { ...@@ -42,6 +56,7 @@ export const CurrencyRow = ({ currency }: { currency: Currency }) => {
</Column> </Column>
</TokenInfoRow> </TokenInfoRow>
{balance && <Balance balance={balance} />} {balance && <Balance balance={balance} />}
{selected && <StyledCheck size={20} />}
</TokenRow> </TokenRow>
) )
} }
......
import { Currency } from '@uniswap/sdk-core'
import create from 'zustand'
import { devtools } from 'zustand/middleware'
interface TokenInputState {
inputCurrency: Currency | undefined
setInputCurrency: (currency: Currency | undefined) => void
clearInputCurrency: () => void
}
export const useTokenInput = create<TokenInputState>()(
devtools(
(set) => ({
inputCurrency: undefined,
setInputCurrency: (currency) => set(() => ({ inputCurrency: currency })),
clearInputCurrency: () => set(() => ({ inputCurrency: undefined })),
}),
{ name: 'useTokenInput' }
)
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment