Skip to content

Commit

Permalink
fix: update trade complete screen (#8240)
Browse files Browse the repository at this point in the history
  • Loading branch information
NeOMakinG authored Dec 3, 2024
1 parent cc235da commit 35c005c
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 43 deletions.
2 changes: 1 addition & 1 deletion src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@
"allowanceApprovalTxName": "Allowance approval tx:",
"tradeComplete": "You now have %{cryptoAmountFormatted} in your wallet on %{chainName}.",
"doAnotherTrade": "Do another trade",
"showDetails": "Show Details",
"summary": "Trade Summary",
"transactionSuccessful": "Transaction successful, waiting for confirmations",
"temp": {
"tradeSuccess": "Trade complete",
Expand Down
2 changes: 1 addition & 1 deletion src/assets/translations/fr/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@
"allowanceApprovalTxName": "Tx. d'autorisation d'allocation :",
"tradeComplete": "Vous disposez maintenant de %{cryptoAmountFormatted} dans votre porte-monnaie sur %{chainName}.",
"doAnotherTrade": "Faire un autre échange",
"showDetails": "Afficher les détails",
"summary": "Afficher le sommaire",
"transactionSuccessful": "Transaction réussie, en attente de confirmations",
"temp": {
"tradeSuccess": "Échange terminé",
Expand Down
76 changes: 76 additions & 0 deletions src/components/AnimatedCheck.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { BoxProps } from '@chakra-ui/react'
import { Box } from '@chakra-ui/react'
import { motion } from 'framer-motion'
import { useMemo } from 'react'

export const AnimatedCheck = ({
defaultDuration = 1000,
boxSize = 24,
color = 'green.500',
}: {
defaultDuration?: number
boxSize?: BoxProps['boxSize']
color?: BoxProps['color']
}) => {
const placeholderDuration = useMemo(() => defaultDuration / 1000 + 2, [defaultDuration])

const draw = useMemo(() => {
const drawDelay = placeholderDuration / 1.5 > 10 ? 5 : placeholderDuration / 1.5
return {
hidden: { pathLength: 0, opacity: 0 },
visible: () => ({
pathLength: 1,
opacity: 1,
transition: {
pathLength: {
delay: drawDelay,
type: 'spring',
duration: 2,
bounce: 0,
},
opacity: { delay: drawDelay, duration: 2 },
},
}),
}
}, [placeholderDuration])

const border = useMemo(() => {
return {
hidden: { pathLength: 0 },
visible: () => ({
pathLength: 1,
transition: {
pathLength: {
type: 'spring',
duration: placeholderDuration > 10 ? 10 : placeholderDuration,
bounce: 0,
},
},
}),
}
}, [placeholderDuration])

return (
<Box boxSize={boxSize} color={color}>
<motion.svg
xmlns='http://www.w3.org/2000/svg'
width='100%'
height='100%'
viewBox='0 0 24 24'
fill='none'
stroke='currentColor'
strokeWidth='1.5'
strokeLinecap='round'
strokeLinejoin='round'
initial='hidden'
animate='visible'
>
{/* Outer circle */}
<motion.path d='M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0' variants={border} />

{/* Checkmark */}
<motion.path d='M9 12l2 2l4 -4' variants={draw} />
</motion.svg>
</Box>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { TradeSlideTransition } from 'components/MultiHopTrade/TradeSlideTransit
import { TradeRoutePaths } from 'components/MultiHopTrade/types'
import { Text } from 'components/Text'
import { bnOrZero } from 'lib/bignumber/bignumber'
import { fromBaseUnit } from 'lib/math'
import {
selectActiveQuote,
selectConfirmedTradeExecutionState,
selectLastHop,
} from 'state/slices/tradeQuoteSlice/selectors'
import { tradeQuoteSlice } from 'state/slices/tradeQuoteSlice/tradeQuoteSlice'
import { TradeExecutionState } from 'state/slices/tradeQuoteSlice/types'
Expand All @@ -38,6 +40,7 @@ export const MultiHopTradeConfirm = memo(() => {
const [shouldShowWarningAcknowledgement, setShouldShowWarningAcknowledgement] = useState(false)
const activeQuote = useAppSelector(selectActiveQuote)
const { isModeratePriceImpact, priceImpactPercentage } = usePriceImpact(activeQuote)
const lastHop = useAppSelector(selectLastHop)

const initialActiveTradeIdRef = useRef(activeQuote?.id ?? '')

Expand Down Expand Up @@ -136,15 +139,22 @@ export const MultiHopTradeConfirm = memo(() => {
</Heading>
</WithBackButton>
</CardHeader>
{isTradeComplete ? (
{isTradeComplete && activeQuote && lastHop ? (
<TradeSuccess
handleBack={handleBack}
titleTranslation={
isArbitrumBridgeWithdraw ? 'bridge.arbitrum.success.tradeSuccess' : undefined
}
descriptionTranslation={
isArbitrumBridgeWithdraw ? 'bridge.arbitrum.success.withdrawComplete' : undefined
}
sellAsset={activeQuote?.steps[0].sellAsset}
buyAsset={activeQuote?.steps[0].buyAsset}
sellAmountCryptoPrecision={fromBaseUnit(
activeQuote.steps[0].sellAmountIncludingProtocolFeesCryptoBaseUnit,
activeQuote.steps[0].sellAsset.precision,
)}
buyAmountCryptoPrecision={fromBaseUnit(
lastHop.buyAmountAfterFeesCryptoBaseUnit,
lastHop.buyAsset.precision,
)}
>
<Hops
initialActiveTradeId={initialActiveTradeIdRef.current}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import { ArrowForwardIcon } from '@chakra-ui/icons'
import {
Box,
Button,
CardBody,
CardFooter,
Collapse,
Flex,
HStack,
Icon,
Stack,
useDisclosure,
} from '@chakra-ui/react'
import type { Asset } from '@shapeshiftoss/types'
import type { InterpolationOptions } from 'node-polyglot'
import { useMemo } from 'react'
import { useCallback } from 'react'
import { useTranslate } from 'react-polyglot'
import { Amount } from 'components/Amount/Amount'
import { AnimatedCheck } from 'components/AnimatedCheck'
import { AssetIcon } from 'components/AssetIcon'
import { SlideTransition } from 'components/SlideTransition'
import { RawText, Text } from 'components/Text'
import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton'
import { Text } from 'components/Text'
import { selectLastHop } from 'state/slices/tradeQuoteSlice/selectors'
import { useAppSelector } from 'state/store'

Expand All @@ -23,16 +29,20 @@ export type TradeSuccessProps = {
handleBack: () => void
children: JSX.Element
titleTranslation?: string | [string, InterpolationOptions]
descriptionTranslation?: string | [string, InterpolationOptions]
sellAsset?: Asset
buyAsset?: Asset
sellAmountCryptoPrecision?: string
buyAmountCryptoPrecision?: string
}

const pairProps = { showFirst: true }

export const TradeSuccess = ({
handleBack,
titleTranslation,
descriptionTranslation,
children,
sellAmountCryptoPrecision,
sellAsset,
buyAsset,
buyAmountCryptoPrecision,
}: TradeSuccessProps) => {
const translate = useTranslate()

Expand All @@ -42,43 +52,46 @@ export const TradeSuccess = ({

const lastHop = useAppSelector(selectLastHop)

const subText = useMemo(() => {
if (!lastHop) return ''

const manager = getChainAdapterManager()
const adapter = manager.get(lastHop.buyAsset.chainId)

if (!adapter) return ''
const AmountsLine = useCallback(() => {
if (!(sellAsset && buyAsset)) return null
if (!(sellAmountCryptoPrecision && buyAmountCryptoPrecision)) return null

const chainName = adapter.getDisplayName()

if (descriptionTranslation)
return typeof descriptionTranslation === 'string'
? translate(descriptionTranslation, {
symbol: lastHop.buyAsset.symbol,
chainName,
})
: translate(...descriptionTranslation)

return translate('trade.temp.tradeComplete', {
symbol: lastHop.buyAsset.symbol,
chainName,
})
}, [lastHop, translate, descriptionTranslation])
return (
<Flex justifyContent='center' alignItems='center' flexWrap='wrap' gap={2} px={4}>
<Flex alignItems='center' gap={2}>
<AssetIcon size='xs' assetId={sellAsset?.assetId} />
<Amount.Crypto
whiteSpace='nowrap'
value={sellAmountCryptoPrecision}
symbol={sellAsset.symbol}
/>
</Flex>
<Icon as={ArrowForwardIcon} boxSize={4} color='text.subtle' />
<Flex alignItems='center' gap={2}>
<AssetIcon size='xs' assetId={buyAsset?.assetId} />
<Amount.Crypto
whiteSpace='nowrap'
value={buyAmountCryptoPrecision}
symbol={buyAsset.symbol}
/>
</Flex>
</Flex>
)
}, [sellAsset, buyAsset, sellAmountCryptoPrecision, buyAmountCryptoPrecision])

if (!lastHop) return null

return (
<>
<CardBody pb={0} px={0}>
<SlideTransition>
<Box textAlign='center' py={4}>
<AssetIcon assetId={lastHop.buyAsset.assetId} mb={2} pairProps={pairProps} />
<Text translation={titleTranslation ?? 'trade.temp.tradeSuccess'} />
<RawText fontSize='md' color='gray.500' mt={2}>
{subText}
</RawText>
</Box>
<Flex flexDir='column' alignItems='center' textAlign='center' py={8} gap={6}>
<Stack alignItems='center'>
<AnimatedCheck boxSize={12} />
<Text translation={titleTranslation ?? 'trade.temp.tradeSuccess'} fontWeight='bold' />
</Stack>
<AmountsLine />
</Flex>
</SlideTransition>
</CardBody>
<CardFooter flexDir='column' gap={2} px={4}>
Expand All @@ -88,7 +101,7 @@ export const TradeSuccess = ({
</Button>
<HStack width='full' justifyContent='space-between' mt={4}>
<Button variant='link' onClick={handleToggle} px={2}>
{translate('trade.showDetails')}
{translate('trade.summary')}
</Button>
<TwirlyToggle isOpen={isOpen} onToggle={handleToggle} />
</HStack>
Expand Down

0 comments on commit 35c005c

Please sign in to comment.