Skip to content

Commit

Permalink
Merge pull request #619 from Secured-Finance/SF-1213-Shorten-header-a…
Browse files Browse the repository at this point in the history
…dd-points-UI

fix: header fix wip [SF-1213]
  • Loading branch information
as1602 authored Jul 3, 2024
2 parents 8c49fc8 + 4f01327 commit ccd9fee
Show file tree
Hide file tree
Showing 24 changed files with 271 additions and 68 deletions.
4 changes: 2 additions & 2 deletions src/components/molecules/MenuPopover/MenuPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { LinkList } from 'src/utils';

export const MenuPopover = ({}) => {
return (
<div className='flex h-full items-center justify-center px-[30px]'>
<div className='flex h-full items-center justify-center px-[30px] laptop:w-[100px]'>
<Popover className='relative'>
{({}) => (
<>
<Popover.Button
as='button'
data-cy='popover-button'
className='typography-nav-menu-default mt-1 flex h-4 flex-row items-center gap-2.5 whitespace-nowrap text-neutral-8 opacity-70 outline-none duration-300 focus-within:text-secondary7 focus-within:opacity-100 hover:text-secondary7 hover:opacity-100 hover:ease-in-out'
className='typography-nav-menu-default flex h-4 flex-row items-center gap-1 whitespace-nowrap text-neutral-200 outline-none duration-300 focus-within:text-secondary7 focus-within:opacity-100 hover:text-secondary7 hover:opacity-100 hover:ease-in-out'
>
<p>More</p>
<ChevronDownIcon className='h-4 w-4' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const NetworkSelector = ({ networkName }: { networkName: string }) => {
data-cy='network-selector-button'
aria-label='Network Selector Button'
className={clsx(
'flex items-center gap-2 rounded-lg bg-neutral-800 p-2 ring-1 ring-neutral-500 focus:outline-none tablet:rounded-xl tablet:p-3 tablet:ring-[1.5px]',
'flex items-center gap-2 rounded-lg bg-neutral-800 p-2 ring-1 ring-neutral-500 focus:outline-none tablet:rounded-xl tablet:p-2.5 tablet:ring-[1.5px]',
{
'pr-2': !selectedNetwork,
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/molecules/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const Settings = ({ isProduction }: { isProduction: boolean }) => {
<Popover.Button
data-cy='settings-button'
aria-label='Settings Button'
className='flex items-center rounded-lg bg-neutral-800 p-[7px] ring-1 ring-neutral-500 focus:outline-none tablet:rounded-xl tablet:px-3.5 tablet:py-[13px] tablet:ring-[1.5px]'
className='flex items-center rounded-lg bg-neutral-800 p-[7px] ring-1 ring-neutral-500 focus:outline-none tablet:rounded-xl tablet:p-[11px] tablet:ring-[1.5px]'
>
<Gear className='h-18px w-18px' />
</Popover.Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryFn } from '@storybook/react';
import { ConnectWalletDialog } from './ConnectWalletDialog';

export default {
title: 'Organism/ConnectWalletDialog',
component: ConnectWalletDialog,
args: {
isOpen: true,
onClose: () => {},
},
} as Meta<typeof ConnectWalletDialog>;

const Template: StoryFn<typeof ConnectWalletDialog> = args => {
return <ConnectWalletDialog {...args} />;
};

export const Default = Template.bind({});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { composeStories } from '@storybook/react';
import { mockUseSF } from 'src/stories/mocks/useSFMock';
import { render, screen } from 'src/test-utils.js';
import * as stories from './ConnectWalletDialog.stories';

const { Default } = composeStories(stories);

const mockSecuredFinance = mockUseSF();
jest.mock('src/hooks/useSecuredFinance', () => () => mockSecuredFinance);

describe('DepositCollateral component', () => {
it('should display the Connect Wallet Dialog when open', () => {
render(<Default />);

expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(
screen.getByRole('heading', { name: 'Connect Wallet' })
).toBeInTheDocument();

const button = screen.getByTestId('dialog-action-button');
expect(button).toHaveTextContent('Connect');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Badge from 'src/assets/icons/badge.svg';
import { Dialog } from 'src/components/molecules';

export const ConnectWalletDialog = ({
isOpen,
onClose,
handleConnectWallet,
}: {
isOpen: boolean;
onClose: () => void;
handleConnectWallet: () => void;
}) => {
return (
<Dialog
title='Connect Wallet'
description='Get Points by placing limit orders and maintaining active positions on our app. But first, connect your wallet.'
callToAction='Connect Wallet'
onClick={handleConnectWallet}
isOpen={isOpen}
onClose={onClose}
showCancelButton
>
<div className='mx-auto flex h-[100px] w-[100px] items-center justify-center rounded-full border border-white/[19%] bg-white/[5%]'>
<Badge className='h-16 w-16' />
</div>
</Dialog>
);
};
1 change: 1 addition & 0 deletions src/components/organisms/ConnectWalletDialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ConnectWalletDialog';
13 changes: 12 additions & 1 deletion src/components/organisms/Header/Header.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { RESPONSIVE_PARAMETERS, VIEWPORTS } from '.storybook/constants';
import {
WithGraphClient,
withChainErrorEnabled,
withWalletProvider,
} from '.storybook/decorators';
import type { Meta, StoryFn } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { userPoints } from 'src/stories/mocks/queries';
import Header from './Header';

const FIGMA_STORYBOOK_LINK =
Expand All @@ -16,7 +18,7 @@ export default {
args: {
showNavigation: true,
},
decorators: [withWalletProvider],
decorators: [withWalletProvider, WithGraphClient],
parameters: {
...RESPONSIVE_PARAMETERS,
viewport: {
Expand All @@ -35,6 +37,15 @@ export const Primary = Template.bind({});
export const Connected = Template.bind({});
Connected.parameters = {
connected: true,
apolloClient: {
mocks: [...userPoints],
},
cookie: {
verified_data: {
token: '1234567890',
walletAddress: '0xB98bD7C7f656290071E52D1aA617D9cB4467Fd6D',
},
},
};

export const TradingMenuOpened = Template.bind({});
Expand Down
8 changes: 8 additions & 0 deletions src/components/organisms/Header/Header.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,12 @@ describe('Header component', () => {
expect(screen.queryByTestId('testnet-info')).not.toBeInTheDocument();
expect(screen.queryByTestId('testnet-alert')).not.toBeInTheDocument();
});

it('should not display SF Points if the user is not logged in', async () => {
render(<Primary />);

await waitFor(() => {
expect(screen.queryByText('164 Points')).not.toBeInTheDocument(); //
});
});
});
152 changes: 109 additions & 43 deletions src/components/organisms/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useGetUserLazyQuery } from '@secured-finance/sf-point-client';
import clsx from 'clsx';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useMemo, useState } from 'react';
import { useEffect, useState } from 'react';
import { useCookies } from 'react-cookie';
import { useDispatch, useSelector } from 'react-redux';
import Badge from 'src/assets/icons/badge.svg';
import SFLogo from 'src/assets/img/logo.svg';
import SFLogoSmall from 'src/assets/img/small-logo.svg';
import {
Expand All @@ -17,16 +21,11 @@ import {
Settings,
} from 'src/components/molecules';
import {
DepositCollateral,
ConnectWalletDialog,
WalletDialog,
WalletPopover,
generateCollateralList,
} from 'src/components/organisms';
import {
useBreakpoint,
useCollateralBalances,
useCollateralCurrencies,
} from 'src/hooks';
import { useBreakpoint } from 'src/hooks';
import useSF from 'src/hooks/useSecuredFinance';
import { setWalletDialogOpen } from 'src/store/interactions';
import { RootState } from 'src/store/types';
Expand All @@ -37,6 +36,9 @@ import { useAccount } from 'wagmi';
import { TradingDropdown } from './TradingDropdown';
import { DEV_LINKS, PRODUCTION_LINKS } from './constants';

const POLL_INTERVAL = 600000; // 10 minutes
const POINT_API_QUERY_OPTIONS = { context: { type: 'point-dashboard' } };

const HeaderMessage = ({
chainId,
chainError,
Expand Down Expand Up @@ -74,12 +76,36 @@ const HeaderMessage = ({
};

const Header = ({ showNavigation }: { showNavigation: boolean }) => {
const [isConnectWalletDialogOpen, setIsConnectWalletDialogOpen] =
useState<boolean>(false);
const dispatch = useDispatch();
const isMobile = useBreakpoint('tablet');
const [isOpenDepositModal, setIsOpenDepositModal] =
useState<boolean>(false);

const { address, isConnected } = useAccount();

const [cookies] = useCookies();

const [getUser, { data: userData, refetch }] = useGetUserLazyQuery({
pollInterval: POLL_INTERVAL,
...POINT_API_QUERY_OPTIONS,
});

useEffect(() => {
if (cookies.verified_data) {
userData?.user.walletAddress &&
userData?.user.walletAddress !== address
? refetch()
: getUser();
}
}, [
cookies.verified_data,
getUser,
address,
userData?.user.walletAddress,
refetch,
]);

const userPoints = userData?.user.point;

const securedFinance = useSF();
const chainError = useSelector(
(state: RootState) => state.blockchain.chainError
Expand All @@ -91,21 +117,7 @@ const Header = ({ showNavigation }: { showNavigation: boolean }) => {

const LINKS = isProduction ? PRODUCTION_LINKS : DEV_LINKS;

const collateralBalances = useCollateralBalances();

const { data: collateralCurrencies = [] } = useCollateralCurrencies();

const depositCollateralList = useMemo(
() =>
generateCollateralList(
collateralBalances,
false,
collateralCurrencies
),
[collateralBalances, collateralCurrencies]
);

const btnSize = isMobile ? ButtonSizes.sm : ButtonSizes.lg;
const btnSize = isMobile ? ButtonSizes.sm : undefined;

return (
<>
Expand All @@ -116,11 +128,11 @@ const Header = ({ showNavigation }: { showNavigation: boolean }) => {
/>
<nav
data-cy='header'
className='grid h-14 w-full grid-flow-col bg-neutral-800 px-4 tablet:h-[72px] tablet:px-5 laptop:h-20 laptop:grid-flow-col'
className='grid h-14 w-full grid-flow-col bg-neutral-800 px-4 tablet:h-16 tablet:px-5 laptop:grid-flow-col'
>
<div className='col-span-2 flex flex-row items-center gap-8 desktop:gap-12'>
<Link href='/'>
<SFLogo className='hidden desktop:inline desktop:h-5 desktop:w-[200px]' />
<div className='col-span-2 flex flex-row items-center gap-6 largeDesktop:gap-8'>
<Link href='/' className='flex'>
<SFLogo className='hidden desktop:inline desktop:h-4 desktop:w-[160px] largeDesktop:h-5 largeDesktop:w-[200px]' />
<SFLogoSmall className='inline h-7 w-7 desktop:hidden' />
</Link>
{showNavigation && (
Expand All @@ -143,14 +155,15 @@ const Header = ({ showNavigation }: { showNavigation: boolean }) => {
)}
</div>
<div className='col-span-2 flex flex-row items-center justify-end gap-2 laptop:col-span-1 laptop:gap-2.5'>
<PointsTag
isConnected={isConnected}
points={userPoints}
handleOpenConnectWalletDialog={() =>
setIsConnectWalletDialogOpen(true)
}
/>
{isConnected && address ? (
<>
<Button
size={btnSize}
onClick={() => setIsOpenDepositModal(true)}
>
Deposit
</Button>
<NetworkSelector
networkName={
securedFinance?.config?.network ??
Expand Down Expand Up @@ -192,14 +205,16 @@ const Header = ({ showNavigation }: { showNavigation: boolean }) => {
</div>
</div>
<WalletDialog />
<ConnectWalletDialog
isOpen={isConnectWalletDialogOpen}
onClose={() => setIsConnectWalletDialogOpen(false)}
handleConnectWallet={() => {
setIsConnectWalletDialogOpen(false);
dispatch(setWalletDialogOpen(true));
}}
/>
</nav>
</div>
<DepositCollateral
isOpen={isOpenDepositModal}
onClose={() => setIsOpenDepositModal(false)}
collateralList={depositCollateralList}
source={'Header'}
/>
</>
);
};
Expand Down Expand Up @@ -228,10 +243,61 @@ const ItemLink = ({
text={text}
active={useCheckActive()}
isFullHeight
className='laptop:px-[1.875rem]'
className='laptop:w-[100px]'
/>
</Link>
);
};

const PointsTag = ({
points,
isConnected,
handleOpenConnectWalletDialog,
}: {
points?: number;
isConnected: boolean;
handleOpenConnectWalletDialog: () => void;
}) => {
const router = useRouter();
const showPoints = isConnected && points;

let pointsDisplay = '';

if (points) {
if (points < 1000) {
pointsDisplay = `${points} Points`;
} else if (points < 1000000) {
pointsDisplay = `${Math.floor(points / 100) / 10}K Points`;
} else {
pointsDisplay = `${Math.floor(points / 100000) / 10}M Points`;
}
}

const handleOnClick = () => {
if (isConnected) {
router.pathname !== '/points' && router.push('/points');
return;
}

handleOpenConnectWalletDialog();
};

return (
<button
onClick={() => handleOnClick()}
className={clsx(
'typography-mobile-body-5 tablet:typography-desktop-body-4 flex h-8 flex-shrink-0 items-center justify-center gap-1 rounded-lg bg-tertiary-700/30 px-2.5 py-[5px] font-semibold text-neutral-50 ring-1 ring-tertiary-500 hover:bg-tertiary-700 active:border-transparent tablet:h-10 tablet:rounded-xl tablet:ring-[1.5px]',
{
'w-8 tablet:w-10 tablet:pr-2.5': !showPoints,
'tablet:pr-3': showPoints,
}
)}
aria-label='Points Tag'
>
<Badge className='flex h-[13px] w-[13px] flex-shrink-0 tablet:h-4 tablet:w-4' />
{isConnected && points !== undefined && <>{pointsDisplay}</>}
</button>
);
};

export default Header;
Loading

0 comments on commit ccd9fee

Please sign in to comment.