Skip to content

Commit

Permalink
[TRAH5082] Suisin/trah5082/change traders hub button url based on ff (#…
Browse files Browse the repository at this point in the history
…17916)

* chore: open new tab for options and cfds in hub when user has wallets account

* chore: only to add it in wallets account switcher

* chore: fix build fail

* chore: revert TContractInfo auto convert

* chore: change to have redirection logic on tradershub page itself

* chore: change taxResidence to citizen

* chore: update redirection logic and add hooks for checking hub redirection

* chore: revert auto correct TContractInfo

* chore: revert AppContent and account-switcher-wallet logic

* chore: if modal is open in tradershub we dont redirect user to low-code

* chore: fix failing testcase and revert TContractInfo

* chore: display blank screen in wallets for hub enabled countries

* chore: fix build failing issue

* chore: fix code based on comments

* chore: update to use process.env.NODE_ENV based on comment

* chore: update logic redirection to check either trading_hub or GB value is true

* chore: fix redirection to staging-hub when clicking on cfds button

* chore: fix redirection before clicking on Get started
  • Loading branch information
suisin-deriv authored Jan 10, 2025
1 parent 51811f7 commit 8664cb5
Show file tree
Hide file tree
Showing 39 changed files with 421 additions and 72 deletions.
2 changes: 2 additions & 0 deletions packages/api-v2/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ export { default as useDynamicLeverage } from './useDynamicLeverage';
export { default as useExchangeRateSubscription } from './useExchangeRateSubscription';
export { default as useGetAccountStatus } from './useGetAccountStatus';
export { default as useGetExchangeRate } from './useGetExchangeRate';
export { default as useGrowthbookGetFeatureValue } from './useGrowthbookGetFeatureValue';
export { default as useGrowthbookIsOn } from './useGrowthbookIsOn';
export { default as useIdentityDocumentVerificationAdd } from './useIdentityDocumentVerificationAdd';
export { default as useIsEuRegion } from './useIsEuRegion';
export { default as useIsHubRedirectionEnabled } from './useIsHubRedirectionEnabled';
export { default as useJurisdictionStatus } from './useJurisdictionStatus';
export { default as useLandingCompany } from './useLandingCompany';
export { default as useMT5AccountsList } from './useMT5AccountsList';
Expand Down
41 changes: 41 additions & 0 deletions packages/api-v2/src/hooks/useGrowthbookGetFeatureValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useEffect, useState } from 'react';
import { useIsMounted } from 'usehooks-ts';

import { getFeatureFlag } from '@deriv/utils';
import { Analytics } from '@deriv-com/analytics';

interface UseGrowthbookGetFeatureValueArgs<T> {
featureFlag: string;
defaultValue?: T;
}

const useGrowthbookGetFeatureValue = <T extends string | boolean>({
featureFlag,
defaultValue,
}: UseGrowthbookGetFeatureValueArgs<T>) => {
const resolvedDefaultValue: T = defaultValue !== undefined ? defaultValue : (false as T);
const [featureFlagValue, setFeatureFlagValue] = useState<boolean>(false);
const [isGBLoaded, setIsGBLoaded] = useState(false);
const isMounted = useIsMounted();

// Required for debugging Growthbook, this will be removed after this is added in the Analytics directly.
if (typeof window !== 'undefined') {
window.Analytics = Analytics;
}

useEffect(() => {
const fetchFeatureFlag = async () => {
const is_enabled = await getFeatureFlag(featureFlag, resolvedDefaultValue);
if (isMounted()) {
setFeatureFlagValue(is_enabled);
setIsGBLoaded(true);
}
};

fetchFeatureFlag();
}, [featureFlag, resolvedDefaultValue, isMounted]);

return [featureFlagValue, isGBLoaded];
};

export default useGrowthbookGetFeatureValue;
34 changes: 34 additions & 0 deletions packages/api-v2/src/hooks/useIsHubRedirectionEnabled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import useClientCountry from './useClientCountry';
import useGrowthbookGetFeatureValue from './useGrowthbookGetFeatureValue';
import useSettings from './useSettings';

type THubEnabledCountryList = {
hub_enabled_country_list: string[];
};

const useIsHubRedirectionEnabled = () => {
const [hubEnabledCountryList] = useGrowthbookGetFeatureValue({
featureFlag: 'hub_enabled_country_list',
});
const { data: clientCountry } = useClientCountry();
const { data: accountSettings } = useSettings();
const { citizen } = accountSettings;

const isHubRedirectionEnabled =
typeof hubEnabledCountryList === 'object' &&
hubEnabledCountryList !== null &&
Array.isArray((hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list) &&
citizen &&
(hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list.includes(citizen);

const isChangingToHubAppId =
typeof hubEnabledCountryList === 'object' &&
hubEnabledCountryList !== null &&
Array.isArray((hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list) &&
clientCountry &&
(hubEnabledCountryList as THubEnabledCountryList).hub_enabled_country_list.includes(clientCountry);

return { isHubRedirectionEnabled, isChangingToHubAppId };
};

export default useIsHubRedirectionEnabled;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ type TMockPlatformDropdown = {
}[];
};

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useIsHubRedirectionEnabled: () => ({
isHubRedirectionEnabled: false,
}),
}));

const history = createBrowserHistory();
const store = mockStore({});

Expand Down Expand Up @@ -81,19 +88,19 @@ describe('PlatformDropdown component', () => {
expect(screen.getByTestId('dt_platform_dropdown_link')).toBeInTheDocument();
expect(screen.getByText(tradershub_redirect)).toBeInTheDocument();
});
it('should update URL when clicking on another (non-selected) platform', () => {
it('should update URL when clicking on another (non-selected) platform', async () => {
history.push(routes.bot);
render(<MockPlatformDropdown platform_config={[dtrader_platform_config]} />);

userEvent.click(screen.getByText(dtrader_description));
await userEvent.click(screen.getByText(dtrader_description));
expect(history.location.pathname).toBe(routes.trade);
expect(history.location.search).toBe('');
});
it('should not update URL when clicking on an already selected platform', () => {
it('should not update URL when clicking on an already selected platform', async () => {
history.push(routes.trade + dtrader_url_params);
render(<MockPlatformDropdown platform_config={[dtrader_platform_config]} />);

userEvent.click(screen.getByText(dtrader_description));
await userEvent.click(screen.getByText(dtrader_description));
expect(history.location.pathname).toBe(routes.trade);
expect(history.location.search).toBe(dtrader_url_params);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { Div100vhContainer, Icon, useOnClickOutside, Text } from '@deriv/components';
import { routes, getActivePlatform } from '@deriv/shared';
import { routes, getActivePlatform, platforms } from '@deriv/shared';
import { BinaryLink } from 'App/Components/Routes';
import 'Sass/app/_common/components/platform-dropdown.scss';
import { Localize } from '@deriv/translations';
import { useHistory } from 'react-router';
import { useDevice } from '@deriv-com/ui';
import { useIsHubRedirectionEnabled } from '@deriv/hooks';
import { useStore } from '@deriv/stores';

const PlatformBox = ({ platform: { icon, description } }) => (
<React.Fragment>
Expand Down Expand Up @@ -50,12 +52,20 @@ const PlatformDropdownContent = ({ platform, app_routing_history }) => {
const PlatformDropdown = ({ app_routing_history, closeDrawer, platform_config, setTogglePlatformType }) => {
const history = useHistory();
const { isDesktop } = useDevice();
const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled();
const { client } = useStore();
const { account_settings } = client;
const { trading_hub } = account_settings;

const TradersHubRedirect = () => {
return (
<div className='platform-dropdown__cta'>
<BinaryLink
onClick={() => {
if (isHubRedirectionEnabled || !!trading_hub) {
window.location.assign(platforms.tradershub_os.url);
return;
}
if (!isDesktop) {
history.push(routes.traders_hub);
setTogglePlatformType('cfd');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ jest.mock('@deriv/hooks', () => ({
useWalletAccountsList: jest.fn(() => ({
data: [{ loginid: 'CR007', dtrade_loginid: 'CR008' }],
})),
useIsHubRedirectionEnabled: jest.fn(() => ({
isHubRedirectionEnabled: false,
})),
}));

jest.mock('react-router', () => ({
Expand Down Expand Up @@ -93,7 +96,7 @@ describe('AccountSwitcherWalletMobile', () => {
expect(screen.getByText('AccountSwitcherWalletList')).toBeInTheDocument();
});

it('should toggle the switcher on footer click', () => {
it('should toggle the switcher on footer click', async () => {
const store = mockStore({
client: {
accounts: {
Expand All @@ -107,7 +110,7 @@ describe('AccountSwitcherWalletMobile', () => {
});
render(<AccountSwitcherWalletMobile {...props} />, { wrapper: wrapper(store) });
const footer = screen.getByText('Looking for CFDs? Go to Trader’s Hub');
userEvent.click(footer);
await userEvent.click(footer);
expect(props.toggle).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ jest.mock('react-router', () => ({
}),
}));

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
useIsHubRedirectionEnabled: () => ({
isHubRedirectionEnabled: false,
}),
}));

jest.mock('../account-switcher-wallet-list', () => ({
AccountSwitcherWalletList: () => <div>AccountSwitcherWalletList</div>,
}));
Expand Down Expand Up @@ -74,12 +81,12 @@ describe('AccountSwitcherWalletComponent', () => {
expect(screen.getByText('AccountSwitcherWalletList')).toBeInTheDocument();
});

it('should toggle the switcher on button click', () => {
it('should toggle the switcher on button click', async () => {
const mock = mockStore({});

render(<AccountSwitcherWallet {...props} />, { wrapper: wrapper(mock) });
const button = screen.getByTestId('dt_go_to_arrow');
userEvent.click(button);
await userEvent.click(button);
expect(props.toggle).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { useHistory } from 'react-router';
import { Button, Icon, MobileDialog, Text } from '@deriv/components';
import { routes } from '@deriv/shared';
import { platforms, routes } from '@deriv/shared';
import { Localize } from '@deriv/translations';
import { AccountSwitcherWalletList } from './account-switcher-wallet-list';
import { useIsRtl, useStoreWalletAccountsList } from '@deriv/hooks';
import { observer } from '@deriv/stores';
import { useIsHubRedirectionEnabled, useIsRtl, useStoreWalletAccountsList } from '@deriv/hooks';
import { observer, useStore } from '@deriv/stores';
import './account-switcher-wallet-mobile.scss';

type TAccountSwitcherWalletMobile = {
Expand All @@ -18,14 +18,22 @@ export const AccountSwitcherWalletMobile = observer(({ is_visible, toggle, login
const history = useHistory();
const isRtl = useIsRtl();
const { data: wallet_list } = useStoreWalletAccountsList();
const { client } = useStore();
const { account_settings } = client;
const { trading_hub } = account_settings;

const dtrade_account_wallets = wallet_list?.filter(wallet => wallet.dtrade_loginid);
const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled();

const closeAccountsDialog = React.useCallback(() => {
toggle(false);
}, [toggle]);

const handleTradersHubRedirect = () => {
if (isHubRedirectionEnabled || !!trading_hub) {
window.location.assign(platforms.tradershub_os.url);
return;
}
closeAccountsDialog();
history.push(routes.traders_hub);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { useHistory } from 'react-router';
import { Icon, Text, ThemedScrollbars, useOnClickOutside } from '@deriv/components';
import { routes } from '@deriv/shared';
import { observer } from '@deriv/stores';
import { platforms, routes } from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
import { Localize } from '@deriv/translations';
import { useStoreWalletAccountsList } from '@deriv/hooks';
import { useIsHubRedirectionEnabled, useStoreWalletAccountsList } from '@deriv/hooks';
import { AccountSwitcherWalletList } from './account-switcher-wallet-list';
import './account-switcher-wallet.scss';

Expand All @@ -18,8 +18,12 @@ export const AccountSwitcherWallet = observer(({ is_visible, toggle }: TAccountS
const dtrade_account_wallets = wallet_list?.filter(wallet => wallet.dtrade_loginid);

const history = useHistory();
const { client } = useStore();
const { account_settings } = client;
const { trading_hub } = account_settings;

const wrapper_ref = React.useRef<HTMLDivElement>(null);
const { isHubRedirectionEnabled } = useIsHubRedirectionEnabled();

const validateClickOutside = (event: MouseEvent) => {
const checkAllParentNodes = (node: HTMLElement): boolean => {
Expand All @@ -39,6 +43,10 @@ export const AccountSwitcherWallet = observer(({ is_visible, toggle }: TAccountS
useOnClickOutside(wrapper_ref, closeAccountsDialog, validateClickOutside);

const handleTradersHubRedirect = async () => {
if (isHubRedirectionEnabled || !!trading_hub) {
window.location.assign(platforms.tradershub_os.url);
return;
}
closeAccountsDialog();
history.push(routes.traders_hub);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const ConfirmEmailModal = observer(
const [is_modal_open, setIsModalOpen] = React.useState(is_open);

const { client } = useStore();
const { verification_code, setVerificationCode } = client;
const { verification_code, setVerificationCode, setPreventRedirectToHub } = client;

const handleSubmit = () => {
const api_request: TSocketRequest<'change_email'> = {
Expand Down Expand Up @@ -57,7 +57,10 @@ export const ConfirmEmailModal = observer(
return (
<SentEmailModal
is_open={is_send_email_modal_open}
onClose={() => setIsSendEmailModalOpen(false)}
onClose={() => {
setIsSendEmailModalOpen(false);
setPreventRedirectToHub(false);
}}
identifier_title={'Change_Email'}
onClickSendEmail={resendEmail}
has_live_chat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { Localize, localize } from '@deriv/translations';
import EmailResent from './email-resent';

const LinkExpiredModal = observer(() => {
const { ui } = useStore();
const { ui, client } = useStore();
const { setPreventRedirectToHub } = client;
const { enableApp, disableApp, is_link_expired_modal_visible: is_visible, toggleLinkExpiredModal } = ui;

const { send, error: verify_error, data: verify_data } = useVerifyEmail('reset_password');
Expand Down Expand Up @@ -60,7 +61,10 @@ const LinkExpiredModal = observer(() => {
enableApp={enableApp}
title={is_email_sent ? '' : localize('Link expired')}
has_close_icon
onConfirm={() => toggleLinkExpiredModal(false)}
onConfirm={() => {
toggleLinkExpiredModal(false);
setPreventRedirectToHub(false);
}}
>
<div className='link-expired'>
{is_email_sent ? (
Expand Down Expand Up @@ -94,7 +98,10 @@ const LinkExpiredModal = observer(() => {
<FormSubmitButton
has_cancel
cancel_label={localize('Close')}
onCancel={() => toggleLinkExpiredModal(false)}
onCancel={() => {
toggleLinkExpiredModal(false);
setPreventRedirectToHub(false);
}}
is_disabled={!values.email || !!errors.email || isSubmitting}
is_loading={isSubmitting}
label={localize('Resend email')}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import Cookies from 'js-cookie';
import { Button, Icon, MobileDialog, Modal, Text } from '@deriv/components';
Expand All @@ -9,13 +9,19 @@ import './wallets-upgrade-completed-modal.scss';

const WalletsUpgradeCompletedModal = observer(() => {
const history = useHistory();
const { ui } = useStore();
const { client, ui } = useStore();
const { is_mobile } = ui;
const { setPreventRedirectToHub } = client;
const [isOpen, setIsOpen] = useState(true);

useEffect(() => {
setPreventRedirectToHub(true);
}, []);

const handleClose = () => {
setIsOpen(false);
Cookies.remove('recent_wallets_migration');
setPreventRedirectToHub(false);
history.push(routes.traders_hub);
};

Expand Down
Loading

0 comments on commit 8664cb5

Please sign in to comment.