Skip to content

Commit

Permalink
feat: add no routes available message
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed Jul 13, 2022
1 parent 065ee86 commit 797db9c
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 74 deletions.
15 changes: 5 additions & 10 deletions packages/widget-embedded/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-constant-condition */
import { LiFiWidget, LiFiWidgetDrawer, WidgetConfig } from '@lifi/widget';
import {
Box,
Expand Down Expand Up @@ -380,15 +379,11 @@ const App = () => {

root.render(
<React.StrictMode>
{true ? (
<BrowserRouter>
<Routes>
<Route path="/*" element={<App />} />
</Routes>
</BrowserRouter>
) : (
<App />
)}
<BrowserRouter>
<Routes>
<Route path="*" element={<App />} />
</Routes>
</BrowserRouter>
</React.StrictMode>,
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Box, BoxProps, Skeleton } from '@mui/material';
import { Card } from './SwapRouteCard.style';
import { SwapRouteCardSkeletonProps } from './types';

export const SwapRouteCardSkeleton: React.FC<
SwapRouteCardSkeletonProps & BoxProps
> = ({ active, dense, ...other }) => {
return (
<Card dense={dense} {...other}>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}
>
<Skeleton
variant="rectangular"
width={120}
height={24}
sx={{ borderRadius: 0.5 }}
/>
{active ? <Skeleton variant="circular" width={24} height={24} /> : null}
</Box>
<Box my={2}>
<Box
sx={{
display: 'flex',
alignItems: 'center',
}}
>
<Box mr={2}>
<Skeleton variant="circular" width={32} height={32} />
</Box>
<Skeleton variant="text" width={96} height={32} />
</Box>
<Box ml={6}>
<Skeleton variant="text" width={56} height={22} />
</Box>
</Box>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<Box>
<Skeleton variant="text" width={56} height={22} />
<Skeleton variant="text" width={52} height={15} />
</Box>
<Box
sx={{
display: 'flex',
alignItems: 'flex-end',
flexDirection: 'column',
}}
>
<Skeleton variant="text" width={40} height={22} />
<Skeleton variant="text" width={48} height={15} />
</Box>
</Box>
</Card>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Route as RouteIcon } from '@mui/icons-material';
import { Box, BoxProps, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { Card } from './SwapRouteCard.style';
import { SwapRouteCardSkeletonProps } from './types';

export const SwapRouteNotFoundCard: React.FC<
SwapRouteCardSkeletonProps & BoxProps
> = ({ active, dense, ...other }) => {
const { t } = useTranslation();
return (
<Card active={active} dense={dense} {...other}>
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
flex: 1,
}}
py={1.375}
>
<RouteIcon fontSize="large" />
<Typography fontSize={16} fontWeight="500" mt={2}>
{t('swap.info.title.routeNotFound')}
</Typography>
<Typography
fontSize={14}
color="text.secondary"
textAlign="center"
mt={1}
>
{t('swap.info.message.routeNotFound')}
</Typography>
</Box>
</Card>
);
};
2 changes: 2 additions & 0 deletions packages/widget/src/components/SwapRouteCard/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './SwapRouteCard';
export * from './SwapRouteCardSkeleton';
export * from './SwapRouteNotFoundCard';
6 changes: 6 additions & 0 deletions packages/widget/src/components/SwapRouteCard/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ export interface SwapRouteCardProps {
active?: boolean;
blur?: boolean;
}

export interface SwapRouteCardSkeletonProps {
dense?: boolean;
active?: boolean;
blur?: boolean;
}
72 changes: 40 additions & 32 deletions packages/widget/src/components/SwapRoutes/SwapRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,75 @@
/* eslint-disable react/no-array-index-key */
import { KeyboardArrowRight as KeyboardArrowRightIcon } from '@mui/icons-material';
import { Box, BoxProps, IconButton, Skeleton, Theme } from '@mui/material';
import { Box, BoxProps, IconButton } from '@mui/material';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useSwapRoutes } from '../../hooks';
import { useCurrentRoute } from '../../stores';
import { routes } from '../../utils/routes';
import { CardContainer, CardTitle } from '../Card';
import { SwapRouteCard } from '../SwapRouteCard';
import {
SwapRouteCard,
SwapRouteCardSkeleton,
SwapRouteNotFoundCard,
} from '../SwapRouteCard';
import { Stack } from './SwapRoutes.style';
import { SwapRoutesUpdateProgress } from './SwapRoutesUpdateProgress';

export const SwapRoutes: React.FC<BoxProps> = (props) => {
const { t } = useTranslation();
const navigate = useNavigate();
const [currentRoute] = useCurrentRoute();
const { routes: swapRoutes, isLoading, isFetching } = useSwapRoutes();
const {
routes: swapRoutes,
isLoading,
isFetching,
isFetched,
} = useSwapRoutes();

const handleCardClick = useCallback(() => {
navigate(routes.swapRoutes);
}, [navigate]);

if (!swapRoutes?.length && !isLoading && !isFetching) {
if (!swapRoutes?.length && !isLoading && !isFetching && !isFetched) {
return null;
}

const routeNotFound = !swapRoutes?.length && isFetched;

return (
<CardContainer {...props}>
<CardTitle>{t('swap.routes')}</CardTitle>
<SwapRoutesUpdateProgress
sx={{
position: 'absolute',
top: 8,
right: 8,
}}
/>
{!routeNotFound ? (
<SwapRoutesUpdateProgress
sx={{
position: 'absolute',
top: 8,
right: 8,
}}
/>
) : null}
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Stack direction="row" py={2} pl={2} pr={1}>
{isLoading || isFetching || !currentRoute ? (
<Skeleton
variant="rectangular"
width="100%"
height={181}
sx={(theme: Theme) => ({
borderRadius:
theme.shape.borderRadiusSecondary / theme.shape.borderRadius,
minWidth: '100%',
})}
/>
<Stack direction="row" py={2} pl={2} pr={routeNotFound ? 2 : 1}>
{routeNotFound ? (
<SwapRouteNotFoundCard minWidth="100%" dense />
) : isLoading || isFetching || !currentRoute ? (
<SwapRouteCardSkeleton minWidth="100%" active dense />
) : (
<SwapRouteCard minWidth="100%" route={currentRoute} active dense />
)}
</Stack>
<Box py={1} pr={1}>
<IconButton
onClick={handleCardClick}
size="medium"
aria-label="swap-routes"
>
<KeyboardArrowRightIcon />
</IconButton>
</Box>
{!routeNotFound ? (
<Box py={1} pr={1}>
<IconButton
onClick={handleCardClick}
size="medium"
aria-label="swap-routes"
>
<KeyboardArrowRightIcon />
</IconButton>
</Box>
) : null}
</Box>
</CardContainer>
);
Expand Down
14 changes: 11 additions & 3 deletions packages/widget/src/i18n/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,22 @@
"fundsReceived": "You now have {{amount}} {{tokenSymbol}} in your wallet on {{chainName}} chain."
}
},
"info": {
"title": {
"routeNotFound": "No routes available"
},
"message": {
"routeNotFound": "Try another \"from\" and \"to\" token combination."
}
},
"warning": {
"title": {
"insufficientGas": "Insufficient gas"
},
"message": {
"insufficientFunds": "You don't have enough funds for this transaction on the start from chain.",
"insufficientGasOnStartChain": "You need to have enough gas to pay for this transaction on the start from chain.",
"insufficientGasOnDestinationChain": "You need to have enough gas to pay for this transaction on the destination “to” chain."
"insufficientFunds": "You don't have enough funds for this transaction on the start \"from\" chain.",
"insufficientGasOnStartChain": "You need to have enough gas to pay for this transaction on the start \"from\" chain.",
"insufficientGasOnDestinationChain": "You need to have enough gas to pay for this transaction on the destination \"to\" chain."
}
},
"error": {
Expand Down
67 changes: 38 additions & 29 deletions packages/widget/src/pages/SwapRoutesPage/SwapRoutesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,62 @@
/* eslint-disable react/no-array-index-key */
import { Route } from '@lifi/sdk';
import { BoxProps, Skeleton } from '@mui/material';
import { BoxProps } from '@mui/material';
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { SwapRouteCard } from '../../components/SwapRouteCard';
import {
SwapRouteCard,
SwapRouteCardSkeleton,
SwapRouteNotFoundCard,
} from '../../components/SwapRouteCard';
import { useSwapRoutes } from '../../hooks';
import { useCurrentRoute, useSetExecutableRoute } from '../../stores';
import { routes } from '../../utils/routes';
import { Stack } from './SwapRoutesPage.style';

export const SwapRoutesPage: React.FC<BoxProps> = () => {
const navigate = useNavigate();
const { routes: swapRoutes, isLoading, isFetching } = useSwapRoutes();
const {
routes: swapRoutes,
isLoading,
isFetching,
isFetched,
} = useSwapRoutes();
const [currentRoute] = useCurrentRoute();
const setExecutableRoute = useSetExecutableRoute();

if (!swapRoutes?.length && !isLoading && !isFetching) {
// TODO: make no routes message
return null;
}

const handleRouteClick = (route: Route) => {
setExecutableRoute(route);
navigate(routes.swap, { state: { routeId: route.id }, replace: true });
};

// A route for this transaction does not exist yet possibly due to liquidity issues or because the amount of tokens you are sending is below the bridge minimum amount.
// Please try again later or change the tokens you intend to swap.
// If the problem persists, come to our Discord and leave a message in the support channel.
useEffect(() => {
if (!swapRoutes?.length && !isLoading && !isFetching) {
navigate(routes.home);
}
// redirect to the home page if no routes are found on page reload
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const routeNotFound = !swapRoutes?.length && isFetched;

return (
<Stack direction="column" spacing={2}>
{isLoading || isFetching
? Array.from({ length: 3 }).map((_, index) => (
<Skeleton
key={index}
variant="rectangular"
width="100%"
height={196}
sx={{ borderRadius: 1 }}
/>
))
: swapRoutes?.map((route, index) => (
<SwapRouteCard
key={route.id}
route={route}
active={currentRoute?.id === route.id}
onClick={() => handleRouteClick(route)}
/>
))}
{routeNotFound ? (
<SwapRouteNotFoundCard minWidth="100%" dense />
) : isLoading || isFetching ? (
Array.from({ length: 3 }).map((_, index) => (
<SwapRouteCardSkeleton key={index} minWidth="100%" dense />
))
) : (
swapRoutes?.map((route, index) => (
<SwapRouteCard
key={route.id}
route={route}
active={currentRoute?.id === route.id}
onClick={() => handleRouteClick(route)}
/>
))
)}
</Stack>
);
};

0 comments on commit 797db9c

Please sign in to comment.