Skip to content

Commit

Permalink
feat: limit order mobile view (#8073)
Browse files Browse the repository at this point in the history
* refactor: make generic slide transition route

* chore: wip

* fix: route + header styling

* chore: style improvements

* fix: more style improvements

* fix: more style improvements

* chore: update imports

* chore: remove relative position
  • Loading branch information
0xApotheosis authored Nov 5, 2024
1 parent 37f5bb4 commit a96f515
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 96 deletions.
3 changes: 2 additions & 1 deletion src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -2717,7 +2717,8 @@
"filled": "Filled",
"cancelled": "Cancelled",
"expired": "Expired"
}
},
"orders": "Orders"
},
"thorFees": {
"title": "Here from THORSwap?",
Expand Down
7 changes: 5 additions & 2 deletions src/components/MultiHopTrade/MultiHopTrade.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import { useAppDispatch, useAppSelector } from 'state/store'

import { LimitOrder } from './components/LimitOrder/LimitOrder'
import { MultiHopTradeConfirm } from './components/MultiHopTradeConfirm/MultiHopTradeConfirm'
import { QuoteListRoute } from './components/QuoteList/QuoteListRoute'
import { QuoteList } from './components/QuoteList/QuoteList'
import { SlideTransitionRoute } from './components/SlideTransitionRoute'
import { Claim } from './components/TradeInput/components/Claim/Claim'
import { TradeInput } from './components/TradeInput/TradeInput'
import { VerifyAddresses } from './components/VerifyAddresses/VerifyAddresses'
Expand Down Expand Up @@ -155,9 +156,11 @@ const TradeRoutes = memo(({ isCompact }: TradeRoutesProps) => {
<VerifyAddresses />
</Route>
<Route key={TradeRoutePaths.QuoteList} path={TradeRoutePaths.QuoteList}>
<QuoteListRoute
<SlideTransitionRoute
height={tradeInputRef.current?.offsetHeight ?? '500px'}
width={tradeInputRef.current?.offsetWidth ?? 'full'}
component={QuoteList}
parentRoute={TradeRoutePaths.Input}
/>
</Route>
<Route key={TradeRoutePaths.Claim} path={TradeRoutePaths.Claim}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Flex } from '@chakra-ui/react'
import { useCallback } from 'react'
import { MemoryRouter, Route, Switch, useLocation } from 'react-router'
import type { TradeInputTab } from 'components/MultiHopTrade/types'
import { type TradeInputTab } from 'components/MultiHopTrade/types'

import { SlideTransitionRoute } from '../SlideTransitionRoute'
import { LimitOrderConfirm } from './components/LimitOrderConfirm'
import { LimitOrderInput } from './components/LimitOrderInput'
import { LimitOrderStatus } from './components/LimitOrderStatus'
import { LimitOrderList } from './LimitOrderList'
import { LimitOrderRoutePaths } from './types'

const LimitOrderRouteEntries = [
Expand Down Expand Up @@ -60,6 +62,14 @@ export const LimitOrder = ({ isCompact, tradeInputRef, onChangeTab }: LimitOrder
path={LimitOrderRoutePaths.Status}
render={renderLimitOrderStatus}
/>
<Route key={LimitOrderRoutePaths.QuoteList} path={LimitOrderRoutePaths.QuoteList}>
<SlideTransitionRoute
height={tradeInputRef.current?.offsetHeight ?? '500px'}
width={tradeInputRef.current?.offsetWidth ?? 'full'}
component={LimitOrderList}
parentRoute={LimitOrderRoutePaths.Input}
/>
</Route>
</Flex>
</Switch>
</MemoryRouter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
Card,
CardBody,
CardHeader,
Flex,
Heading,
Tab,
TabList,
TabPanel,
Expand All @@ -11,22 +13,33 @@ import {
} from '@chakra-ui/react'
import { foxAssetId } from '@shapeshiftoss/caip'
import type { FC } from 'react'
import { useMemo } from 'react'
import { usdcAssetId } from 'test/mocks/accounts'
import { Text } from 'components/Text'

import { WithBackButton } from '../WithBackButton'
import { LimitOrderCard } from './components/LimitOrderCard'
import { LimitOrderStatus } from './types'

type LimitOrderListProps = {
isLoading: boolean
cardProps?: CardProps
onBack?: () => void
}

const textColorBaseProps = {
color: 'text.base',
}
export const LimitOrderList: FC<LimitOrderListProps> = ({ cardProps, onBack }) => {
const textColorBaseProps = useMemo(() => {
return {
color: 'text.base',
...(onBack && {
bg: 'blue.500',
px: 4,
py: 2,
borderRadius: 'full',
}),
}
}, [onBack])

export const LimitOrderList: FC<LimitOrderListProps> = ({ cardProps }) => {
// FIXME: Use real data
const MockOpenOrderCard = () => (
<LimitOrderCard
Expand Down Expand Up @@ -56,48 +69,61 @@ export const LimitOrderList: FC<LimitOrderListProps> = ({ cardProps }) => {

return (
<Card {...cardProps}>
<CardHeader px={0} pt={4} h='full'>
<Tabs variant='unstyled' display='flex' flexDirection='column' h='full'>
<TabList gap={4} flex='0 0 auto' mb={2} ml={6}>
<Tab
p={0}
fontSize='md'
fontWeight='bold'
color='text.subtle'
_selected={textColorBaseProps}
>
<Text translation='limitOrders.openOrders' />
</Tab>
<Tab
p={0}
fontSize='md'
fontWeight='bold'
color='text.subtle'
_selected={textColorBaseProps}
>
<Text translation='limitOrders.orderHistory' />
</Tab>
</TabList>
{onBack && (
<CardHeader px={4} display='flex' flexDirection='column' pb={0} width='100%'>
<Flex width='100%' alignItems='center'>
<Flex flex='1' justifyContent='flex-start'>
<WithBackButton onBack={onBack} />
</Flex>
<Heading flex='2' textAlign='center' fontSize='md'>
<Text translation='limitOrders.orders' />
</Heading>
<Flex flex='1' />
</Flex>
</CardHeader>
)}

<TabPanels flex='1' overflowY='auto' minH={0} px={2}>
<TabPanel px={0}>
<Tabs variant='unstyled' display='flex' flexDirection='column' overflowY='auto' mt={4}>
<TabList gap={4} flex='0 0 auto' mb={2} ml={4}>
<Tab
p={0}
fontSize='md'
fontWeight='bold'
color={onBack ? 'text.base' : 'text.subtle'}
_selected={textColorBaseProps}
>
<Text translation='limitOrders.openOrders' />
</Tab>
<Tab
p={0}
fontSize='md'
fontWeight='bold'
color={onBack ? 'text.base' : 'text.subtle'}
_selected={textColorBaseProps}
>
<Text translation='limitOrders.orderHistory' />
</Tab>
</TabList>
<CardBody flex='1' overflowY='auto' minH={0} px={2} py={0}>
<TabPanels>
<TabPanel px={0} py={0}>
<CardBody px={0} overflowY='auto' flex='1 1 auto'>
{Array.from({ length: 3 }).map((_, index) => (
{Array.from({ length: 5 }).map((_, index) => (
<MockOpenOrderCard key={index} />
))}
</CardBody>
</TabPanel>

<TabPanel px={0}>
<TabPanel px={0} py={0}>
<CardBody px={0} overflowY='auto' flex='1 1 auto'>
{Array.from({ length: 2 }).map((_, index) => (
<MockHistoryOrderCard key={index} />
))}
</CardBody>
</TabPanel>
</TabPanels>
</Tabs>
</CardHeader>
</CardBody>
</Tabs>
</Card>
)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Divider, Stack } from '@chakra-ui/react'
import { Divider, Stack, useMediaQuery } from '@chakra-ui/react'
import { skipToken } from '@reduxjs/toolkit/query'
import { foxAssetId, fromAccountId, usdcAssetId } from '@shapeshiftoss/caip'
import { isLedger } from '@shapeshiftoss/hdwallet-ledger'
import { SwapperName } from '@shapeshiftoss/swapper'
import type { Asset } from '@shapeshiftoss/types'
import { bnOrZero, toBaseUnit } from '@shapeshiftoss/utils'
import { noop } from 'lodash'
import type { FormEvent } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useFormContext } from 'react-hook-form'
Expand Down Expand Up @@ -34,6 +33,7 @@ import {
selectShouldShowTradeQuoteOrAwaitInput,
} from 'state/slices/tradeQuoteSlice/selectors'
import { useAppSelector } from 'state/store'
import { breakpoints } from 'theme/theme'

import { SharedTradeInput } from '../../SharedTradeInput/SharedTradeInput'
import { SharedTradeInputBody } from '../../SharedTradeInput/SharedTradeInputBody'
Expand Down Expand Up @@ -67,6 +67,7 @@ export const LimitOrderInput = ({
const { manualReceiveAddress, walletReceiveAddress } = useReceiveAddress({
fetchUnchainedAddress: Boolean(wallet && isLedger(wallet)),
})
const [isSmallerThanXl] = useMediaQuery(`(max-width: ${breakpoints.xl})`, { ssr: false })

const [sellAsset, setSellAsset] = useState(localAssetData[usdcAssetId] ?? defaultAsset)
const [buyAsset, setBuyAsset] = useState(localAssetData[foxAssetId] ?? defaultAsset)
Expand Down Expand Up @@ -97,6 +98,11 @@ export const LimitOrderInput = ({
selectIsAnyAccountMetadataLoadedForChainId(state, isAnyAccountMetadataLoadedForChainIdFilter),
)

const handleOpenCompactQuoteList = useCallback(() => {
if (!isCompact && !isSmallerThanXl) return
history.push({ pathname: LimitOrderRoutePaths.QuoteList })
}, [history, isCompact, isSmallerThanXl])

const isVotingPowerLoading = useMemo(
() => isSnapshotApiQueriesPending && votingPower === undefined,
[isSnapshotApiQueriesPending, votingPower],
Expand Down Expand Up @@ -319,7 +325,7 @@ export const LimitOrderInput = ({
isError={false}
isLoading={isLoading}
manualAddressEntryDescription={undefined}
onRateClick={noop}
onRateClick={handleOpenCompactQuoteList}
quoteStatusTranslation={'trade.previewTrade'}
rate={activeQuote?.rate}
receiveAddress={manualReceiveAddress ?? walletReceiveAddress}
Expand All @@ -336,6 +342,7 @@ export const LimitOrderInput = ({
}, [
activeQuote?.rate,
buyAsset,
handleOpenCompactQuoteList,
hasUserEnteredAmount,
isCompact,
isLoading,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum LimitOrderRoutePaths {
Input = '/trade/limit-order/input',
Confirm = '/trade/limit-order/confirm',
Status = '/trade/limit-order/status',
QuoteList = '/trade/limit-order-quote-list',
}

export enum LimitOrderStatus {
Expand Down
17 changes: 3 additions & 14 deletions src/components/MultiHopTrade/components/QuoteList/QuoteList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { CardProps } from '@chakra-ui/react'
import { Card, CardBody, CardHeader, Heading } from '@chakra-ui/react'
import { useMemo } from 'react'
import { Text } from 'components/Text'

import { TradeQuotes } from '../TradeInput/components/TradeQuotes/TradeQuotes'
Expand All @@ -9,20 +8,10 @@ import { WithBackButton } from '../WithBackButton'
type QuoteListProps = {
onBack?: () => void
isLoading: boolean
} & CardProps

export const QuoteList: React.FC<QuoteListProps> = props => {
const { onBack, isLoading, cardProps } = useMemo(() => {
const { onBack, isLoading, ...cardProps } = props

return {
onBack,
isLoading,
cardProps,
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, Object.values(props))
cardProps?: CardProps
}

export const QuoteList: React.FC<QuoteListProps> = ({ onBack, isLoading, cardProps }) => {
return (
<Card {...cardProps}>
<CardHeader px={6} pt={4}>
Expand Down

This file was deleted.

57 changes: 57 additions & 0 deletions src/components/MultiHopTrade/components/SlideTransitionRoute.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import type { CardProps } from '@chakra-ui/react'
import { Center, Flex, useMediaQuery } from '@chakra-ui/react'
import type { FC } from 'react'
import { useCallback, useMemo, useState } from 'react'
import { useHistory } from 'react-router'
import { TradeSlideTransition } from 'components/MultiHopTrade/TradeSlideTransition'
import type { TradeRoutePaths } from 'components/MultiHopTrade/types'
import { breakpoints } from 'theme/theme'

import type { LimitOrderRoutePaths } from './LimitOrder/types'

type SlideTransitionComponentProps = {
onBack?: () => void
isLoading: boolean
cardProps?: CardProps
}

type SlideTransitionRouteProps = {
height: string | number
width: string | number
component: FC<SlideTransitionComponentProps>
parentRoute: TradeRoutePaths | LimitOrderRoutePaths
}

export const SlideTransitionRoute = ({
width: initialWidth,
height: initialHeight,
component: Component,
parentRoute,
}: SlideTransitionRouteProps) => {
const [width] = useState(initialWidth)
const [height] = useState(initialHeight)
const history = useHistory()
const [isSmallerThanXl] = useMediaQuery(`(max-width: ${breakpoints.xl})`)

const handleBack = useCallback(() => {
history.push({ pathname: parentRoute })
}, [history, parentRoute])

const cardProps: CardProps = useMemo(
() => ({
width,
height,
}),
[width, height],
)

return (
<TradeSlideTransition>
<Flex width='full' justifyContent='center' maxWidth={isSmallerThanXl ? '500px' : undefined}>
<Center width='inherit'>
<Component onBack={handleBack} isLoading={false} cardProps={cardProps} />
</Center>
</Flex>
</TradeSlideTransition>
)
}
Loading

0 comments on commit a96f515

Please sign in to comment.