Commit b472070b authored by Max Alekseenko's avatar Max Alekseenko

move rewards nav link to separate component

parent 201be844
......@@ -4,7 +4,6 @@ import React from 'react';
import type { NavItemInternal, NavItem, NavGroupItem } from 'types/client/navigation';
import config from 'configs/app';
import { useRewardsContext } from 'lib/contexts/rewards';
import { rightLineArrow } from 'lib/html-entities';
interface ReturnType {
......@@ -17,19 +16,12 @@ export function isGroupItem(item: NavItem | NavGroupItem): item is NavGroupItem
}
export function isInternalItem(item: NavItem): item is NavItemInternal {
return !('url' in item);
return 'nextRoute' in item;
}
export default function useNavItems(): ReturnType {
const router = useRouter();
const pathname = router.pathname;
const {
openLoginModal: openRewardsLoginModal,
balancesQuery: rewardsBalancesQuery,
dailyRewardQuery,
apiToken: rewardsApiToken,
isInitialized: isRewardsInitialized,
} = useRewardsContext();
return React.useMemo(() => {
let blockchainNavItems: Array<NavItem> | Array<Array<NavItem>> = [];
......@@ -286,14 +278,6 @@ export default function useNavItems(): ReturnType {
].filter(Boolean);
const accountNavItems: ReturnType['accountNavItems'] = [
config.features.rewards.isEnabled ? {
text: rewardsBalancesQuery.data?.total ? `${ rewardsBalancesQuery.data?.total } Merits` : 'Merits',
nextRoute: { pathname: '/account/rewards' as const },
onClick: (isRewardsInitialized && !rewardsApiToken) ? openRewardsLoginModal : undefined,
icon: dailyRewardQuery.data?.available ? 'merits_with_dot' : 'merits',
isActive: pathname === '/account/rewards',
isDisabled: !isRewardsInitialized,
} : null,
{
text: 'Watch list',
nextRoute: { pathname: '/account/watchlist' as const },
......@@ -327,5 +311,5 @@ export default function useNavItems(): ReturnType {
].filter(Boolean);
return { mainNavItems, accountNavItems };
}, [ pathname, openRewardsLoginModal, rewardsBalancesQuery, dailyRewardQuery, rewardsApiToken, isRewardsInitialized ]);
}, [ pathname ]);
}
......@@ -17,8 +17,6 @@ type NavItemCommon = {
export type NavItemInternal = NavItemCommon & {
nextRoute: Route;
isActive?: boolean;
onClick?: () => void;
isDisabled?: boolean;
}
export type NavItemExternal = {
......
import { Link, Text, HStack, Tooltip, Box, useBreakpointValue } from '@chakra-ui/react';
import NextLink from 'next/link';
import { useRouter } from 'next/router';
import React, { useCallback } from 'react';
import type { NavItem } from 'types/client/navigation';
import { route } from 'nextjs-routes';
import type { Route } from 'nextjs-routes';
import { useRewardsContext } from 'lib/contexts/rewards';
import useIsMobile from 'lib/hooks/useIsMobile';
import LightningLabel, { LIGHTNING_LABEL_CLASS_NAME } from 'ui/snippets/navigation/LightningLabel';
import NavLinkIcon from 'ui/snippets/navigation/NavLinkIcon';
import useColors from 'ui/snippets/navigation/useColors';
import useNavLinkStyleProps from 'ui/snippets/navigation/useNavLinkStyleProps';
import { checkRouteHighlight } from 'ui/snippets/navigation/utils';
type Props = {
isCollapsed?: boolean;
onClick?: () => void;
}
const RewardsNavLink = ({ isCollapsed, onClick }: Props) => {
const isMobile = useIsMobile();
const colors = useColors();
const router = useRouter();
const { openLoginModal, balancesQuery, dailyRewardQuery, apiToken, isInitialized } = useRewardsContext();
const pathname = '/account/rewards';
const nextRoute = { pathname } as Route;
const isActive = router.pathname === pathname;
const isExpanded = isCollapsed === false;
const styleProps = useNavLinkStyleProps({ isCollapsed, isExpanded, isActive });
const isXLScreen = useBreakpointValue({ base: false, xl: true });
const isHighlighted = checkRouteHighlight({ nextRoute } as NavItem);
const handleClick = useCallback(() => {
if (isInitialized && !apiToken) {
openLoginModal();
}
onClick?.();
}, [ onClick, isInitialized, apiToken, openLoginModal ]);
const content = (
<Link
href={ isInitialized && apiToken ? route(nextRoute) : undefined }
as={ isInitialized && apiToken ? 'a' : 'button' }
onClick={ handleClick }
{ ...styleProps.itemProps }
w={{ base: '100%', lg: isExpanded ? '100%' : '60px', xl: isCollapsed ? '60px' : '100%' }}
display="flex"
position="relative"
px={{ base: 2, lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 }}
aria-label="Merits link"
whiteSpace="nowrap"
_hover={{
[`& *:not(.${ LIGHTNING_LABEL_CLASS_NAME }, .${ LIGHTNING_LABEL_CLASS_NAME } *)`]: {
color: isInitialized ? 'link_hovered' : 'inherit',
},
}}
>
<Tooltip
label="Merits"
hasArrow={ false }
isDisabled={ isMobile || isCollapsed === false || (isCollapsed === undefined && isXLScreen) }
placement="right"
variant="nav"
gutter={ 20 }
color={ isActive ? colors.text.active : colors.text.hover }
margin={ 0 }
>
<HStack spacing={ 0 } overflow="hidden">
<NavLinkIcon item={{ icon: dailyRewardQuery.data?.available ? 'merits_with_dot' : 'merits' } as NavItem}/>
<Text { ...styleProps.textProps } as="span" ml={ 3 }>
<span>
{ balancesQuery.data?.total ? `${ balancesQuery.data?.total } Merits` : 'Merits' }
</span>
</Text>
{ isHighlighted && (
<LightningLabel iconColor={ styleProps.itemProps.bgColor } isCollapsed={ isCollapsed }/>
) }
</HStack>
</Tooltip>
</Link>
);
return (
<Box as="li" listStyleType="none" w="100%">
{ isInitialized && apiToken ? (
<NextLink href={ nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
) : content }
</Box>
);
};
export default React.memo(RewardsNavLink);
......@@ -3,6 +3,7 @@ import { animate, motion, useMotionValue } from 'framer-motion';
import React, { useCallback } from 'react';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import RewardsNavLink from 'ui/rewards/RewardsNavLink';
import IconSvg from 'ui/shared/IconSvg';
import useIsAuth from 'ui/snippets/auth/useIsAuth';
......@@ -82,6 +83,7 @@ const NavigationMobile = ({ onNavLinkClick, isMarketplaceAppPage }: Props) => {
borderColor="divider"
>
<VStack as="ul" spacing="1" alignItems="flex-start">
<RewardsNavLink onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>
{ accountNavItems.map((item) => <NavLink key={ item.text } item={ item } onClick={ onNavLinkClick } isCollapsed={ isCollapsed }/>) }
</VStack>
</Box>
......
......@@ -7,5 +7,5 @@ export function checkRouteHighlight(item: NavItem | Array<NavItem> | Array<Array
if (Array.isArray(item)) {
return item.some((subItem) => checkRouteHighlight(subItem));
}
return isInternalItem(item) && item.nextRoute !== undefined && (config.UI.navigation.highlightedRoutes.includes(item.nextRoute.pathname));
return isInternalItem(item) && (config.UI.navigation.highlightedRoutes.includes(item.nextRoute.pathname));
}
......@@ -34,19 +34,13 @@ const NavLink = ({ item, isCollapsed, px, className, onClick, disableActiveState
const styleProps = useNavLinkStyleProps({ isCollapsed, isExpanded, isActive: isInternalLink && item.isActive && !disableActiveState });
const isXLScreen = useBreakpointValue({ base: false, xl: true });
let href;
if (isInternalLink && !item.onClick) {
href = route(item.nextRoute);
} else if ('url' in item) {
href = item.url;
}
const href = isInternalLink ? route(item.nextRoute) : item.url;
const isHighlighted = checkRouteHighlight(item);
const isDisabled = isInternalLink && item.isDisabled;
const content = (
<Link
href={ isDisabled ? undefined : href }
href={ href }
target={ isInternalLink ? '_self' : '_blank' }
{ ...styleProps.itemProps }
w={{ base: '100%', lg: isExpanded ? '100%' : '60px', xl: isCollapsed ? '60px' : '100%' }}
......@@ -55,11 +49,10 @@ const NavLink = ({ item, isCollapsed, px, className, onClick, disableActiveState
px={ px || { base: 2, lg: isExpanded ? 2 : '15px', xl: isCollapsed ? '15px' : 2 } }
aria-label={ `${ item.text } link` }
whiteSpace="nowrap"
as={ isInternalLink && item.onClick ? 'button' : 'a' }
onClick={ isInternalLink && item.onClick ? item.onClick : onClick }
onClick={ onClick }
_hover={{
[`& *:not(.${ LIGHTNING_LABEL_CLASS_NAME }, .${ LIGHTNING_LABEL_CLASS_NAME } *)`]: {
color: isDisabled ? 'inherit' : 'link_hovered',
color: 'link_hovered',
},
}}
>
......@@ -89,7 +82,7 @@ const NavLink = ({ item, isCollapsed, px, className, onClick, disableActiveState
return (
<Box as="li" listStyleType="none" w="100%" className={ className }>
{ isInternalLink && !item.onClick && !isDisabled ? (
{ isInternalLink ? (
<NextLink href={ item.nextRoute } passHref legacyBehavior>
{ content }
</NextLink>
......
......@@ -6,6 +6,7 @@ import { useAppContext } from 'lib/contexts/app';
import * as cookies from 'lib/cookies';
import useNavItems, { isGroupItem } from 'lib/hooks/useNavItems';
import getDefaultTransitionProps from 'theme/utils/getDefaultTransitionProps';
import RewardsNavLink from 'ui/rewards/RewardsNavLink';
import IconSvg from 'ui/shared/IconSvg';
import useIsAuth from 'ui/snippets/auth/useIsAuth';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
......@@ -100,6 +101,7 @@ const NavigationDesktop = () => {
{ isAuth && (
<Box as="nav" borderTopWidth="1px" borderColor="divider" w="100%" mt={ 3 } pt={ 3 }>
<VStack as="ul" spacing="1" alignItems="flex-start">
<RewardsNavLink isCollapsed={ isCollapsed }/>
{ accountNavItems.map((item) => <NavLink key={ item.text } item={ item } isCollapsed={ isCollapsed }/>) }
</VStack>
</Box>
......
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