diff --git a/packages/core/src/index.html b/packages/core/src/index.html index e06deed4412f..2a91b3692b65 100644 --- a/packages/core/src/index.html +++ b/packages/core/src/index.html @@ -245,6 +245,7 @@ +
diff --git a/packages/core/src/sass/app/_common/layout/modal-root.scss b/packages/core/src/sass/app/_common/layout/modal-root.scss index f3fda62a5898..1b1340646019 100644 --- a/packages/core/src/sass/app/_common/layout/modal-root.scss +++ b/packages/core/src/sass/app/_common/layout/modal-root.scss @@ -1,4 +1,5 @@ -.modal-root { +.modal-root, +.launch-modal-root { width: 100vw; height: 100vh; align-items: center; @@ -22,3 +23,7 @@ z-index: 9999; } } + +.launch-modal-root:not(:empty) + .modal-root:not(:empty) { + display: none; +} diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-button.spec.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-button.spec.tsx new file mode 100644 index 000000000000..0b427eb6c342 --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-button.spec.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import LaunchModalButton from '../launch-modal-button'; + +const default_props = { + handleOpen: jest.fn(), + setShowDescription: jest.fn(), +}; + +const confirm_button = 'Ok'; +const learn_more_button = 'Learn more'; + +describe('', () => { + it('should render LaunchModalButton', () => { + render(); + + expect(screen.getByText(confirm_button)).toBeInTheDocument(); + expect(screen.getByText(learn_more_button)).toBeInTheDocument(); + }); + + it('should call only handleOpen function if user click on OK button', () => { + render(); + + userEvent.click(screen.getByText(confirm_button)); + expect(default_props.handleOpen).toBeCalled(); + expect(default_props.setShowDescription).not.toBeCalled(); + }); + + it('should call both handleOpen and setShowDescription function if user click on Learn more button', () => { + render(); + + userEvent.click(screen.getByText(learn_more_button)); + expect(default_props.handleOpen).toBeCalled(); + expect(default_props.setShowDescription).toBeCalled(); + }); +}); diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-info.spec.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-info.spec.tsx new file mode 100644 index 000000000000..9ab5e1f30f6d --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal-info.spec.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import LaunchModalInfo from '../launch-modal-info'; +import { render, screen } from '@testing-library/react'; + +jest.mock('Assets/SvgComponents/trade_explanations/img-turbos.svg', () => jest.fn(() =>
Turbos Image
)); + +describe('', () => { + it('should render component', () => { + render(); + + expect(screen.getByText('Turbos Image')).toBeInTheDocument(); + expect(screen.getByText('Turbos — a new trade type for you!')).toBeInTheDocument(); + }); +}); diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal.spec.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal.spec.tsx similarity index 74% rename from packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal.spec.tsx rename to packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal.spec.tsx index fd007ccee690..fc43007d302b 100644 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal.spec.tsx +++ b/packages/trader/src/App/Components/Elements/LaunchModal/__tests__/launch-modal.spec.tsx @@ -7,8 +7,12 @@ import LaunchModal from '../launch-modal'; const mocked_default_props = { handleChange: jest.fn(() => LocalStore.set('launchModalShown', JSON.stringify(true))), + setShowDescription: jest.fn(), open: true, }; +const launch_modal_id = 'launch-modal'; + +jest.mock('Assets/SvgComponents/trade_explanations/img-turbos.svg', () => jest.fn(() =>
Turbos Image
)); describe('', () => { beforeAll(() => { @@ -28,22 +32,23 @@ describe('', () => { it('should render launch modal ', () => { render(); - expect(screen.getByTestId('launch-modal')).toBeInTheDocument(); + expect(screen.getByTestId(launch_modal_id)).toBeInTheDocument(); }); - it('should set the localStorage key launchModalShown to true on clicking the continue button', async () => { + it('should set the localStorage key launchModalShown to true on clicking the Ok button', async () => { render(); - expect(screen.getByTestId('launch-modal')).toBeInTheDocument(); + expect(screen.getByTestId(launch_modal_id)).toBeInTheDocument(); - const continue_btn = screen.getByRole('button', { name: 'Continue' }); + const continue_btn = screen.getByRole('button', { name: 'Ok' }); userEvent.click(continue_btn); const value = JSON.parse(LocalStore.get('launchModalShown') ?? 'false'); expect(value).toBe(true); }); + it('should not display launch modal if open is equal to false', () => { render(); - expect(screen.queryByTestId('launch-modal')).not.toBeInTheDocument(); + expect(screen.queryByTestId(launch_modal_id)).not.toBeInTheDocument(); }); }); diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/index.ts b/packages/trader/src/App/Components/Elements/LaunchModal/index.ts new file mode 100644 index 000000000000..eeabb86a6d5e --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/index.ts @@ -0,0 +1,3 @@ +import LaunchModal from './launch-modal'; + +export default LaunchModal; diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-button.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-button.tsx new file mode 100644 index 000000000000..250c6ddca5d4 --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-button.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { Button, Modal } from '@deriv/components'; +import { Localize } from '@deriv/translations'; + +const LaunchModalButton = ({ + handleOpen, + setShowDescription, +}: { + handleOpen: () => void; + setShowDescription: (status: boolean) => void; +}) => ( + + + + +); + +export default LaunchModalButton; diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-info.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-info.tsx new file mode 100644 index 000000000000..f50b96014a4e --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal-info.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import ImageTurbos from 'Assets/SvgComponents/trade_explanations/img-turbos.svg'; +import { Text } from '@deriv/components'; +import { Localize } from '@deriv/translations'; + +const LaunchModalInfo = ({ is_mobile }: { is_mobile?: boolean }) => { + return ( +
+ + + + + + + + + + + + + +
+ ); +}; + +export default LaunchModalInfo; diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.scss b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.scss new file mode 100644 index 000000000000..943d6bb6d271 --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.scss @@ -0,0 +1,59 @@ +// For Web Modal +.dc-modal__container_launch-modal-root { + text-align: center; + + .dc-modal-body { + justify-content: center; + display: flex; + height: 100%; + + .modal { + &_image { + margin: 2.4rem 0rem; + width: 21.6rem; + height: 12.8rem; + border-radius: 0.6rem; + } + } + } + + .dc-modal-footer { + .launch-button { + min-width: 5.1rem; + } + } +} + +// For Mobile +.launch-page-mobile { + text-align: center; + display: flex; + flex-direction: column; + height: 100%; + + .modal { + &_content { + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 1rem; + } + + &_image { + margin-bottom: 2.4rem; + border-radius: 0.6rem; + } + } + + .dc-modal-footer { + border-top: 0.2rem solid var(--general-section-5); + padding: 1.6rem; + + .launch-button { + height: 4rem; + width: 100%; + } + } +} diff --git a/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.tsx b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.tsx new file mode 100644 index 000000000000..d159cda8c18b --- /dev/null +++ b/packages/trader/src/App/Components/Elements/LaunchModal/launch-modal.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { DesktopWrapper, MobileWrapper, Modal, UILoader } from '@deriv/components'; +import LaunchModalInfo from './launch-modal-info'; +import LaunchModalButton from './launch-modal-button'; +import './launch-modal.scss'; + +type LaunchModalProps = { + handleChange: () => void; + open: boolean; + setShowDescription: (status: boolean) => void; +}; + +const LaunchModal = ({ handleChange, open, setShowDescription }: LaunchModalProps) => ( + }> + + + + + + + + + +
+ + +
+
+
+); + +export default LaunchModal; diff --git a/packages/trader/src/Assets/SvgComponents/trade_explanations/img-turbos.svg b/packages/trader/src/Assets/SvgComponents/trade_explanations/img-turbos.svg new file mode 100644 index 000000000000..39880d8c9997 --- /dev/null +++ b/packages/trader/src/Assets/SvgComponents/trade_explanations/img-turbos.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-continue-button.spec.tsx b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-continue-button.spec.tsx deleted file mode 100644 index 334d668ead19..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-continue-button.spec.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react'; -import { render, screen } from '@testing-library/react'; -import LaunchModalContinueButton from '../launch-modal-continue-button'; - -describe('Launch Modal Continue Button', () => { - it('should Continue Button', () => { - render(); - expect(screen.getByText('Continue')).toBeInTheDocument(); - }); -}); diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-info.spec.tsx b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-info.spec.tsx deleted file mode 100644 index 26bb11e5fd6c..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/__tests__/launch-modal-info.spec.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as React from 'react'; -import LaunchModalInfo from '../launch-modal-info'; -import { render, screen } from '@testing-library/react'; - -describe('Launch Modal Info', () => { - it('should render the component', () => { - render(); - expect(screen.getByText('Smoother charts. Smarter insights.')).toBeInTheDocument(); - }); -}); diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-continue-button.tsx b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-continue-button.tsx deleted file mode 100644 index b290bd8e13e9..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-continue-button.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import { Button, Modal } from '@deriv/components'; -import { Localize } from '@deriv/translations'; - -const LaunchModalContinueButton = ({ handleOpen }: { handleOpen: () => void }) => ( - - - -); - -export default LaunchModalContinueButton; diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-info.tsx b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-info.tsx deleted file mode 100644 index b6151903e9d2..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal-info.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { Text } from '@deriv/components'; -import { Localize } from '@deriv/translations'; - -const LaunchModalInfo = () => ( -
- - - - - - -
-); - -export default LaunchModalInfo; diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.scss b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.scss deleted file mode 100644 index 093995f6a8d6..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.scss +++ /dev/null @@ -1,40 +0,0 @@ -// For Web Modal -.dc-modal__container_modal_root { - text-align: center; - .dc-modal-body { - justify-content: center; - display: flex; - height: 100%; - flex-direction: column; - } - - .dc-modal-footer { - border-top: 0.2rem solid var(--general-section-5); - padding: 1.6rem 2.4rem; - } -} - -// For Mobile -.launch-page-mobile { - text-align: center; - display: flex; - flex-direction: column; - height: 100%; - - .modal-content { - height: 100%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - } - - .dc-modal-footer { - border-top: 0.2rem solid var(--general-section-5); - padding: 1.6rem 2.4rem; - .continue-button { - height: 4rem; - width: 100%; - } - } -} diff --git a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.tsx b/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.tsx deleted file mode 100644 index a3b7d8e371a0..000000000000 --- a/packages/trader/src/Modules/SmartChartBeta/Components/LaunchModal/launch-modal.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { DesktopWrapper, MobileWrapper, Modal, UILoader } from '@deriv/components'; -import React from 'react'; -import './launch-modal.scss'; -import { observer } from '@deriv/stores'; -import LaunchModalInfo from './launch-modal-info'; -import ContinueButton from './launch-modal-continue-button'; - -type LaunchModalProps = { - handleChange: () => void; - open: boolean; -}; - -const LaunchModal = ({ handleChange, open }: LaunchModalProps) => ( - }> - - - - - - - - - -
- - -
-
-
-); - -export default observer(LaunchModal); diff --git a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx index 65da6557c0d3..37916f6fc1fc 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx +++ b/packages/trader/src/Modules/Trading/Components/Form/ContractType/contract-type-widget.tsx @@ -4,6 +4,7 @@ import { observer, useStore } from '@deriv/stores'; import { Localize, localize } from '@deriv/translations'; import { Analytics } from '@deriv/analytics'; import ContractType from './contract-type'; +import { TRADE_TYPES } from '@deriv/shared'; import { findContractCategory, getContractTypeCategoryIcons, @@ -32,7 +33,7 @@ const ContractTypeWidget = observer( active_symbols: { active_symbols }, ui: { is_mobile }, } = useStore(); - const { symbol } = useTraderStore(); + const { symbol, show_description, setShowDescription } = useTraderStore(); const wrapper_ref = React.useRef(null); const [is_dialog_open, setDialogVisibility] = React.useState(); const [is_info_dialog_open, setInfoDialogVisibility] = React.useState(false); @@ -66,8 +67,17 @@ const ContractTypeWidget = observer( form_source: 'contract_set_up_form', form_name: 'default', }); + if (!is_dialog_open) setShowDescription(false); } - }, [is_dialog_open]); + }, [is_dialog_open, setShowDescription]); + + React.useEffect(() => { + if (show_description) { + onWidgetClick(); + handleInfoClick({ text: 'Long/Short', value: TRADE_TYPES.TURBOS.LONG }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [show_description]); const handleCategoryClick: React.ComponentProps['onCategoryClick'] = ({ key }) => { if (key) setSelectedCategory(key); @@ -77,6 +87,7 @@ const ContractTypeWidget = observer( clicked_item: TContractType, e: React.MouseEvent ) => { + setShowDescription(false); const categories = list_with_category(); const { key } = findContractCategory(categories, clicked_item); if ('id' in e.target && e.target.id !== 'info-icon' && clicked_item) { diff --git a/packages/trader/src/Modules/Trading/Containers/trade.tsx b/packages/trader/src/Modules/Trading/Containers/trade.tsx index 625edd5aa09b..ca5437b46e8f 100644 --- a/packages/trader/src/Modules/Trading/Containers/trade.tsx +++ b/packages/trader/src/Modules/Trading/Containers/trade.tsx @@ -11,7 +11,7 @@ import MarketIsClosedOverlay from 'App/Components/Elements/market-is-closed-over import { ChartTopWidgets, DigitsWidget } from './chart-widgets'; import FormLayout from '../Components/Form/form-layout'; import TradeChart from './trade-chart'; -import LaunchModal from 'Modules/SmartChartBeta/Components/LaunchModal/launch-modal'; +import LaunchModal from 'App/Components/Elements/LaunchModal'; export type TBottomWidgetsParams = { digits: number[]; @@ -56,6 +56,7 @@ const Trade = observer(() => { prepareTradeStore, setIsDigitsWidgetActive, setMobileDigitView, + setShowDescription, should_show_active_symbols_loading, show_digits_stats, symbol, @@ -114,6 +115,10 @@ const Trade = observer(() => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [symbol, setDigits, setTrySyntheticIndices, is_synthetics_available]); + React.useEffect(() => { + setOpenLaunchModal(is_turbos); + }, [is_turbos]); + const bottomWidgets = React.useCallback(({ digits: d, tick: t }: TBottomWidgetsParams) => { return ; }, []); @@ -124,7 +129,7 @@ const Trade = observer(() => { setSwipeIndex(index); }; - const is_already_shown = LocalStore.get('launchModalShown') || false; + const is_already_shown = LocalStore.get('launchTurbosModalShown') || false; const onTryOtherMarkets = async () => { if (!is_synthetics_available) { @@ -150,13 +155,17 @@ const Trade = observer(() => { const handleLaunchModal = () => { setOpenLaunchModal(!open_launch_modal); - LocalStore.set('launchModalShown', true); + LocalStore.set('launchTurbosModalShown', true); }; return ( - {open_launch_modal && is_logged_in && !is_already_shown && ( - + {!is_eu && open_launch_modal && is_logged_in && !is_already_shown && ( + )}
{ + this.show_description = status; + }; + refresh() { this.forgetAllProposal(); this.proposal_info = {};