Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WALL] george / WALL-5028 / Lazy Load "react-joyride" library with wallet onboarding tour guide code #17178

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { useHistory } from 'react-router-dom';
import { useLocalStorage } from 'usehooks-ts';
heorhi-deriv marked this conversation as resolved.
Show resolved Hide resolved
import { Icon, Popover } from '@deriv/components';
import { routes, isTabletOs } from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
Expand All @@ -9,11 +8,10 @@ import { Localize } from '@deriv/translations';
const TradersHubOnboarding = observer(() => {
const history = useHistory();
const { ui } = useStore();
const { is_dark_mode_on, is_mobile } = ui;
const [, setWalletsOnboarding] = useLocalStorage('walletsOnboarding', '');
const { is_dark_mode_on, is_mobile, setIsWalletsOnboardingTourGuideVisible } = ui;

const onClickHandler = () => {
setWalletsOnboarding('started');
setIsWalletsOnboardingTourGuideVisible(true);
if (history.location.pathname !== routes.traders_hub) {
history.push(routes.traders_hub);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,22 @@ const Wallets = React.lazy(() =>
);

const RootComponent = observer(props => {
const { client } = useStore();
const { client, ui } = useStore();
const { is_wallets_onboarding_tour_guide_visible, setIsWalletsOnboardingTourGuideVisible } = ui;
const { has_wallet } = client;

return has_wallet ? <Wallets /> : <AppStore {...props} />;
const onWalletsOnboardingTourGuideCloseHandler = () => {
setIsWalletsOnboardingTourGuideVisible(false);
};

return has_wallet ? (
<Wallets
isWalletsOnboardingTourGuideVisible={is_wallets_onboarding_tour_guide_visible}
onWalletsOnboardingTourGuideCloseHandler={onWalletsOnboardingTourGuideCloseHandler}
/>
) : (
<AppStore {...props} />
);
});

export default RootComponent;
4 changes: 0 additions & 4 deletions packages/core/src/Stores/client-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -1475,10 +1475,6 @@ export default class ClientStore extends BaseStore {
* We initially fetch things from local storage, and then do everything inside the store.
*/
async init(login_new_user) {
// delete walletsOnboarding key after page refresh
/** will be removed later when header for the wallets is created) */
localStorage.removeItem('walletsOnboarding');

const search = SessionStore.get('signup_query_param') || window.location.search;
const search_params = new URLSearchParams(search);
const redirect_url = search_params?.get('redirect_url');
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/Stores/ui-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ export default class UIStore extends BaseStore {
deposit_real_account_signup_target = undefined;
has_real_account_signup_ended = false;

// wallets onboarding tour guide
is_wallets_onboarding_tour_guide_visible = false;

// verification modal
is_verification_modal_visible = false;

Expand Down Expand Up @@ -299,6 +302,7 @@ export default class UIStore extends BaseStore {
is_trading_assessment_for_existing_user_enabled: observable,
is_trading_assessment_for_new_user_enabled: observable,
is_verification_modal_visible: observable,
is_wallets_onboarding_tour_guide_visible: observable,
is_verification_submitted: observable,
is_mt5_migration_modal_open: observable,
is_mt5_migration_modal_enabled: observable,
Expand Down Expand Up @@ -397,6 +401,7 @@ export default class UIStore extends BaseStore {
setIsRealTabEnabled: action.bound,
setIsTradingAssessmentForExistingUserEnabled: action.bound,
setIsTradingAssessmentForNewUserEnabled: action.bound,
setIsWalletsOnboardingTourGuideVisible: action.bound,
setManageRealAccountActiveTabIndex: action.bound,
setModalIndex: action.bound,
setPromptHandler: action.bound,
Expand Down Expand Up @@ -992,6 +997,10 @@ export default class UIStore extends BaseStore {
this.is_from_success_deposit_modal = value;
}

setIsWalletsOnboardingTourGuideVisible(value) {
this.is_wallets_onboarding_tour_guide_visible = value;
}

setIsMFVericationPendingModal(value) {
this.is_mf_verification_pending_modal_visible = value;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/stores/src/mockStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ const mock = (): TStores & { is_mock: boolean } => {
is_services_error_visible: false,
should_show_phone_number_otp: false,
is_trading_assessment_for_existing_user_enabled: false,
is_wallets_onboarding_tour_guide_visible: false,
setIsForcedToExitPnv: jest.fn(),
setIsPhoneVerificationCompleted: jest.fn(),
setRedirectFromEmail: jest.fn(),
Expand Down Expand Up @@ -509,6 +510,7 @@ const mock = (): TStores & { is_mock: boolean } => {
url_hashed_values: '',
is_tnc_update_modal_open: false,
toggleTncUpdateModal: jest.fn(),
setIsWalletsOnboardingTourGuideVisible: jest.fn(),
},
traders_hub: {
getAccount: jest.fn(),
Expand Down
2 changes: 2 additions & 0 deletions packages/stores/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ type TUiStore = {
is_reset_email_modal_visible: boolean;
is_services_error_visible: boolean;
is_trading_assessment_for_existing_user_enabled: boolean;
is_wallets_onboarding_tour_guide_visible: boolean;
isUrlUnavailableModalVisible: boolean;
onChangeUiStore: ({ name, value }: { name: string; value: unknown }) => void;
openPositionsDrawer: () => void;
Expand Down Expand Up @@ -863,6 +864,7 @@ type TUiStore = {
setShouldShowCryptoTransactionProcessingModal: (value: boolean) => void;
is_trading_disabled_by_residence_modal_visible: boolean;
setIsTradingDisabledByResidenceModal: (value: boolean) => void;
setIsWalletsOnboardingTourGuideVisible: (value: boolean) => void;
should_show_same_dob_phone_modal: boolean;
setShouldShowSameDOBPhoneModal: (value: boolean) => void;
setHashedValue: (value: string) => void;
Expand Down
18 changes: 16 additions & 2 deletions packages/wallets/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react';
import React, { lazy, useMemo, useState } from 'react';
import { APIProvider } from '@deriv/api-v2';
import { initializeI18n, TranslationProvider } from '@deriv-com/translations';
import { Loader } from '@deriv-com/ui';
Expand All @@ -10,7 +10,14 @@ import { TLanguageType } from './types';
import './styles/fonts.scss';
import './index.scss';

const App: React.FC = () => {
type TProps = {
isWalletsOnboardingTourGuideVisible: boolean;
onWalletsOnboardingTourGuideCloseHandler: VoidFunction;
};

const LazyWalletTourGuide = lazy(() => import('./components/WalletTourGuide/WalletTourGuide'));

const App: React.FC<TProps> = ({ isWalletsOnboardingTourGuideVisible, onWalletsOnboardingTourGuideCloseHandler }) => {
const [preferredLanguage, setPreferredLanguage] = useState<TLanguageType | null>(null);
const language = useLanguage(preferredLanguage);

Expand All @@ -33,6 +40,13 @@ const App: React.FC = () => {
<AppContent setPreferredLanguage={setPreferredLanguage} />
</ModalProvider>
</React.Suspense>
{isWalletsOnboardingTourGuideVisible && (
<React.Suspense fallback={<Loader />}>
<LazyWalletTourGuide
onWalletsOnboardingTourGuideCloseHandler={onWalletsOnboardingTourGuideCloseHandler}
/>
</React.Suspense>
)}
</TranslationProvider>
</WalletsAuthProvider>
</APIProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react';
import Joyride, { CallBackProps, STATUS } from 'react-joyride';
import { useLocalStorage, useReadLocalStorage } from 'usehooks-ts';
import {
useAllWalletAccounts,
useAuthorize,
Expand All @@ -11,19 +10,16 @@ import {
import { useDevice } from '@deriv-com/ui';
import useIsRtl from '../../hooks/useIsRtl';
import useWalletAccountSwitcher from '../../hooks/useWalletAccountSwitcher';
import { useModal } from '../ModalProvider';
import {
TooltipComponent,
walletsOnboardingLocalStorageKey as key,
walletsOnboardingStartValue as START_VALUE,
} from './WalletTourGuideSettings';
import { TooltipComponent } from './WalletTourGuideSettings';
import { desktopStepTourGuide, mobileStepTourGuide } from './WalletTourGuideSteps';

const WalletTourGuide = () => {
const [walletsOnboarding, setWalletsOnboarding] = useLocalStorage(key, useReadLocalStorage(key) ?? '');
type TProps = {
onWalletsOnboardingTourGuideCloseHandler: VoidFunction;
};

const WalletTourGuide: React.FC<TProps> = ({ onWalletsOnboardingTourGuideCloseHandler }) => {
const [run, setRun] = useState(false);
const { isDesktop } = useDevice();
const modal = useModal();
const isRtl = useIsRtl();

const switchWalletAccount = useWalletAccountSwitcher();
Expand All @@ -33,30 +29,23 @@ const WalletTourGuide = () => {
const { isFetching: sortedAccountsIsLoading } = useSortedMT5Accounts();
const { data: availableWallets } = useAllWalletAccounts();

const needToStart = walletsOnboarding === START_VALUE;
const isEverythingLoaded =
!isLoading && !isFetching && isSuccess && !ctraderIsLoading && !dxtradeIsLoading && !sortedAccountsIsLoading;
const allWalletsAreAdded = Boolean(availableWallets?.every(wallet => wallet.is_added));

useEffect(() => {
if (needToStart && modal.isOpen) {
modal.hide();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [needToStart, modal.isOpen]);

useEffect(() => {
if (needToStart && isEverythingLoaded) {
setWalletsOnboarding('');
if (isEverythingLoaded) {
setRun(true);
}
}, [run, setRun, needToStart, isEverythingLoaded, switchWalletAccount, setWalletsOnboarding]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [run, setRun, isEverythingLoaded, switchWalletAccount]);

const callbackHandle = async (data: CallBackProps) => {
const { status } = data;
const finishedStatuses: string[] = [STATUS.FINISHED, STATUS.SKIPPED];
if (finishedStatuses.includes(status)) {
setRun(false);
onWalletsOnboardingTourGuideCloseHandler();
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ import { Localize } from '@deriv-com/translations';
import { Button, Text } from '@deriv-com/ui';
import './WalletTourGuide.scss';

export const walletsOnboardingLocalStorageKey = 'walletsOnboarding';
export const walletsOnboardingStartValue = 'started';

export const TooltipComponent = ({
backProps,
closeProps,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import React, { lazy } from 'react';
import { useDevice } from '@deriv-com/ui';
import {
WalletListHeader,
WalletsAddMoreCarousel,
WalletsCardLoader,
WalletsResponsiveLoader,
WalletTourGuide,
} from '../../components';
import { WalletListHeader, WalletsAddMoreCarousel, WalletsCardLoader, WalletsResponsiveLoader } from '../../components';
import ResetMT5PasswordHandler from '../../features/cfd/ResetMT5PasswordHandler';
import './WalletsListingRoute.scss';

Expand All @@ -30,7 +24,6 @@ const WalletsListingRoute: React.FC = () => {
)}
<WalletsAddMoreCarousel />
<ResetMT5PasswordHandler />
<WalletTourGuide />
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ describe('WalletsListingRoute', () => {
jest.clearAllMocks();
});

it('renders DesktopWalletsList, WalletsAddMoreCarousel and WalletTourGuide correctly on desktop', async () => {
it('renders DesktopWalletsList and WalletsAddMoreCarousel correctly on desktop', async () => {
render(<WalletsListingRoute />, { wrapper });
expect(screen.getByText('WalletListHeader')).toBeInTheDocument();
expect(screen.queryByText('WalletsCarousel')).not.toBeInTheDocument();
expect(screen.getByText('WalletTourGuide')).toBeInTheDocument();
expect(await screen.findByText('DesktopWalletsList')).toBeInTheDocument();
});

Expand All @@ -55,6 +54,5 @@ describe('WalletsListingRoute', () => {
expect(screen.getByText('WalletListHeader')).toBeInTheDocument();
expect(screen.queryByText('DesktopWalletsList')).not.toBeInTheDocument();
expect(await screen.findByText('WalletsCarousel')).toBeInTheDocument();
expect(screen.queryByText('WalletTourGuide')).toBeInTheDocument();
});
});
Loading