Commit 3d0f21f8 authored by tom's avatar tom

navigation refactoring

parent 90d38a52
......@@ -11,30 +11,32 @@ import publicTagIcon from 'icons/publictags.svg';
import tokensIcon from 'icons/token.svg';
import transactionsIcon from 'icons/transactions.svg';
import watchlistIcon from 'icons/watchlist.svg';
import useBasePath from 'lib/hooks/useBasePath';
import useCurrentRoute from 'lib/link/useCurrentRoute';
import useLink from 'lib/link/useLink';
export default function useNavItems() {
const basePath = useBasePath();
const link = useLink();
const currentRoute = useCurrentRoute()();
return React.useMemo(() => {
const mainNavItems = [
{ text: 'Blocks', pathname: basePath + '/blocks', icon: blocksIcon },
{ text: 'Transactions', pathname: basePath + '/tx', icon: transactionsIcon },
{ text: 'Tokens', pathname: basePath + '/tokens', icon: tokensIcon },
{ text: 'Apps', pathname: basePath + '/apps', icon: appsIcon },
{ text: 'Other', pathname: basePath + '/other', icon: gearIcon },
{ text: 'Blocks', url: link('blocks'), icon: blocksIcon, isActive: [ 'block', 'blocks' ].includes(currentRoute) },
{ text: 'Transactions', url: link('txs'), icon: transactionsIcon, isActive: [ 'tx', 'txs' ].includes(currentRoute) },
{ text: 'Tokens', url: link('tokens'), icon: tokensIcon, isActive: [ 'token', 'tokens' ].includes(currentRoute) },
{ text: 'Apps', url: link('apps'), icon: appsIcon, isActive: currentRoute === 'apps' },
{ text: 'Other', url: link('other'), icon: gearIcon, isActive: currentRoute === 'other' },
];
const accountNavItems = [
{ text: 'Watchlist', pathname: basePath + '/account/watchlist', icon: watchlistIcon },
{ text: 'Private tags', pathname: basePath + '/account/tag_address', icon: privateTagIcon },
{ text: 'Public tags', pathname: basePath + '/account/public_tags_request', icon: publicTagIcon },
{ text: 'API keys', pathname: basePath + '/account/api_key', icon: apiKeysIcon },
{ text: 'Custom ABI', pathname: basePath + '/account/custom_abi', icon: abiIcon },
{ text: 'Watchlist', url: link('watchlist'), icon: watchlistIcon, isActive: currentRoute === 'watchlist' },
{ text: 'Private tags', url: link('private_tags', { tab: 'address' }), icon: privateTagIcon, isActive: currentRoute === 'private_tags' },
{ text: 'Public tags', url: link('public_tags'), icon: publicTagIcon, isActive: currentRoute === 'public_tags' },
{ text: 'API keys', url: link('api_keys'), icon: apiKeysIcon, isActive: currentRoute === 'api_keys' },
{ text: 'Custom ABI', url: link('custom_abi'), icon: abiIcon, isActive: currentRoute === 'custom_abi' },
];
const profileItem = { text: 'My profile', pathname: basePath + '/auth/profile', icon: profileIcon };
const profileItem = { text: 'My profile', url: link('profile'), icon: profileIcon, isActive: currentRoute === 'profile' };
return { mainNavItems, accountNavItems, profileItem };
}, [ basePath ]);
}, [ link, currentRoute ]);
}
......@@ -10,6 +10,7 @@ export function link(routeName: RouteName, urlParams?: Record<string, string | u
}
const toPath = compile(route.pattern, { encode: encodeURIComponent, validate: false });
const path = toPath(urlParams);
const url = new URL(path, window.location.origin);
......
......@@ -3,9 +3,45 @@ export interface Route {
}
export type RouteName = keyof typeof ROUTES;
const BASE_PATH = '/:network_type/:network_sub_type';
export const ROUTES = {
tx: {
pattern: '/:network_type/:network_sub_type/tx/:id/:tab?',
pattern: `${ BASE_PATH }/tx/:id/:tab?`,
},
txs: {
pattern: `${ BASE_PATH }/txs`,
},
blocks: {
pattern: `${ BASE_PATH }/blocks`,
},
tokens: {
pattern: `${ BASE_PATH }/tokens`,
},
apps: {
pattern: `${ BASE_PATH }/apps`,
},
// ??? what URL will be here
other: {
pattern: `${ BASE_PATH }/other`,
},
watchlist: {
pattern: `${ BASE_PATH }/account/watchlist`,
},
private_tags: {
pattern: `${ BASE_PATH }/account/tag_{:tab}`,
},
public_tags: {
pattern: `${ BASE_PATH }/account/public_tags_request`,
},
api_keys: {
pattern: `${ BASE_PATH }/account/api_key`,
},
custom_abi: {
pattern: `${ BASE_PATH }/account/custom_abi`,
},
profile: {
pattern: `${ BASE_PATH }/auth/profile`,
},
};
......
import { useRouter } from 'next/router';
import { match } from 'path-to-regexp';
import React from 'react';
import type { RouteName } from 'lib/link/routes';
import { ROUTES } from 'lib/link/routes';
export default function useCurrentRoute() {
const { asPath } = useRouter();
return React.useCallback(() => {
for (const routeName in ROUTES) {
const route = ROUTES[routeName as RouteName];
const isMatch = Boolean(match(route.pattern)(asPath));
if (isMatch) {
return routeName as RouteName;
}
}
return '';
}, [ asPath ]);
}
......@@ -10,13 +10,13 @@ import useColors from './useColors';
interface Props {
isCollapsed?: boolean;
isActive?: boolean;
pathname: string;
url: string;
text: string;
icon: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
px?: string | number;
}
const NavLink = ({ text, pathname, icon, isCollapsed, isActive, px }: Props) => {
const NavLink = ({ text, url, icon, isCollapsed, isActive, px }: Props) => {
const colors = useColors();
const isMobile = useIsMobile();
const width = (() => {
......@@ -28,7 +28,7 @@ const NavLink = ({ text, pathname, icon, isCollapsed, isActive, px }: Props) =>
})();
return (
<NextLink href={ pathname } passHref>
<NextLink href={ url } passHref>
<Link
as="li"
listStyleType="none"
......
import { ChevronLeftIcon } from '@chakra-ui/icons';
import { Flex, Box, VStack, useColorModeValue, useBreakpointValue } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import * as cookies from 'lib/cookies';
......@@ -13,8 +12,6 @@ import NavFooter from './NavFooter';
import NavLink from './NavLink';
const NavigationDesktop = () => {
const router = useRouter();
const { mainNavItems, accountNavItems } = useNavItems();
const isLargeScreen = useBreakpointValue({ base: false, xl: true });
const cookieValue = cookies.get(cookies.NAMES.NAV_BAR_COLLAPSED);
......@@ -66,14 +63,12 @@ const NavigationDesktop = () => {
</Box>
<Box as="nav" mt={ 14 }>
<VStack as="ul" spacing="2" alignItems="flex-start" overflow="hidden">
{ mainNavItems.map((item) =>
<NavLink key={ item.text } { ...item } isCollapsed={ isCollapsed } isActive={ router.asPath.startsWith(item.pathname) }/>) }
{ mainNavItems.map((item) => <NavLink key={ item.text } { ...item } isCollapsed={ isCollapsed }/>) }
</VStack>
</Box>
<Box as="nav" mt={ 12 }>
<VStack as="ul" spacing="2" alignItems="flex-start" overflow="hidden">
{ accountNavItems.map((item) =>
<NavLink key={ item.text } { ...item } isCollapsed={ isCollapsed } isActive={ router.asPath.startsWith(item.pathname) }/>) }
{ accountNavItems.map((item) => <NavLink key={ item.text } { ...item } isCollapsed={ isCollapsed }/>) }
</VStack>
</Box>
<NavFooter isCollapsed={ isCollapsed }/>
......
import { Box, VStack } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import useNavItems from 'lib/hooks/useNavItems';
......@@ -8,18 +7,17 @@ import NavLink from 'ui/blocks/navigation/NavLink';
const NavigationMobile = () => {
const { mainNavItems, accountNavItems } = useNavItems();
const router = useRouter();
return (
<>
<Box as="nav" mt={ 6 }>
<VStack as="ul" spacing="2" alignItems="flex-start" overflow="hidden">
{ mainNavItems.map((item) => <NavLink key={ item.text } { ...item } isActive={ router.asPath.startsWith(item.pathname) }/>) }
{ mainNavItems.map((item) => <NavLink key={ item.text } { ...item }/>) }
</VStack>
</Box>
<Box as="nav" mt={ 6 }>
<VStack as="ul" spacing="2" alignItems="flex-start" overflow="hidden">
{ accountNavItems.map((item) => <NavLink key={ item.text } { ...item } isActive={ router.asPath.startsWith(item.pathname) }/>) }
{ accountNavItems.map((item) => <NavLink key={ item.text } { ...item }/>) }
</VStack>
</Box>
<NavFooter/>
......
......@@ -33,10 +33,10 @@ const ProfileMenuContent = ({ name, nickname, email }: Props) => {
>
{ email }
</Text>
<NavLink { ...profileItem } px="0px"/>
<NavLink { ...profileItem } isActive={ undefined } px="0px"/>
<Box as="nav" mt={ 2 } pt={ 2 } borderTopColor={ borderColor } borderTopWidth="1px" { ...getDefaultTransitionProps() }>
<VStack as="ul" spacing="0" alignItems="flex-start" overflow="hidden">
{ accountNavItems.map((item) => <NavLink key={ item.text } { ...item } px="0px"/>) }
{ accountNavItems.map((item) => <NavLink key={ item.text } { ...item } isActive={ undefined } px="0px"/>) }
</VStack>
</Box>
<Box mt={ 2 } pt={ 3 } borderTopColor={ borderColor } borderTopWidth="1px" { ...getDefaultTransitionProps() }>
......
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