Skip to content

Commit

Permalink
[DTRA] henry/dtra-1237/fix: dtrader-v2 setup (#14991)
Browse files Browse the repository at this point in the history
* fix: initial setup

* fix: partially finished setup

* fix: ensure new header only appears for mobile

* fix: quill-ui version bump

* fix: change classnames

* fix: change to kebab case file names

* fix: resolve comments

* fix: add color to text

* fix: add tests

* fix: sonarcloud

* fix: sonarcloud issues

* fix: parse JSON with try catch in case FeatureFlagsStore returns empty

* fix: change to quill icons

* fix: add missing css

* fix: change hamburger menu icon to standalone

* fix: move quill-ui to core and wrap application with themeprovider

* fix: import themeprovider from quill/ui

* fix: wrong import

* fix: remove unused css and make header bold

* fix: make labels red when active

* fix: change text to correct component

* fix: move themeprovider to appcontent to react to changes in store

* chore: reset package lock

* fix: update package-lock and add quill-ui to traders package

* fix: jest config error

* fix: ignore errors from quill-ui

* fix: jest config and add babel config

* fix: remove a plugin

* fix: lets try this

* fix: remove irrelevant files

* fix: test

* fix: change

* fix: asdf

* fix: errors

* fix: give contract details page a new header
  • Loading branch information
henry-deriv authored May 17, 2024
1 parent 81c9be6 commit 8a70548
Show file tree
Hide file tree
Showing 33 changed files with 544 additions and 14 deletions.
36 changes: 31 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"@babel/polyfill": "^7.4.4",
"@datadog/browser-rum": "^5.11.0",
"@deriv-com/analytics": "1.4.13",
"@deriv-com/quill-ui": "^1.9.17",
"@deriv-com/utils": "^0.0.20",
"@deriv/account": "^1.0.0",
"@deriv/account-v2": "^1.0.0",
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/App/AppContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import AppModals from './Containers/Modals';
import Routes from './Containers/Routes/routes.jsx';
import Devtools from './Devtools';
import initDatadog from '../Utils/Datadog';
import { ThemeProvider } from '@deriv-com/quill-ui';

const AppContent: React.FC<{ passthrough: unknown }> = observer(({ passthrough }) => {
const store = useStore();
Expand Down Expand Up @@ -89,7 +90,7 @@ const AppContent: React.FC<{ passthrough: unknown }> = observer(({ passthrough }
}, [has_wallet, store.common, store.ui]);

return (
<>
<ThemeProvider theme={store.ui.is_dark_mode_on ? 'dark' : 'light'}>
<Header />
<ErrorBoundary root_store={store}>
<AppContents>
Expand All @@ -107,7 +108,7 @@ const AppContent: React.FC<{ passthrough: unknown }> = observer(({ passthrough }
<BinaryBotIFrame />
<AppToastMessages />
<Devtools />
</>
</ThemeProvider>
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Header from '../header';
jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useStoreWalletAccountsList: jest.fn(() => ({ data: [], has_wallet: false })),
useFeatureFlags: jest.fn(() => ({})),
}));
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { observer, useStore } from '@deriv/stores';
import { getCurrencyDisplayCode } from '@deriv/shared';
import AccountInfoIcon from 'App/Components/Layout/Header/account-info-icon';
import { CaptionText } from '@deriv-com/quill-ui';

const DTraderV2Header = observer(() => {
const { client } = useStore();
const { balance, currency, is_virtual, loginid } = client;

const currency_lower = currency?.toLowerCase();

return (
<header className='header header-v2'>
<React.Suspense fallback={<div />}>
<div className='header-v2__acc-info'>
<div className='header-v2__acc-info--top'>
<span className='header-v2__acc-info--logo'>
{(is_virtual || currency) && (
<AccountInfoIcon is_virtual={is_virtual} currency={currency_lower} />
)}
</span>
<CaptionText size='sm'>{loginid}</CaptionText>
</div>
<div className='header-v2__acc-info--bottom'>
<CaptionText size='sm' bold>{`${balance} ${getCurrencyDisplayCode(currency)}`}</CaptionText>
</div>
</div>
</React.Suspense>
</header>
);
});

export default DTraderV2Header;
31 changes: 25 additions & 6 deletions packages/core/src/App/Containers/Layout/header/header.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react';
import { useLocation } from 'react-router-dom';
import { useFeatureFlags } from '@deriv/hooks';
import { useReadLocalStorage } from 'usehooks-ts';
import { makeLazyLoader, moduleLoader, routes } from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
import { useDevice } from '@deriv/components';

const HeaderFallback = () => <div className='header' />;

Expand Down Expand Up @@ -37,10 +39,16 @@ const TradersHubHeaderWallets = makeLazyLoader(
() => <HeaderFallback />
)();

const DTraderV2Header = makeLazyLoader(
() => moduleLoader(() => import(/* webpackChunkName: "dtrader-v2-header" */ './dtrader-v2-header')),
() => <HeaderFallback />
)();

const Header = observer(() => {
const { client } = useStore();
const { accounts, has_wallet, is_logged_in, setAccounts, loginid, switchAccount } = client;
const { pathname } = useLocation();
const { is_mobile } = useDevice();

const is_wallets_cashier_route = pathname.includes(routes.wallets_cashier);

Expand All @@ -59,6 +67,7 @@ const Header = observer(() => {
is_wallets_cashier_route;

const client_accounts = useReadLocalStorage('client.accounts');
const { is_dtrader_v2_enabled } = useFeatureFlags();

React.useEffect(() => {
if (has_wallet && is_logged_in) {
Expand All @@ -74,12 +83,22 @@ const Header = observer(() => {

if (is_logged_in) {
let result;
if (traders_hub_routes) {
result = has_wallet ? <TradersHubHeaderWallets /> : <TradersHubHeader />;
} else if (pathname === routes.onboarding) {
result = null;
} else {
result = has_wallet ? <DTraderHeaderWallets /> : <DTraderHeader />;
switch (true) {
case pathname === routes.onboarding:
result = null;
break;
case is_dtrader_v2_enabled &&
is_mobile &&
(pathname === routes.trade ||
pathname.startsWith('/contract/') === routes.contract.startsWith('/contract/')):
result = <DTraderV2Header />;
break;
case traders_hub_routes:
result = has_wallet ? <TradersHubHeaderWallets /> : <TradersHubHeader />;
break;
default:
result = has_wallet ? <DTraderHeaderWallets /> : <DTraderHeader />;
break;
}
return result;
} else if (pathname === routes.onboarding) {
Expand Down
36 changes: 36 additions & 0 deletions packages/core/src/sass/app/_common/layout/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,39 @@
}
}
}

.header-v2 {
display: flex;
justify-content: center;

&__acc-info {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;

&--top {
display: flex;
align-items: center;
justify-content: center;
gap: var(--semantic-spacing-gap-sm);
}

&--logo {
height: var(--core-size-800);
width: var(--core-size-800);

svg {
width: var(--core-size-800);
height: var(--core-size-800);
}
}

&--bottom {
display: flex;
align-items: center;
justify-content: center;
gap: var(--semantic-spacing-gap-sm);
}
}
}
1 change: 1 addition & 0 deletions packages/trader/build/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const {
const ALIASES = {
_common: path.resolve(__dirname, '../src/_common'),
App: path.resolve(__dirname, '../src/App'),
AppV2: path.resolve(__dirname, '../src/AppV2'),
Assets: path.resolve(__dirname, '../src/Assets'),
Constants: path.resolve(__dirname, '../src/Constants'),
Fonts: path.resolve(__dirname, '../src/public/fonts'),
Expand Down
3 changes: 3 additions & 0 deletions packages/trader/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ module.exports = {
...baseConfigForPackages,
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'\\.css$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/styleMock.js',
'^_common/(.*)$': '<rootDir>/src/_common/$1',
'^App/(.*)$': '<rootDir>/src/App/$1',
'^AppV2/(.*)$': '<rootDir>/src/AppV2/$1',
'^Assets/(.*)$': '<rootDir>/src/Assets/$1',
'^Constants/(.*)$': '<rootDir>/src/Constants/$1',
'^Constants$': '<rootDir>/src/Constants/index.js',
Expand All @@ -16,4 +18,5 @@ module.exports = {
'^Services/(.*)$': '<rootDir>/src/Services/$1',
'^Stores/(.*)$': '<rootDir>/src/Stores/$1',
},
transformIgnorePatterns: ['/node_modules/(?!(@deriv-com/quill-ui|@simplewebauthn/browser)).+\\.js$'],
};
2 changes: 2 additions & 0 deletions packages/trader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"dependencies": {
"@cloudflare/stream-react": "^1.9.1",
"@deriv-com/analytics": "1.4.13",
"@deriv-com/quill-ui": "^1.9.17",
"@deriv-com/utils": "^0.0.20",
"@deriv/api-types": "^1.0.172",
"@deriv/components": "^1.0.0",
Expand All @@ -99,6 +100,7 @@
"@deriv/shared": "^1.0.0",
"@deriv/stores": "^1.0.0",
"@deriv/translations": "^1.0.0",
"@deriv/quill-icons": "^1.22.4",
"@types/react-loadable": "^5.5.6",
"classnames": "^2.2.6",
"extend": "^3.0.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import BottomNavItem from '../bottom-nav-item';
import userEvent from '@testing-library/user-event';

jest.mock('@deriv-com/quill-ui', () => ({
Text: jest.fn(() => {
return 'MockedText';
}),
}));

describe('BottomNavItem', () => {
const mockProps = {
icon: <div>Icon</div>,
selectedIndex: 0,
label: 'Label',
setSelectedIndex: jest.fn(),
index: 0,
};

it('should render icon and label', () => {
render(<BottomNavItem {...mockProps} />);
expect(screen.getByText('Icon')).toBeInTheDocument();
expect(screen.getByText('MockedText')).toBeInTheDocument();
});
it('should have bottom-nav-item--active class when active', () => {
render(<BottomNavItem {...mockProps} />);
expect(screen.getByText('MockedText')).toHaveClass('bottom-nav-item--active');
});
it('should have not bottomNav-item--active class when not active', () => {
render(<BottomNavItem {...mockProps} selectedIndex={1} />);
expect(screen.getByText('MockedText')).not.toHaveClass('bottom-nav-item--active');
});
it('should call setSelectedIndex with index when clicked', () => {
render(<BottomNavItem {...mockProps} />);
userEvent.click(screen.getByText('MockedText'));
expect(mockProps.setSelectedIndex).toHaveBeenCalledWith(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import BottomNav from '../bottom-nav';
import userEvent from '@testing-library/user-event';

jest.mock('../bottom-nav-item', () => {
return jest.fn(({ index, setSelectedIndex }) => (
<button onClick={() => setSelectedIndex(index)}>MockedBottomNavItem</button>
));
});

jest.mock('@deriv-com/quill-ui', () => ({
Badge: jest.fn(() => {
return 'MockedBadge';
}),
}));
describe('BottomNav', () => {
const mockedTradeContainer = <div>MockedTrade</div>;
const mockedMarketsContainer = <div>MockedMarkets</div>;
const mockedPositionsContainer = <div>MockedPositions</div>;
const renderedBottomNav = (
<BottomNav>
<div>{mockedTradeContainer}</div>
<div>{mockedMarketsContainer}</div>
<div>{mockedPositionsContainer}</div>
</BottomNav>
);
it('should render correctly', () => {
const { container } = render(renderedBottomNav);
expect(container).toBeInTheDocument();
});
it('should render the correct number of BottomNavItem components', () => {
render(renderedBottomNav);
expect(screen.getAllByText(/MockedBottomNavItem/i)).toHaveLength(4);
});
it('should render MockedTrade by default since selected index is 0', () => {
render(renderedBottomNav);
expect(screen.getByText('MockedTrade')).toBeInTheDocument();
});
it('should render MockedPositions if 3rd MockedBottomNavItem is selected', () => {
render(renderedBottomNav);
userEvent.click(screen.getAllByText('MockedBottomNavItem')[2]);
expect(screen.getByText('MockedPositions')).toBeInTheDocument();
});
});
Loading

0 comments on commit 8a70548

Please sign in to comment.