From 506292efc662b4cf471d9f072b72f744287d90ee Mon Sep 17 00:00:00 2001 From: amina-deriv <84661147+amina-deriv@users.noreply.github.com> Date: Mon, 1 Aug 2022 13:57:15 +0400 Subject: [PATCH] Matin/ Hirad/ Amina/ Maryia-task_push_labuan_bvi_vanuatu (#5697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added add account buttons * Fixed add button issues * Added disabled * feat: sorry amina * Changed the condition of add account button * Added condition for add account * Renamed add account button and fixes its condition * Revert "feat: sorry amina" This reverts commit ca7bc6c330973d95fd836b6f0ac999341871e471. * Fixed the undefined issue in disabled cards * Fixed the issue of undefined data * Added condition for failed POI and POA * Maryia/Fix: for tests and add buttons (#15) * Maryia/fix for tests and account buttons * Fix: removed duplication for ModalCheckbox * poa_error_msg * Changed the conditions of POI and POA failed * Pulled from master * Added conditional modal button function * Maryia/fix: jurisdiction modal next button enabling (#16) * Maryia/fix: jurisdiction modal next buton enabling * refactoring * Fixed buttonText conditions * Chore: MT5 Trade Modal implementation * Maryia/used local state for setting selected card & updated flow (#17) * Maryia/used local state for setting selected card & updated flow * fix: for tests * Added the compare accounts add button integration * Pulled from master * Added box shadow hover to jurisdiction card * Chore: Account signup flow improvement * Chore: code cleanup * Fixed some of the stylings of MT5 cards * Fixed the mobile banner issue * Maryia/Fix: CFDPersonalDetails styles & logics + refactoring (#18) * Maryia/Fix: synthetic flow + refactoring * Maryia/Fix: CFDPersonalDetails styles + refactoring * Maryia/Fix: for Labuan footnote to not appear when pending status is visible * Chore: small bug fixes * Added three new conditions for modal footnote * Pulled from master * Maryia/fix: quick fix for failed & pending statuses (#19) * fix for pending statuses * showing status when the card is selected * quick fix for poi/poa failed statuses & footnotes * Maryia/used shortcode + updated mt5_new_account request & cfd personal account modal (#20) * Maryia/used shortcode + updated mt5_new_account request & cfd personal account modal * commented out personal details form tests temporarily * Revert "Maryia/used shortcode + updated mt5_new_account request & cfd personal account modal (#20)" (#21) This reverts commit 05bd322f35c328ee663d426379ecb88021a8fdda. * Maryia/used shortcode + updated mt5_new_account request (#23) * Maryia/using shortcode + mt5_new_account request + updated cfd personal account modal * commented out personal details form tests temporarily * revert personal details form * revert tests for cfd personal detail form * revert cfd personal details modal * revert prop types * prevent memory leak in cfd personal details modal * Chore: update jurisdiction cards style * Chore: Fixed bug on CFD card banners * Fixed poa failed and poi failed conditions * Changed is pending footnote condition * Maryia/fix: next button for failed+pending (#24) * Fixed the texts of jurisdiction cards * style fix for poi-poa * style fix for poi-poa * Added condition for Account added * maltainvest * Finished DXTrade styling * Pulled from main branch * Maryia/fix: state for failed+none (#25) * Maryia/fix: state for failed+none * getting settings in jurisdiction modal to check if the client has already submitted personal details * fix: statuses for failed + none * Fixes some styling issues * Fixed some stylings * Fixed paddings of verification statuses * Chore: Fix trade modal heading title * Fixes some of our issues * Maryia/fix: jurisdiction modal styles & open account request (financial flow check) (#26) * Maryia/fix: tnc agreement footnote * Maryia/fixed styles & added more data to open account request * fix: remove used classname * Chore: Fix logged out MT5 dashboard bug * Chore: Hide adding account from compare accounts modal when logged out * Chore: Huawei appgallery - CFD dashboard style updates * Chore: Huawei on mobile * Chore: Fix a tiny bug * Added seperator to the modal footer * Fixed console warning issues * Maryia/Merged from master & resolved conflicts + small style fix for dmt5 dashboard (#27) * Niloofar / Indicators documentation review (#5825) * indicators documentation review * resolved review comment Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * Niloofar / Trader documentation review (#5792) * edit some parts of trader docs * remove extra information from traders docs Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * shayan / cfd documentation updated (#5800) * docs/ cfd readme.md updated * Update README.md * docs/ Readme file updated * docs/ readme file updated * docs/ Update packages/cfd/README.md Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * docs/ Update packages/cfd/README.md Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * docs /Update packages/cfd/README.md Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * docs/ update readme file * doc/ updated readme file * doc/ updated readme file * doc/ updated readme file Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> * yauheni / Notify users about sharing tokens with admin scope selected (#5741) * yauheni / Notify users about sharing tokens with admin scope selected, added note * tests fix * created token scope styling * deleted option test fix * token value fild markup * clipboard with warning dialog implemented * responsive version done, tests refactoring * dialog fix for admin scope * check commit after rebuild * css fixes, refactor after review * svg icon fill color fix * inline note fix * Delete package-lock.json * fix commit * fix * dots component placing fix * dialog fixes * api token tests fix * css fix for token table * review fixes * naming fix, close delete dialog timeout deleted * testcase fix * localize fix * admin note message change * copy token hover message fix * token alignment eye button fix * ok button capital letters fix * delete button hover fix, clipboard refactor Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”> * farrah/ fixed cfd lint errors (#5607) * ci/ exclude dist files from eslint scan * ci/ disable spaced-comment * ci/ exclude lib dir from eslint scan * fixed cfd eslint errors * renamed variables and fixed types * fixed missing return function * refactor code * fixed cleanup function * fixed invalid property document_file on submit Co-authored-by: Ali(Ako) Hosseini * yashim/feat: add TTI Measurement (#5764) * feat: add TTI Measurement * fix: security error * fix: add regex to fire only in specific domain * chore: remove console log * fix: remove TTI script. Offload to GTM * chore: revert gtm loading changes * translations: 📚 sync translations with crowdin (#5965) Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> * chore: removed unused prop from jurisdiction card * fix for dmt5 server maintenance & download center styles Co-authored-by: Niloofar Sadeghi <93518187+niloo-fs@users.noreply.github.com> Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> Co-authored-by: Shayan Khaleghparast <100833613+iman-fs@users.noreply.github.com> Co-authored-by: yauheni-kryzhyk-deriv <103182683+yauheni-kryzhyk-deriv@users.noreply.github.com> Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”> Co-authored-by: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> Co-authored-by: Ali(Ako) Hosseini Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> * eu-cfd-modal * Fixed compare accounts modal account creation issues * Added financial in front of the malatinvest for Adding account * Maryia/updated t&c links and improved jurisdiction modal (#29) * modal * modal- style * add account fix * Chore: hide compare accounts button * Chore: Display all MT5 accounts created * vanuatu-only-onfido * Fixed the issue where modal goes to the left * banner condition changes * Fixed the issue where selected card was showing wrong data * Pulled from main branch * Fixed the real mt5 account top up button issue * onfido failed * Fixed existing financial_stp account not being shown * real-account-under-virtual deriv * Increased the delay before closing and opening of modals * Fixed the sliding of the compare accounts modal * Account transfer will show the landing company to the end of accounts name * Added some more timeout function to prevent sliding modal to the left * Added timeout for all of toggle modals * Fixed POI acknowledged issue * Fixed can have more real synthetic mt5 condition to hide add account button if we do not have any more accounts to create * notifications * remove duplicate notifications * Changed the styling of disabled account * Made banners text capitalization exactly like the design * Account switcher add button won't show up when we cannot create anymore accounts * Maryia/fix: showing only available accounts in CompareAccountsModal (#30) * Maryia/fix: showing only available accounts in CompareAccountsModal * fix: getting complete content for all available accounts + removed unused has_cfd_account * Maryia/finalized CompareAccountsModal table * Merge branch master of github.com:binary-com/deriv-app into task_push_labuan_bvi_vanuatu * cfd-personal-details * Chore: JY's requests reflected. * Maryia/Refactor: compare account modal content + improvements (#32) * Maryia/refactoring compare accounts modal content * added a case for 0 financial or 0 synthetic accounts count * improved synthetic & financial header style loop * Chore: cfd card height update * svg routing * Added new conditions for add account button * Fixed the capital letter demonstration of SVG and BVI banner texts * Fixed the TTradingPlatfromAvailabeAccount Type * Fixed CodeCov error * svg routing * Fixed labuan account creation bug * Fixed Code Cov errors * Fixed demo account dashboard error and hid the add button for it * compare account fix * compare account fix * poi-poa-mobile-style-fixes * Changed over header color * Fixed the issue where server name was shown for BVI, Labuan and ... * Fixed compare accounts account creation flow * Added new styling for demo accounts * poa-fix * Added login id to demo accounts * Fixed the account transfer text upper and lower cases * account swtcher fix * region in account switcher * overheader change in jurisdiction * Fixed eu password manager modal header title * Fixed eu user cfd icon color and trading account label * Fixed the add account buttun issue where having more than one account with same landing_company_shortcode hides the button * Fixed the redirected account to reset password errors * Fixed demo accounts backward compatibility * Fixed EU demo account text in account switcher * Chore: Resolve SonarCloud bug * server name for account switcher * server name for account switcher * Fixed account switcher bug which shows add button even when we have accounts created * revert-last commit * Fixed the issue where add button in account switcher was shown even after having all of the accounts created * Chore: login id padding issues fixed for Demo * Chore: Small padding update for Labuan clients * Fixed derivx account name in cashier transfer * tnc fix * Fixed POIPOA submited text * remove equities * Fixed the checkbox issue in mobile mode * Fixed account switcher issues * labuan -compare-accounts-modal-content-update * Fixed the font size of Proof of identity and address are required in verification statuses * Changed the straight through processing text style * Fixed account switcher bug * fix in tnc checkbox * Consolidated the responsive design * separator line in demo account switcher * Maryia/Fixed modals sliding to the left using styles * compare modal * Fixed the issue of account switcher for backward compatibility * Fixed the mt5-trade-modal title for eu users * Chore: added tooltip info to jurisdiction modal for Financial Labuan account * fix loading * Fixed the grammatical issue of MT5 server maintenance message * Fixed mt5 trade modal header title for eu accounts * compare account fix * compare accout fix * Added malta invest footnote * Fixed the text color of one of jurisdiction footnotes * Maryia/fix: add buttons + accounts switcher + only svg available to add in demo (#35) * Maryia/fix: add buttons + accounts switcher + only svg available for demo * showing company shortcode for added demo accounts * show company shortcode in demo only for financial labuan * fix: setting company code for demo account opening request * fix for tests * Fixed the issue where jurisdiction cards were linked in responsive design * Fixed sonar cloud issue * Sonar cloud fix * Fixed sonar cloud issue * Sonar cloud issue * Maryia/fix: sliding trade modal & compare accounts modal (#36) * Sonar cloud issue * Checking sonar cloud issue * Fixed MT5 success dialog icon * Maryia/fix add buttons for multiple real accounts * Fixed server tag for account switcher * Maryia/fix: CompareAccountsModal Add button to open real account needed modal (#37) * Maryia/fix showing real acc needed when adding acc from compare acc modal * fixed compare accounts modal for logged out clients * removed unused loading state from poi/poa * vanuatu flow from compare accounts modal * Maryia/fix: console TS warning for exit_classname type * Fix: Display popovers on top of Trade modal * Fixed the issue where server name was shown for bvi accounts as well * Maryia/fix: setting account type in compare accounts modal * next button logic * vanuatu flow * Fix: title update and css changes * app crash issue * vanuatu banner and next button labels * Fixed the issue where server banner was shown even for accounts with 1 synthetic svg account in account switcher * onfido blank screen check * Maryia/fix: avoided state update on unmounted CFDFinancialStpRealAccountSignup + removed unused setSubmitting * fix for loading * mt5 add g * Maryia/fix: Trade modal for demo to display only STP shortcode * update branch with master * typo fix * checkbox missing issue * maltainvest * Maryia/fix: responsive CompareAccountsModal * code cleanup in packages/account/src/Components/poi-poa-docs-submitted Co-authored-by: hirad-rework Co-authored-by: yashim-deriv Co-authored-by: Yashim Wong <75345074+yashim-deriv@users.noreply.github.com> Co-authored-by: Maryia <103177211+maryia-binary@users.noreply.github.com> Co-authored-by: Matin-binary Co-authored-by: Niloofar Sadeghi <93518187+niloo-fs@users.noreply.github.com> Co-authored-by: Shayan Khaleghparast <100833613+iman-fs@users.noreply.github.com> Co-authored-by: yauheni-kryzhyk-deriv <103182683+yauheni-kryzhyk-deriv@users.noreply.github.com> Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”> Co-authored-by: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> Co-authored-by: Ali(Ako) Hosseini Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> Co-authored-by: maryia-binary Co-authored-by: Matin shafiei --- packages/account/build/webpack.config.js | 5 + .../personal-details/personal-details.jsx | 308 +++---- .../poi-poa-docs-submitted.jsx | 48 + .../idv-doc-submit-on-signup.jsx | 360 ++++++++ .../idv-doc-submit-on-signup/index.js | 3 + .../poi/poi-form-on-signup/index.js | 3 + .../poi-form-on-signup/poi-form-on-signup.jsx | 48 + .../src/Configs/proof-of-identity-config.js | 15 + .../two-factor-authentication.jsx | 9 +- .../Verification/Helpers/verification.js | 9 + .../ProofOfIdentity/onfido-sdk-view.jsx | 1 + .../proof-of-identity-container-for-mt5.jsx | 100 +++ .../proof-of-identity-submission-for-mt5.jsx | 109 +++ packages/account/src/Styles/account.scss | 4 + .../account-transfer-form.jsx | 102 +-- .../src/stores/account-transfer-store.js | 26 +- .../utils/validator/__tests__/error.spec.js | 2 +- .../cfd-demo-account-display.spec.js | 183 +--- .../cfd-financial-stp-pending-dialog.spec.js | 65 -- .../cfd-personal-details-form.spec.js | 2 +- .../src/Components/__tests__/cfd-poi.spec.js | 91 +- .../cfd-real-account-display.spec.js | 334 +------ .../cfd/src/Components/cfd-account-card.tsx | 551 +++++++----- .../Components/cfd-demo-account-display.tsx | 98 +-- .../cfd-financial-stp-pending-dialog.tsx | 44 - .../Components/cfd-personal-details-form.tsx | 174 +++- packages/cfd/src/Components/cfd-poa.tsx | 115 +-- packages/cfd/src/Components/cfd-poi.tsx | 120 +-- .../Components/cfd-real-account-display.tsx | 293 ++----- packages/cfd/src/Components/props.types.ts | 38 +- .../cfd/src/Constants/cfd-shared-strings.js | 4 +- .../src/Constants/jurisdiction-contents.ts | 133 +++ ...-financial-stp-real-account-signup.spec.js | 40 +- .../Containers/cfd-dashboard-container.tsx | 17 +- packages/cfd/src/Containers/cfd-dashboard.tsx | 132 +-- .../src/Containers/cfd-dbvi-onboarding.tsx | 149 ++++ .../cfd-financial-stp-real-account-signup.tsx | 318 +++---- .../Containers/cfd-password-manager-modal.tsx | 6 +- .../cfd/src/Containers/cfd-password-modal.tsx | 228 +---- .../Containers/cfd-personal-details-modal.tsx | 195 +++++ .../Containers/cfd-reset-password-modal.tsx | 5 +- .../src/Containers/compare-accounts-modal.tsx | 132 ++- .../Containers/jurisdiction-modal-content.tsx | 826 ++++++++++++++++++ .../cfd/src/Containers/jurisdiction-modal.tsx | 354 ++++++++ ...count-opening-real-financial-stp-modal.tsx | 51 -- .../Containers/mt5-compare-table-content.tsx | 617 +++++++++++++ .../cfd/src/Containers/mt5-trade-modal.tsx | 327 +++++++ packages/cfd/src/Containers/props.types.ts | 32 +- packages/cfd/src/Helpers/constants.ts | 2 + .../Stores/Modules/CFD/Helpers/cfd-config.ts | 36 + .../cfd/src/Stores/Modules/CFD/cfd-store.js | 122 ++- packages/cfd/src/sass/cfd-dashboard.scss | 762 +++++++++++++++- packages/cfd/src/sass/cfd.scss | 30 + .../src/components/dialog/dialog.scss | 2 +- .../src/components/dropdown/dropdown.scss | 4 + .../components/icon/common/ic-docs-submit.svg | 1 + .../icon/common/ic-installation-huawei.svg | 1 + .../components/icon/common/ic-linux-logo.svg | 1 + .../components/icon/common/ic-macos-logo.svg | 1 + .../icon/common/ic-windows-logo.svg | 1 + .../components/src/components/icon/icons.js | 6 + .../src/components/icon/mt5/ic-mt5-logo.svg | 1 + .../mobile-dialog/mobile-dialog.jsx | 16 +- .../components/src/components/modal/modal.jsx | 4 +- packages/components/stories/icon/icons.js | 6 + .../deriv-real-account-required-modal.jsx | 45 + .../NotificationMessage/notification.jsx | 6 +- .../Layout/Footer/regulatory-information.jsx | 2 +- .../account-signup-modal.jsx | 234 ++--- .../validate-signup-fields.jsx | 52 ++ .../account-switcher-account-list.jsx | 75 +- .../AccountSwitcher/account-switcher.jsx | 171 ++-- .../AccountSwitcher/helpers/account-helper.js | 35 +- .../same-citizenship-modal.jsx | 53 ++ .../CitizenshipModal/set-citizenship-form.jsx | 65 ++ .../src/App/Containers/Modals/app-modals.jsx | 8 + .../PasswordSelectionModal/index.js | 1 + .../password-selection-modal.jsx | 104 +++ .../RealAccountSignup/account-wizard-form.js | 9 + .../RealAccountSignup/account-wizard.jsx | 19 +- .../Containers/app-notification-messages.jsx | 5 + packages/core/src/Constants/cfd-text.js | 8 +- packages/core/src/Stores/client-store.js | 91 +- .../core/src/Stores/notification-store.js | 27 +- packages/core/src/Stores/ui-store.js | 7 + packages/core/src/_common/base/socket_base.js | 7 + .../common/static_images/mt5_download.png | Bin 0 -> 1836 bytes .../_common/components/account-switcher.scss | 2 +- .../components/app-notification-message.scss | 4 + .../src/sass/app/modules/account-signup.scss | 27 +- .../src/sass/app/modules/set-citizenship.scss | 43 + .../src/sass/app/modules/set-residence.scss | 3 - packages/core/src/sass/details-form.scss | 6 + .../core/src/sass/real-account-signup.scss | 118 +++ packages/reports/.eslintrc.js | 2 +- packages/reports/.eslintrc.ts | 16 - packages/shared/src/styles/themes.scss | 1 + packages/shared/src/utils/cfd/cfd.js | 123 ++- .../sass/app/modules/mt5/cfd-dashboard.scss | 33 +- 99 files changed, 6585 insertions(+), 2639 deletions(-) create mode 100644 packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.jsx create mode 100644 packages/account/src/Components/poi/poi-form-on-signup/idv-doc-submit-on-signup/idv-doc-submit-on-signup.jsx create mode 100644 packages/account/src/Components/poi/poi-form-on-signup/idv-doc-submit-on-signup/index.js create mode 100644 packages/account/src/Components/poi/poi-form-on-signup/index.js create mode 100644 packages/account/src/Components/poi/poi-form-on-signup/poi-form-on-signup.jsx create mode 100644 packages/account/src/Configs/proof-of-identity-config.js create mode 100644 packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx create mode 100644 packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx delete mode 100644 packages/cfd/src/Components/__tests__/cfd-financial-stp-pending-dialog.spec.js delete mode 100644 packages/cfd/src/Components/cfd-financial-stp-pending-dialog.tsx create mode 100644 packages/cfd/src/Constants/jurisdiction-contents.ts create mode 100644 packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx create mode 100644 packages/cfd/src/Containers/cfd-personal-details-modal.tsx create mode 100644 packages/cfd/src/Containers/jurisdiction-modal-content.tsx create mode 100644 packages/cfd/src/Containers/jurisdiction-modal.tsx delete mode 100644 packages/cfd/src/Containers/mt5-account-opening-real-financial-stp-modal.tsx create mode 100644 packages/cfd/src/Containers/mt5-compare-table-content.tsx create mode 100644 packages/cfd/src/Containers/mt5-trade-modal.tsx create mode 100644 packages/components/src/components/icon/common/ic-docs-submit.svg create mode 100644 packages/components/src/components/icon/common/ic-installation-huawei.svg create mode 100644 packages/components/src/components/icon/common/ic-linux-logo.svg create mode 100644 packages/components/src/components/icon/common/ic-macos-logo.svg create mode 100644 packages/components/src/components/icon/common/ic-windows-logo.svg create mode 100644 packages/components/src/components/icon/mt5/ic-mt5-logo.svg create mode 100644 packages/core/src/App/Components/Elements/Modals/deriv-real-account-required-modal.jsx create mode 100644 packages/core/src/App/Containers/AccountSignupModal/validate-signup-fields.jsx create mode 100644 packages/core/src/App/Containers/CitizenshipModal/same-citizenship-modal.jsx create mode 100644 packages/core/src/App/Containers/CitizenshipModal/set-citizenship-form.jsx create mode 100644 packages/core/src/App/Containers/PasswordSelectionModal/index.js create mode 100644 packages/core/src/App/Containers/PasswordSelectionModal/password-selection-modal.jsx create mode 100644 packages/core/src/public/images/common/static_images/mt5_download.png create mode 100644 packages/core/src/sass/app/modules/set-citizenship.scss delete mode 100644 packages/reports/.eslintrc.ts diff --git a/packages/account/build/webpack.config.js b/packages/account/build/webpack.config.js index 213d321dc78f..f1d3e8430bfe 100644 --- a/packages/account/build/webpack.config.js +++ b/packages/account/build/webpack.config.js @@ -55,6 +55,11 @@ module.exports = function (env) { 'text-container': 'Components/text-container', 'terms-of-use': 'Components/terms-of-use', 'terms-of-use-config': 'Configs/terms-of-use-config', + 'proof-of-identity-config': 'Configs/proof-of-identity-config', + 'proof-of-identity-form-on-signup': 'Components/poi/poi-form-on-signup', + 'proof-of-identity-containerfor-mt5': + 'Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5', + 'poi-poa-submitted': 'Components/poi-poa-docs-submitted/poi-poa-docs-submitted.jsx', }, mode: IS_RELEASE ? 'production' : 'development', module: { diff --git a/packages/account/src/Components/personal-details/personal-details.jsx b/packages/account/src/Components/personal-details/personal-details.jsx index 7efc280ba200..b045dae38e96 100644 --- a/packages/account/src/Components/personal-details/personal-details.jsx +++ b/packages/account/src/Components/personal-details/personal-details.jsx @@ -172,6 +172,18 @@ const PersonalDetails = ({ data-testid='personal_details_form' > + + + {is_appstore && (
@@ -408,159 +420,159 @@ const PersonalDetails = ({ )} {('tax_residence' in props.value || 'tax_identification_number' in props.value) && ( - - - {'tax_residence' in props.value && ( - - {({ field }) => ( -
- - - setFieldValue( - 'tax_residence', - value ? text : '', - true - ) - } - list_portal_id='modal_root' - data-testid='tax_residence' - /> - - - { - handleChange(e); - setFieldValue( - 'tax_residence', - e.target.value, - true - ); + + + {'tax_residence' in props.value && ( + + {({ field }) => ( +
+ + + setFieldValue( + 'tax_residence', + value ? text : '', + true + ) + } + list_portal_id='modal_root' + data-testid='tax_residence' + /> + + + { + handleChange(e); + setFieldValue( + 'tax_residence', + e.target.value, + true + ); + }} + {...field} + required + data_testid='tax_residence_mobile' + /> + +
{ + setIsTaxResidencePopoverOpen(true); + setIsTinPopoverOpen(false); + e.stopPropagation(); }} - {...field} - required - data_testid='tax_residence_mobile' - /> - -
{ - setIsTaxResidencePopoverOpen(true); - setIsTinPopoverOpen(false); - e.stopPropagation(); - }} - > - + > + +
-
- )} -
- )} - {'tax_identification_number' in props.value && ( -
- - - )} - {warning_items?.tax_identification_number && ( -
- )} - {'tax_identification_confirm' in props.value && ( - - setFieldValue( - 'tax_identification_confirm', - !values.tax_identification_confirm, - true - ) - } - value={values.tax_identification_confirm} - label={localize( - 'I hereby confirm that the tax information I provided is true and complete. I will also inform {{legal_entity_name}} about any changes to this information.', - { - legal_entity_name: getLegalEntityName('maltainvest'), + )} + {warning_items?.tax_identification_number && ( +
+ )} + {'tax_identification_confirm' in props.value && ( + + setFieldValue( + 'tax_identification_confirm', + !values.tax_identification_confirm, + true + ) } - )} - renderlabel={title => ( - - {title} - - )} - withTabIndex='0' - data-testid='tax_identification_confirm' - /> - )} - - )} + value={values.tax_identification_confirm} + label={localize( + 'I hereby confirm that the tax information I provided is true and complete. I will also inform {{legal_entity_name}} about any changes to this information.', + { + legal_entity_name: getLegalEntityName('maltainvest'), + } + )} + renderlabel={title => ( + + {title} + + )} + withTabIndex='0' + data-testid='tax_identification_confirm' + /> + )} + + )} {'account_opening_reason' in props.value && ( // TODO: [deriv-eu] Remove account opening reason once api is optional diff --git a/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.jsx b/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.jsx new file mode 100644 index 000000000000..b613f15b1107 --- /dev/null +++ b/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.jsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { Button, Icon, Text } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import IconMessageContent from 'Components/icon-message-content'; + +const PoiPoaSubmitted = ({ onClickOK, onClickYes, account_type, mt5_login_list, is_eu }) => { + const [should_show_svg_msg, setShouldShowSvgMsg] = React.useState(false); + const message = localize('Your documents were submitted successfully'); + React.useEffect(() => { + if (account_type.type && account_type.category && !is_eu) { + const svg_accounts = mt5_login_list.filter( + data => + data.market_type === account_type.type && + data.landing_company_short === 'svg' && + data.account_type === 'real' + ); + if (!svg_accounts.length) { + setShouldShowSvgMsg(true); + } + } + }, []); + const SVGRoutingData = () => ( + <> + + {localize('Meanwhile, do you want to explore other accounts?')} + +
+
+ + ); + return ( + } + className='poi-poa-submitted' + > + {should_show_svg_msg ? ( + + ) : ( +
+ )} + {acc && is_logged_in && !is_web_terminal_unsupported && ( + + )} +
+
+ ))} + {existing_data?.login && + is_logged_in && + platform === CFD_PLATFORMS.MT5 && + !existing_accounts_data?.length && + type.category === 'demo' && ( +
+ {(existing_data as TTradingPlatformAccounts)?.display_login && ( +
+ + {(existing_data as TTradingPlatformAccounts)?.display_login} + +
+ )} + {existing_data?.display_balance && is_logged_in && ( +
+ + + +
+ )} +
+ {existing_data && is_logged_in && ( + + )} + {existing_data && is_logged_in && !is_web_terminal_unsupported && ( + + )} +
+
+ )} + {existing_data?.login && + is_logged_in && + platform === CFD_PLATFORMS.MT5 && + type.category === 'real' && + existing_accounts_data?.map((acc, index) => ( +
+ {existing_data?.display_balance && is_logged_in && ( +
+ +
+ )} + {(acc as TTradingPlatformAccounts)?.display_login && ( +
+ + {(acc as TTradingPlatformAccounts)?.display_login} + +
+ )} + {existing_data?.display_balance && is_logged_in && ( +
+ + + + {checkMultipleSvgAcc()?.length > 1 && acc.landing_company_short === 'svg' && ( + + {getServerName(acc)} + + )} +
+ )} +
+ {existing_data && is_logged_in && ( + + )} + {existing_data && is_logged_in && !is_web_terminal_unsupported && ( + + )} +
+
+ ))} + {existing_data?.login && is_logged_in && platform === CFD_PLATFORMS.DXTRADE && (
@@ -414,58 +579,16 @@ const CFDAccountCardComponent = ({
- ) : ( -
- - - {typeof specs !== 'undefined' && - Object.keys(specs).map((spec_attribute, idx) => ( - - - - - ))} - {has_server_banner && - existing_data && - type.type === 'synthetic' && - type.category === 'real' && ( - - - - - )} - -
-

- {specs[spec_attribute].key()} -

-
-

- {specs[spec_attribute].value()} -

-
-

- -

-
-

- {getServerName(existing_data)} -

-
-
)} - - {((!existing_data && commission_message) || !is_logged_in) && ( -
- - {commission_message} - -
- )} - {existing_data && is_logged_in && ( + {((!existing_data && commission_message) || !is_logged_in) && + platform === CFD_PLATFORMS.DXTRADE && ( +
+ + {commission_message} + +
+ )} + {existing_data && is_logged_in && platform === CFD_PLATFORMS.DXTRADE && (
)} - {!existing_data && has_cfd_account && ( - - )} - {existing_data && is_logged_in && !is_web_terminal_unsupported && ( -
- - - )} + {existing_data && + is_logged_in && + !is_web_terminal_unsupported && + platform === CFD_PLATFORMS.DXTRADE && ( + + + + )} {existing_data && is_logged_in && is_web_terminal_unsupported && ( )} - {!existing_data && !has_cfd_account && is_logged_in && ( + {!existing_data && is_logged_in && (
- {should_show_trade_servers && ( + {should_show_extra_add_account_button && ( - - ({ +const CFDAccountCard = connect(({ modules: { cfd }, client }: RootStore) => ({ dxtrade_tokens: cfd.dxtrade_tokens, + isEligibleForMoreDemoMt5Svg: client.isEligibleForMoreDemoMt5Svg, + isEligibleForMoreRealMt5: client.isEligibleForMoreRealMt5, + setMT5TradeAccount: cfd.setMT5TradeAccount, }))(CFDAccountCardComponent); export { CFDAccountCard }; diff --git a/packages/cfd/src/Components/cfd-demo-account-display.tsx b/packages/cfd/src/Components/cfd-demo-account-display.tsx index 88bb9afa0e6e..de4289300d2c 100644 --- a/packages/cfd/src/Components/cfd-demo-account-display.tsx +++ b/packages/cfd/src/Components/cfd-demo-account-display.tsx @@ -1,11 +1,12 @@ import React from 'react'; -import { DetailsOfEachMT5Loginid, LandingCompany } from '@deriv/api-types'; import { localize } from '@deriv/translations'; +import { CFDAccountCard } from './cfd-account-card'; import { general_messages } from '../Constants/cfd-shared-strings'; import specifications, { TSpecifications } from '../Constants/cfd-specifications'; import Loading from '../templates/_common/components/loading'; -import { CFDAccountCard } from './cfd-account-card'; +import { DetailsOfEachMT5Loginid, LandingCompany } from '@deriv/api-types'; import { TTradingPlatformAccounts } from './props.types'; +import { TObjectCFDAccount } from 'Containers/cfd-dashboard'; type TStandPoint = { financial_company: string; @@ -32,20 +33,17 @@ type TCFDDemoAccountDisplayProps = { is_logged_in: boolean; isSyntheticCardVisible: (account_category: string) => boolean; isFinancialCardVisible: () => boolean; - isFinancialStpCardVisible: () => boolean; - onSelectAccount: (objCFDAccount: { category: string; type: string; set_password?: number }) => void; + onSelectAccount: (objCFDAccount: TObjectCFDAccount) => void; openAccountTransfer: ( data: DetailsOfEachMT5Loginid | TTradingPlatformAccounts, meta: TOpenAccountTransferMeta ) => void; platform: string; - current_list: Array & { - [key: string]: DetailsOfEachMT5Loginid | TTradingPlatformAccounts; - }; - has_cfd_account: boolean; + current_list: Record; openPasswordManager: (login?: string, title?: string, group?: string, type?: string, server?: string) => void; residence: string; landing_companies?: LandingCompany; + toggleMT5TradeModal: () => void; }; const CFDDemoAccountDisplay = ({ @@ -59,14 +57,13 @@ const CFDDemoAccountDisplay = ({ is_logged_in, isSyntheticCardVisible, isFinancialCardVisible, - isFinancialStpCardVisible, onSelectAccount, openAccountTransfer, platform, current_list, - has_cfd_account, openPasswordManager, residence, + toggleMT5TradeModal, }: TCFDDemoAccountDisplayProps) => { const is_eu_user = (is_logged_in && is_eu) || (!is_logged_in && is_eu_country); @@ -77,10 +74,23 @@ const CFDDemoAccountDisplay = ({ onSelectAccount({ category: 'demo', type: 'financial', + platform, }); } }; + const financial_accounts_data = () => { + const acc = Object.keys(current_list).some(key => key.startsWith(`${platform}.demo.financial`)) + ? Object.keys(current_list) + .filter(key => key.startsWith(`${platform}.demo.financial`)) + .reduce((_acc, cur) => { + _acc.push(current_list[cur]); + return _acc; + }, [] as DetailsOfEachMT5Loginid[]) + : undefined; + return acc; + }; + const financial_specs = React.useMemo(() => { const should_show_eu = (is_logged_in && is_eu) || (!is_logged_in && is_eu_country); if (residence === 'au') { @@ -100,7 +110,6 @@ const CFDDemoAccountDisplay = ({
{isSyntheticCardVisible('demo') && ( key.startsWith(`${platform}.demo.synthetic`) @@ -121,6 +130,7 @@ const CFDDemoAccountDisplay = ({ onSelectAccount({ category: 'demo', type: 'synthetic', + platform, }) } onPasswordManager={openPasswordManager} @@ -139,16 +149,16 @@ const CFDDemoAccountDisplay = ({ } platform={platform} descriptor={localize( - 'Trade CFDs on our synthetic indices that simulate real-world market movement.' + 'Trade CFDs on our synthetic indices that simulate real-world market movements.' )} specs={specifications[platform as keyof TSpecifications].real_synthetic_specs} has_banner + toggleMT5TradeModal={toggleMT5TradeModal} /> )} {isFinancialCardVisible() && ( - key.startsWith(`${platform}.demo.financial@`) - ) || '' - ] - } + existing_accounts_data={financial_accounts_data()} commission_message={localize('No commission')} onSelectAccount={openCFDAccount} onPasswordManager={openPasswordManager} @@ -172,7 +176,7 @@ const CFDDemoAccountDisplay = ({ openAccountTransfer( current_list[ Object.keys(current_list).find((key: string) => - key.startsWith(`${platform}.demo.financial@`) + key.startsWith(`${platform}.demo.financial`) ) || '' ], { @@ -185,55 +189,7 @@ const CFDDemoAccountDisplay = ({ descriptor={general_messages.getFinancialAccountDescriptor(platform, is_eu_user)} specs={financial_specs} has_banner - /> - )} - {isFinancialStpCardVisible() && ( - - key.startsWith(`${platform}.demo.financial_stp@`) - ) || '' - ] - } - commission_message={localize('No commission')} - onSelectAccount={() => - onSelectAccount({ - category: 'demo', - type: 'financial_stp', - }) - } - onPasswordManager={openPasswordManager} - onClickFund={() => - openAccountTransfer( - current_list[ - Object.keys(current_list).find((key: string) => - key.startsWith(`${platform}.demo.financial_stp@`) - ) || '' - ], - { - category: 'demo', - type: 'financial_stp', - } - ) - } - descriptor={localize( - 'Trade popular currency pairs and cryptocurrencies with straight-through processing order (STP).' - )} - specs={ - (specifications as TSpecifications)[platform as keyof TSpecifications].demo_financial_stp_specs - } - platform={platform} - has_banner + toggleMT5TradeModal={toggleMT5TradeModal} /> )}
diff --git a/packages/cfd/src/Components/cfd-financial-stp-pending-dialog.tsx b/packages/cfd/src/Components/cfd-financial-stp-pending-dialog.tsx deleted file mode 100644 index 7b214a528366..000000000000 --- a/packages/cfd/src/Components/cfd-financial-stp-pending-dialog.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import { Modal, Button } from '@deriv/components'; -import { Localize, localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; -import { TCFDFinancialStpPendingDialog } from './props.types'; -import RootStore from 'Stores/index'; - -const CFDFinancialStpPendingDialog = ({ - enableApp, - disableApp, - toggleModal, - is_cfd_pending_dialog_open, - is_fully_authenticated, -}: TCFDFinancialStpPendingDialog) => ( - - - {is_fully_authenticated ? ( - - ) : ( - - )} - - -
@@ -636,6 +642,15 @@ const CFDDashboard = (props: TCFDDashboardProps) => { > + {platform === CFD_PLATFORMS.MT5 && ( + + + + )}
@@ -643,11 +658,11 @@ const CFDDashboard = (props: TCFDDashboardProps) => { - {platform === CFD_PLATFORMS.MT5 && ( - - - - + {platform === CFD_PLATFORMS.MT5 && is_logged_in && ( + <> + + + )} & { + market_type?: 'financial' | 'gaming'; +}; +type TVerificationModalProps = { + disableApp: () => void; + enableApp: () => void; + is_cfd_verification_modal_visible: boolean; + toggleCFDVerificationModal: () => void; + account_type: { + type: string; + category: string; + }; + mt5_login_list: TExtendedDetailsOfEachMT5Loginid[]; + toggleJurisdictionModal: () => void; + jurisdiction_selected_shortcode: string; + is_eu: boolean; +}; + +const CFDDbViOnBoarding = ({ + disableApp, + enableApp, + is_cfd_verification_modal_visible, + toggleCFDVerificationModal, + account_type, + mt5_login_list, + toggleJurisdictionModal, + jurisdiction_selected_shortcode, + is_eu, +}: TVerificationModalProps) => { + const [showSubmittedModal, setShowSubmittedModal] = React.useState(false); + const [is_loading, setIsLoading] = React.useState(false); + const handleOpenJurisditionModal = () => { + toggleCFDVerificationModal(); + toggleJurisdictionModal(); + }; + const getAccountStatusFromAPI = () => { + WS.authorized.getAccountStatus().then((response: AccountStatusResponse) => { + const { get_account_status } = response; + setIsLoading(false); + if (get_account_status?.authentication) { + const identity_status = get_account_status?.authentication?.identity?.status; + const document_status = get_account_status?.authentication?.document?.status; + const { need_poi_for_vanuatu } = getIdentityStatusInfo(get_account_status); + if (jurisdiction_selected_shortcode === 'vanuatu' && need_poi_for_vanuatu) { + setShowSubmittedModal(false); + } else if ( + (identity_status === 'pending' || identity_status === 'verified') && + (document_status === 'pending' || document_status === 'verified') + ) { + setShowSubmittedModal(true); + } else { + setShowSubmittedModal(false); + } + } + }); + }; + React.useEffect(() => { + if (is_cfd_verification_modal_visible) { + getAccountStatusFromAPI(); + setIsLoading(true); + setShowSubmittedModal(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [is_cfd_verification_modal_visible]); + + return is_loading ? ( + + ) : ( + }> + + getAccountStatusFromAPI()} + exit_classname='cfd-modal--custom-exit' + > + {showSubmittedModal ? ( + + ) : ( + { + setShowSubmittedModal(true); + }} + /> + )} + + + + + {showSubmittedModal ? ( + + ) : ( + { + setShowSubmittedModal(true); + }} + /> + )} + + + + ); +}; + +export default connect(({ client, modules, ui }: RootStore) => ({ + disableApp: ui.disableApp, + enableApp: ui.enableApp, + is_cfd_verification_modal_visible: modules.cfd.is_cfd_verification_modal_visible, + toggleCFDVerificationModal: modules.cfd.toggleCFDVerificationModal, + account_type: modules.cfd.account_type, + mt5_login_list: client.mt5_login_list, + toggleJurisdictionModal: modules.cfd.toggleJurisdictionModal, + jurisdiction_selected_shortcode: modules.cfd.jurisdiction_selected_shortcode, + is_eu: client.is_eu, +}))(CFDDbViOnBoarding); diff --git a/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx b/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx index fa2fc2c7fb96..995a9c877654 100644 --- a/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx +++ b/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx @@ -1,12 +1,11 @@ import React from 'react'; -import { FormProgress, DesktopWrapper, MobileWrapper, Div100vhContainer } from '@deriv/components'; -import { getPropertyValue, isDesktop, WS } from '@deriv/shared'; -import { localize, Localize } from '@deriv/translations'; +import { Div100vhContainer } from '@deriv/components'; +import { isDesktop, getIdentityStatusInfo } from '@deriv/shared'; +import { localize } from '@deriv/translations'; import { connect } from 'Stores/connect'; -import CFDPOA from '../Components/cfd-poa'; -import CFDPersonalDetailsForm from '../Components/cfd-personal-details-form'; +import CFDPOA, { TCFDPOAProps } from '../Components/cfd-poa'; import CFDPOI from '../Components/cfd-poi'; -import { LandingCompany, ResidenceList, GetSettings, StatesList } from '@deriv/api-types'; +import { LandingCompany, ResidenceList, GetSettings, StatesList, GetAccountStatus } from '@deriv/api-types'; import RootStore from 'Stores/index'; type TAuthenticationStatus = { document_status: string; identity_status: string }; @@ -21,12 +20,6 @@ type TRemoveNotificationMessage = { should_show_again: boolean; }; -type TIndexLookupObject = { - CFDPersonalDetailsForm: number; - CFDPOI: number; - CFDPOA: number; -}; - type TGetSettings = GetSettings & { upload_file?: string; poi_state?: string; @@ -34,220 +27,146 @@ type TGetSettings = GetSettings & { type TCFDFinancialStpRealAccountSignupProps = { addNotificationByKey: (key: string) => void; - authentication_status: () => TAuthenticationStatus; + authentication_status: TAuthenticationStatus; get_settings: TGetSettings; client_email: string; is_fully_authenticated: boolean; landing_company: LandingCompany; - openPendingDialog: () => void; refreshNotifications: () => void; removeNotificationMessage: () => void; removeNotificationByKey: (args: TRemoveNotificationMessage) => void; residence_list: ResidenceList; states_list: StatesList; storeProofOfAddress: TStoreProofOfAddressArgs; - toggleModal: () => void; + fetchStatesList: () => void; + account_status: GetAccountStatus; + onFinish: () => void; + jurisdiction_selected_shortcode: string; + needs_poi_for_vanuatu: boolean; }; -type TSetSubmiting = (isSubmitting: boolean) => void; - -type TNextStep = (submitting: TSetSubmiting) => void; +type TNextStep = (index: number, value: { [key: string]: string | undefined }) => void; type TItemsState = { header: { [key: string]: string }; - body: typeof CFDPersonalDetailsForm | typeof CFDPOI | typeof CFDPOA; + body: ({ onSave, index, onSubmit, refreshNotifications, ...props }: TCFDPOAProps) => JSX.Element; form_value: { [key: string]: string | undefined }; - props: Array; -}; - -type TItemsProps = - | 'residence_list' - | 'is_fully_authenticated' - | 'landing_company' - | 'addNotificationByKey' - | 'authentication_status' - | 'refreshNotifications' - | 'removeNotificationMessage' - | 'removeNotificationByKey' - | 'states_list' - | 'get_settings' - | 'storeProofOfAddress'; - -type TgetCurrentProps = 'header' | 'body' | 'props' | 'form_value'; -const index_lookup: TIndexLookupObject = { - CFDPersonalDetailsForm: 0, - CFDPOI: 1, - CFDPOA: 2, + forwarded_props: Array>; }; const CFDFinancialStpRealAccountSignup = (props: TCFDFinancialStpRealAccountSignupProps) => { - const { refreshNotifications } = props; - const [step, setStep] = React.useState(0); - const [form_error, setFormError] = React.useState(''); - const [is_loading, setIsLoading] = React.useState(false); - const [items, setItems] = React.useState([ - { - header: { - active_title: localize('Complete your personal details'), - title: localize('Personal details'), - }, - body: CFDPersonalDetailsForm, - form_value: { - citizen: '', - tax_residence: '', - tax_identification_number: '', - account_opening_reason: '', - }, - props: ['residence_list', 'is_fully_authenticated', 'landing_company'], - }, - { - header: { - active_title: localize('Complete your proof of identity'), - title: localize('Proof of identity'), - }, - body: CFDPOI, - form_value: { - poi_state: 'unknown', - }, - props: [ - 'addNotificationByKey', - 'authentication_status', - 'refreshNotifications', - 'removeNotificationMessage', - 'removeNotificationByKey', - ], + const { refreshNotifications, authentication_status, fetchStatesList } = props; + const [step, setStep] = React.useState(0); + const [form_error, setFormError] = React.useState(''); + const state_index = step; + const height = 'auto'; + let is_mounted = React.useRef(true).current; + const { need_poi_for_vanuatu } = getIdentityStatusInfo(props.account_status); + const poi_config: TItemsState = { + header: { + active_title: localize('Complete your proof of identity'), + title: localize('Proof of identity'), }, - { - header: { - active_title: localize('Complete your proof of address'), - title: localize('Proof of address'), - }, - body: CFDPOA, - form_value: { - address_line_1: props.get_settings.address_line_1, - address_line_2: props.get_settings.address_line_2, - address_city: props.get_settings.address_city, - address_state: props.get_settings.address_state, - address_postcode: props.get_settings.address_postcode, - upload_file: '', - }, - props: ['states_list', 'get_settings', 'storeProofOfAddress', 'refreshNotifications'], + body: CFDPOI, + form_value: { + poi_state: 'unknown', }, - ]); - - const state_index = step; - - const clearError = () => { - setFormError(''); + forwarded_props: [ + 'addNotificationByKey', + 'authentication_status', + 'refreshNotifications', + 'removeNotificationMessage', + 'removeNotificationByKey', + 'jurisdiction_selected_shortcode', + ], }; - const nextStep: TNextStep = () => { - clearError(); - if (step + 1 < items.length) { - setStep(step + 1); - } else { - props.openPendingDialog(); - props.toggleModal(); - } + const poa_config: TItemsState = { + header: { + active_title: localize('Complete your proof of address'), + title: localize('Proof of address'), + }, + body: CFDPOA, + form_value: { + address_line_1: props.get_settings.address_line_1, + address_line_2: props.get_settings.address_line_2, + address_city: props.get_settings.address_city, + address_state: props.get_settings.address_state, + address_postcode: props.get_settings.address_postcode, + upload_file: '', + }, + forwarded_props: ['states_list', 'get_settings', 'storeProofOfAddress', 'refreshNotifications'], }; - const prevStep = () => { - setStep(step - 1); - setFormError(''); - }; - const updateValue = async ( - index: number, - value: { [key: string]: string | undefined }, - setSubmitting: TSetSubmiting, - is_dirty = true - ) => { - if (is_dirty && index_lookup.CFDPersonalDetailsForm === index) { - // Set account settings - const data = await WS.setSettings(value); - if (data.error) { - setFormError(data.error.message); - setSubmitting(false); - return; - } - initiatePersonalDetails(setSubmitting); + const should_show_poi = () => { + if (props.jurisdiction_selected_shortcode === 'vanuatu' && need_poi_for_vanuatu) { + return true; } - if (index === 0) await WS.triggerMt5DryRun({ email: props.client_email }); - saveFormData(index, value); - nextStep(setSubmitting); + return !( + authentication_status.identity_status === 'pending' || authentication_status.identity_status === 'verified' + ); }; + const should_show_poa = !( + authentication_status.document_status === 'pending' || authentication_status.document_status === 'verified' + ); + const verification_configs = [...(should_show_poi() ? [poi_config] : []), ...(should_show_poa ? [poa_config] : [])]; - const initiatePersonalDetails = async (setSubmitting?: TSetSubmiting) => { - // force request to update settings cache since settings have been updated - const response = await WS.authorized.storage.getSettings(); + const [items, setItems] = React.useState(verification_configs); - if (response.error) { - setFormError(response.error.message); - if (typeof setSubmitting === 'function') { - setSubmitting(false); - } - return; - } - - const cloned: Array = Object.assign([], items); - if (response.get_settings.citizen) { - cloned[index_lookup.CFDPersonalDetailsForm].form_value.citizen = transform(response.get_settings.citizen); - } - if (response.get_settings.tax_residence) { - cloned[index_lookup.CFDPersonalDetailsForm].form_value.tax_residence = transform( - response.get_settings.tax_residence - ); - } - if (response.get_settings.tax_identification_number) { - cloned[index_lookup.CFDPersonalDetailsForm].form_value.tax_identification_number = - response.get_settings.tax_identification_number; - } - if (response.get_settings.account_opening_reason) { - cloned[index_lookup.CFDPersonalDetailsForm].form_value.account_opening_reason = - response.get_settings.account_opening_reason; - } - setItems(cloned); + const clearError = () => { + setFormError(''); }; React.useEffect(() => { refreshNotifications(); }, [items, refreshNotifications]); - const transform = (value: string | undefined) => { - const [result] = props.residence_list.filter(item => item.value === value); - return getPropertyValue(result, ['text']) || value; - }; - React.useEffect(() => { - if (state_index === index_lookup.CFDPersonalDetailsForm) { - setIsLoading(true); - initiatePersonalDetails().then(() => { - setIsLoading(false); - }); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + fetchStatesList(); + }, [fetchStatesList]); - const getCurrent = (key?: TgetCurrentProps) => { - return key ? items[state_index][key] : items[state_index]; + const unmount = () => { + is_mounted = false; + props.onFinish(); }; const saveFormData = (index: number, value: { [key: string]: string | undefined }) => { - const cloned_items: Array = Object.assign([], items); + if (!is_mounted) return; // avoiding state update on unmounted component + const cloned_items: TItemsState[] = [...items]; cloned_items[index].form_value = value; - if (state_index === index_lookup.CFDPersonalDetailsForm) { - cloned_items[index_lookup.CFDPersonalDetailsForm].form_value.citizen = transform(value.citizen); - - cloned_items[index_lookup.CFDPersonalDetailsForm].form_value.tax_residence = transform(value.tax_residence); - } setItems(cloned_items); }; - const BodyComponent = getCurrent('body') as TItemsState['body']; + + const nextStep: TNextStep = (index, value) => { + clearError(); + if (step + 1 < items.length) { + saveFormData(index, value); + setStep(step + 1); + } else unmount(); + }; + + const prevStep = () => { + if (step - 1 >= 0) { + setStep(step - 1); + setFormError(''); + } else unmount(); + }; + + const getCurrent = (key?: keyof TItemsState) => { + return key ? items[state_index][key] : items[state_index]; + }; + + const BodyComponent = getCurrent('body') as typeof CFDPOI & typeof CFDPOA; const form_value = getCurrent('form_value'); - const passthrough = ((getCurrent('props') || []) as TItemsState['props']).reduce((arr, item) => { - return Object.assign(arr, { [item]: props[item as keyof TCFDFinancialStpRealAccountSignupProps] }); - }, {}); - const height = 'auto'; + const passthrough = ((getCurrent('forwarded_props') || []) as TItemsState['forwarded_props']).reduce( + (forwarded_prop, item) => { + return Object.assign(forwarded_prop, { + [item]: props[item], + }); + }, + {} + ); return ( -
- {getCurrent() && ( - <> - - - - -
-

- -

- {items[step].header.active_title && ( -

- {items[step].header.active_title} -

- )} -
-
- - )} -
-
+
({ email: client.email, enableApp: ui.enableApp, disableApp: ui.disableApp, + is_eu: client.is_eu, sendVerifyEmail: cfd.sendVerifyEmail, }))(CFDPasswordManagerModal); diff --git a/packages/cfd/src/Containers/cfd-password-modal.tsx b/packages/cfd/src/Containers/cfd-password-modal.tsx index 9468a8b7cd4b..8192c33fc618 100644 --- a/packages/cfd/src/Containers/cfd-password-modal.tsx +++ b/packages/cfd/src/Containers/cfd-password-modal.tsx @@ -2,13 +2,7 @@ import { Formik, FormikErrors, FormikHelpers } from 'formik'; import React from 'react'; import { RouteComponentProps, withRouter } from 'react-router'; import { SentEmailModal } from '@deriv/account'; -import { - DetailsOfEachMT5Loginid, - DetailsOfEachServer, - GetAccountStatus, - LandingCompany, - Mt5NewAccount, -} from '@deriv/api-types'; +import { DetailsOfEachMT5Loginid, GetAccountStatus, LandingCompany, Mt5NewAccount } from '@deriv/api-types'; import RootStore from 'Stores/index'; import { getMtCompanies, TMtCompanies } from 'Stores/Modules/CFD/Helpers/cfd-config'; import { @@ -18,7 +12,6 @@ import { Modal, PasswordInput, PasswordMeter, - RadioGroup, Text, MultiStep, } from '@deriv/components'; @@ -41,7 +34,6 @@ import { connect } from 'Stores/connect'; import ChangePasswordConfirmation from './cfd-change-password-confirmation'; export type TCFDPasswordFormValues = { password: string }; -export type TCFDServerFormValues = { server: string }; type TExtendedDetailsOfEachMT5Loginid = Omit & { market_type?: 'synthetic' | 'financial' | 'gaming'; @@ -51,8 +43,6 @@ type TOnSubmitPassword = (values: TCFDPasswordFormValues, actions: FormikHelpers type TPasswordModalHeaderProps = { should_set_trading_password: boolean; - should_show_server_form: boolean; - account_title: string; is_password_reset_error: boolean; platform: string; has_mt5_account?: boolean; @@ -99,27 +89,9 @@ type TCFDPasswordFormProps = TCFDPasswordFormReusedProps & { onCancel: () => void; onForgotPassword: () => void; should_set_trading_password: boolean; - should_show_server_form: boolean; submitPassword: TOnSubmitPassword; }; -type TCFDServerModalWarningProps = { - show_warning: boolean; - platform: string; -}; - -type TCFDServerFormProps = { - mt5_trading_servers: DetailsOfEachServer[]; - mt5_login_list: TExtendedDetailsOfEachMT5Loginid[]; - account_title: string; - closeModal: () => void; - form_error?: string; - submitMt5Server: (server: string) => void; - platform: string; - has_error: boolean; - validateServer?: (values: TCFDServerFormValues) => FormikErrors; -}; - type TCFDPasswordModalProps = RouteComponentProps & { account_title: string; account_type: { @@ -134,35 +106,26 @@ type TCFDPasswordModalProps = RouteComponentProps & { form_error?: string; getAccountStatus: (platform: string) => void; is_eu: boolean; - is_eu_country: boolean; is_fully_authenticated: boolean; - is_logged_in: boolean; is_cfd_password_modal_enabled: boolean; is_cfd_success_dialog_enabled: boolean; is_dxtrade_allowed: boolean; platform: string; has_cfd_error: boolean; - has_suspended_account: boolean; landing_companies: LandingCompany; mt5_login_list: TExtendedDetailsOfEachMT5Loginid[]; cfd_new_account: Mt5NewAccount; setCFDSuccessDialog: (value: boolean) => void; setMt5Error: (state: boolean, obj?: Error) => void; - submitMt5Password: ( - values: TCFDPasswordFormValues & { server?: string }, - actions: FormikHelpers - ) => void; + submitMt5Password: (values: TCFDPasswordFormValues, actions: FormikHelpers) => void; submitCFDPassword: ( values: TCFDPasswordFormValues & { platform?: string }, actions: FormikHelpers ) => void; - mt5_trading_servers: DetailsOfEachServer[]; }; const PasswordModalHeader = ({ should_set_trading_password, - should_show_server_form, - account_title, is_password_reset_error, platform, }: TPasswordModalHeaderProps) => { @@ -177,7 +140,7 @@ const PasswordModalHeader = ({ return ( - {!should_show_server_form && !should_set_trading_password && !is_password_reset_error && ( + {!should_set_trading_password && !is_password_reset_error && ( )} - {!should_show_server_form && is_password_reset_error && } - {should_show_server_form && ( - - )} + {is_password_reset_error && } ); }; @@ -249,7 +204,7 @@ const IconType = React.memo(({ platform, type, is_eu }: TIconTypeProps) => { return ; case 'financial': if (is_eu) { - return ; + return ; } return ; default: @@ -258,17 +213,10 @@ const IconType = React.memo(({ platform, type, is_eu }: TIconTypeProps) => { }); IconType.displayName = 'IconType'; -const getCancelButtonLabel = ({ - should_set_trading_password, - error_type, - should_show_server_form, -}: TCFDPasswordFormProps) => { +const getCancelButtonLabel = ({ should_set_trading_password, error_type }: TCFDPasswordFormProps) => { if (should_set_trading_password && error_type !== 'PasswordReset') { return isDesktop() ? null : localize('Cancel'); } - if (should_show_server_form) { - return localize('Back'); - } return localize('Forgot password?'); }; @@ -434,18 +382,14 @@ const CFDCreatePasswordForm = ({ const CFDPasswordForm = (props: TCFDPasswordFormProps) => { const button_label = React.useMemo(() => { - if (props.should_show_server_form) { - return localize('Next'); - } else if (props.error_type === 'PasswordReset') { + if (props.error_type === 'PasswordReset') { return localize('Try later'); } return localize('Add account'); - }, [props.should_show_server_form, props.error_type]); + }, [props.error_type]); const has_cancel_button = - props.should_show_server_form || - (isDesktop() ? !props.should_set_trading_password : true) || - props.error_type === 'PasswordReset'; + (isDesktop() ? !props.should_set_trading_password : true) || props.error_type === 'PasswordReset'; const cancel_button_label = getCancelButtonLabel(props); @@ -590,104 +534,6 @@ const CFDPasswordForm = (props: TCFDPasswordFormProps) => { ); }; -const CFDServerModalWarning = ({ show_warning = true, platform }: TCFDServerModalWarningProps) => { - if (!show_warning) return null; - return ( -
- - - -
- ); -}; - -const CFDServerForm = ({ ...props }: TCFDServerFormProps) => { - const available_servers = React.useMemo(() => { - return [...props.mt5_trading_servers] - .map(server => { - const geolocation_sequence = server.geolocation?.sequence === 1 ? '' : server.geolocation?.sequence; - const message_to_client = server.disabled ? `(${server.message_to_client})` : ''; - // Transform properties to support radiogroup - return { - ...server, - ...{ - label: `${server.geolocation?.region} ${geolocation_sequence} ${message_to_client}`, - value: server.id, - disabled: server.disabled, - }, - }; - }) - .sort(a => (a.recommended ? -1 : 1)) - .sort((a, b) => (a.disabled ? a.disabled : 0) - (b.disabled ? b.disabled : 0)); - }, [props.mt5_trading_servers]); - - return ( - - - !server.disabled)?.id ?? '', - }} - validate={props.validateServer} - onSubmit={values => props.submitMt5Server(values.server)} - > - {({ handleSubmit, setFieldValue, errors, values, isSubmitting }) => ( -
-
-
-
- !server.disabled)?.id} - onToggle={(e: React.ChangeEvent) => { - e.persist(); - setFieldValue('server', e.target.value); - }} - > - {available_servers.map(item => ( - - ))} - -
-
-
- 0} - has_cancel - cancel_label={localize('Cancel')} - onCancel={props.closeModal} - is_absolute={isMobile()} - is_loading={isSubmitting} - label={localize('Next')} - form_error={props.form_error} - /> - - )} -
-
- ); -}; - const CFDPasswordModal = ({ account_title, account_type, @@ -700,15 +546,12 @@ const CFDPasswordModal = ({ getAccountStatus, history, is_eu, - is_eu_country, is_fully_authenticated, - is_logged_in, is_cfd_password_modal_enabled, is_cfd_success_dialog_enabled, is_dxtrade_allowed, platform, has_cfd_error, - has_suspended_account, landing_companies, mt5_login_list, cfd_new_account, @@ -716,9 +559,7 @@ const CFDPasswordModal = ({ setMt5Error, submitMt5Password, submitCFDPassword, - mt5_trading_servers, }: TCFDPasswordModalProps) => { - const [server, setServer] = React.useState(''); const [is_password_modal_exited, setPasswordModalExited] = React.useState(true); const is_bvi = landing_companies?.mt_financial_company?.financial_stp?.shortcode === 'bvi'; @@ -758,7 +599,6 @@ const CFDPasswordModal = ({ const closeDialogs = () => { setCFDSuccessDialog(false); setMt5Error(false); - setTimeout(() => setServer(''), 300); // To prevent flashing on modal transitions }; const closeModal = () => { @@ -809,7 +649,6 @@ const CFDPasswordModal = ({ submitMt5Password( { ...values, - server, }, actions ); @@ -830,34 +669,20 @@ const CFDPasswordModal = ({ const should_show_sent_email_modal = is_sent_email_modal_open && is_password_modal_exited; const is_real_financial_stp = [account_type.category, account_type.type].join('_') === 'real_financial_stp'; - const is_real_synthetic = [account_type.category, account_type.type].join('_') === 'real_synthetic'; - const should_show_server_form = React.useMemo(() => { - return ( - (is_logged_in ? !is_eu : !is_eu_country) && - is_real_synthetic && - mt5_login_list.some( - item => - item.account_type === 'real' && (item.market_type === 'gaming' || item.market_type === 'synthetic') - ) && - !server && - platform === CFD_PLATFORMS.MT5 - ); - }, [is_eu, is_eu_country, is_logged_in, is_real_synthetic, server, mt5_login_list, platform]); const should_show_password_modal = React.useMemo(() => { if (should_show_password) { - if (should_show_server_form) return isDesktop(); return should_set_trading_password ? true : isDesktop(); } return false; - }, [should_set_trading_password, should_show_password, should_show_server_form]); + }, [should_set_trading_password, should_show_password]); const should_show_password_dialog = React.useMemo(() => { if (should_show_password) { - if (should_show_server_form || !should_set_trading_password) return isMobile(); + if (!should_set_trading_password) return isMobile(); } return false; - }, [should_set_trading_password, should_show_password, should_show_server_form]); + }, [should_set_trading_password, should_show_password]); const needs_poi = is_eu && !is_fully_authenticated; @@ -871,12 +696,6 @@ const CFDPasswordModal = ({ return localize('Continue'); }, [account_type, needs_poi]); - React.useEffect(() => { - if ((!is_password_error && !is_password_reset && has_cfd_error) || is_cfd_success_dialog_enabled) { - setServer(''); - } - }, [has_cfd_error, is_cfd_success_dialog_enabled, is_password_error, is_password_reset]); - const cfd_password_form = ( ); - const cfd_server_form = ( - - ); - const password_modal = ( ( @@ -931,7 +735,7 @@ const CFDPasswordModal = ({ onEntered={() => setPasswordModalExited(false)} width={isMobile() ? '32.8rem' : 'auto'} > - {should_show_server_form ? cfd_server_form : cfd_password_form} + {cfd_password_form} ); @@ -944,15 +748,13 @@ const CFDPasswordModal = ({ wrapper_classname='cfd-password-modal' > - {should_show_server_form ? cfd_server_form : cfd_password_form} + {cfd_password_form} ); diff --git a/packages/cfd/src/Containers/cfd-personal-details-modal.tsx b/packages/cfd/src/Containers/cfd-personal-details-modal.tsx new file mode 100644 index 000000000000..5628a567bd14 --- /dev/null +++ b/packages/cfd/src/Containers/cfd-personal-details-modal.tsx @@ -0,0 +1,195 @@ +import React from 'react'; +import { Modal, MobileDialog, DesktopWrapper, MobileWrapper, Div100vhContainer, Text } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; +import { TCFDPersonalDetailsModalProps } from './props.types'; +import CFDPersonalDetailsForm from '../Components/cfd-personal-details-form'; +import { getPropertyValue, isDesktop, WS } from '@deriv/shared'; +import { GetSettings } from '@deriv/api-types'; + +type TFormValues = { [key: string]: string }; +type TSetSubmiting = (isSubmitting: boolean) => void; + +const CFDPersonalDetailsModal = ({ + account_settings, + disableApp, + enableApp, + getChangeableFields, + is_fully_authenticated, + is_open, + landing_company, + openPasswordModal, + toggleCFDPersonalDetailsModal, + toggleJurisdictionModal, + residence_list, + setAccountSettings, +}: TCFDPersonalDetailsModalProps) => { + const [form_error, setFormError] = React.useState(''); + const [is_loading, setIsLoading] = React.useState(false); + const [form_values, setFormValues] = React.useState({ + citizen: '', + place_of_birth: '', + tax_residence: '', + tax_identification_number: '', + account_opening_reason: '', + }); + + const initiatePersonalDetails = async (setSubmitting?: TSetSubmiting) => { + // force request to update settings cache since settings have been updated + let get_settings_response: GetSettings; + if (!account_settings) { + const response = await WS.authorized.storage.getSettings(); + + if (response.error) { + setFormError(response.error.message); + if (typeof setSubmitting === 'function') { + setSubmitting(false); + } + return; + } + get_settings_response = response.get_settings; + } else { + get_settings_response = account_settings; + } + + const { citizen, place_of_birth, tax_residence, tax_identification_number, account_opening_reason } = + get_settings_response; + + setFormValues({ + ...form_values, + citizen: transform(citizen) || '', + place_of_birth: transform(place_of_birth) || '', + tax_residence: transform(tax_residence) || '', + tax_identification_number: tax_identification_number || '', + account_opening_reason: account_opening_reason || '', + }); + }; + + React.useEffect(() => { + if (is_open) { + setIsLoading(true); + initiatePersonalDetails().then(() => { + setIsLoading(false); + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [is_open]); + + const transform = (value: unknown) => { + const [result] = residence_list.filter(item => item.value === value); + return getPropertyValue(result, ['text']) || value; + }; + + const saveFormData = (_index: number, value: TFormValues) => { + setFormValues({ + ...value, + citizen: transform(value.citizen), + place_of_birth: transform(value.place_of_birth), + tax_residence: transform(value.tax_residence), + }); + }; + + const prevStep = () => { + setFormError(''); + toggleCFDPersonalDetailsModal(); + toggleJurisdictionModal(); + }; + + const updateValue = async (index: number, value: TFormValues, setSubmitting: TSetSubmiting, is_dirty = true) => { + if (is_dirty) { + // Set account settings + const data = await WS.setSettings(value); + if (data.error) { + setFormError(data.error.message); + setSubmitting(false); + return; + } + initiatePersonalDetails(setSubmitting); + } + saveFormData(index, value); + toggleCFDPersonalDetailsModal(); + setAccountSettings({ ...account_settings, ...value }); + openPasswordModal(); + }; + + const getPersonalDetailsForm = () => ( + +
+ + {localize('Complete your personal details')} + +
+
+ +
+
+ ); + + return ( + + + + {getPersonalDetailsForm()} + + + + + {getPersonalDetailsForm()} + + + + ); +}; + +export default connect(({ client, modules, ui }: RootStore) => ({ + account_settings: client.account_settings, + disableApp: ui.disableApp, + enableApp: ui.enableApp, + getChangeableFields: client.getChangeableFields, + is_fully_authenticated: client.is_fully_authenticated, + is_open: modules.cfd.is_cfd_personal_details_modal_visible, + landing_company: client.landing_company, + openPasswordModal: modules.cfd.enableCFDPasswordModal, + toggleCFDPersonalDetailsModal: modules.cfd.toggleCFDPersonalDetailsModal, + toggleJurisdictionModal: modules.cfd.toggleJurisdictionModal, + residence_list: client.residence_list, + setAccountSettings: client.setAccountSettings, +}))(CFDPersonalDetailsModal); diff --git a/packages/cfd/src/Containers/cfd-reset-password-modal.tsx b/packages/cfd/src/Containers/cfd-reset-password-modal.tsx index 65d3497aab78..feb5b21f9092 100644 --- a/packages/cfd/src/Containers/cfd-reset-password-modal.tsx +++ b/packages/cfd/src/Containers/cfd-reset-password-modal.tsx @@ -22,7 +22,10 @@ const ResetPasswordIntent = ({ current_list, children, is_eu, ...props }: TReset const reset_password_intent = localStorage.getItem('cfd_reset_password_intent'); const reset_password_type = localStorage.getItem('cfd_reset_password_type') || 'main'; // Default to main const has_intent = - reset_password_intent && /(real|demo)\.(financial_stp|financial|synthetic)/.test(reset_password_intent); + reset_password_intent && + /(real|demo)\.(financial_stp|financial|synthetic|synthetic_svg|synthetic_bvi|financial_svg|financial_bvi|financial_fx|financial_v)/.test( + reset_password_intent + ); let group, type, login, title, server; if (has_intent && current_list) { diff --git a/packages/cfd/src/Containers/compare-accounts-modal.tsx b/packages/cfd/src/Containers/compare-accounts-modal.tsx index f0b8339092eb..fdae781a52cb 100644 --- a/packages/cfd/src/Containers/compare-accounts-modal.tsx +++ b/packages/cfd/src/Containers/compare-accounts-modal.tsx @@ -6,6 +6,7 @@ import RootStore from 'Stores/index'; import { CFD_PLATFORMS } from '@deriv/shared'; import { LandingCompany } from '@deriv/api-types'; import ModalContent from './compare-accounts-content'; +import DMT5CompareModalContent from './mt5-compare-table-content'; type TCompareAccountsReusedProps = { landing_companies: LandingCompany; @@ -14,6 +15,11 @@ type TCompareAccountsReusedProps = { is_uk: boolean; }; +type TOpenAccountTransferMeta = { + category: string; + type?: string; +}; + type TCompareAccountsModalProps = TCompareAccountsReusedProps & { disableApp: () => void; enableApp: () => void; @@ -21,8 +27,12 @@ type TCompareAccountsModalProps = TCompareAccountsReusedProps & { is_loading: boolean; is_eu: boolean; is_eu_country: boolean; + is_real_enabled: boolean; residence: string; + is_demo_tab: boolean; toggleCompareAccounts: () => void; + openPasswordModal: (account_type: TOpenAccountTransferMeta) => void; + openDerivRealAccountNeededModal: () => void; }; const CompareAccountsModal = ({ @@ -35,12 +45,16 @@ const CompareAccountsModal = ({ is_eu, is_uk, is_eu_country, + is_real_enabled, platform, residence, + is_demo_tab, toggleCompareAccounts, + openPasswordModal, + openDerivRealAccountNeededModal, }: TCompareAccountsModalProps) => { const show_eu_related = (is_logged_in && is_eu) || (!is_logged_in && is_eu_country); - + const is_dxtrade = platform && platform === CFD_PLATFORMS.DXTRADE; const mt5_accounts = [ landing_companies?.mt_gaming_company?.financial, landing_companies?.mt_financial_company?.financial, @@ -50,61 +64,106 @@ const CompareAccountsModal = ({ const cfd_account_button_label = mt5_accounts.filter(Boolean).length === 1 ? localize('Account Information') : localize('Compare accounts'); + const getCFDModalTitle = () => (is_dxtrade ? cfd_account_button_label : localize('Compare available accounts')); + + const getModalStyle = () => { + if (is_dxtrade) { + return { + height: '696px', + width: '903px', + }; + } else if (show_eu_related) { + return { + height: '506px', + width: '300px', + }; + } + return { + height: '506px', + width: '996px', + }; + }; + return ( <> -
- + + + + + + + + + + + + +
+ + ); +}; + +export default connect(({ modules, ui, client }: RootStore) => ({ + account_settings: client.account_settings, + account_type: modules.cfd.account_type, + authentication_status: client.authentication_status, + disableApp: ui.disableApp, + enableApp: ui.enableApp, + is_jurisdiction_modal_visible: modules.cfd.is_jurisdiction_modal_visible, + jurisdiction_selected_shortcode: modules.cfd.jurisdiction_selected_shortcode, + trading_platform_available_accounts: client.trading_platform_available_accounts, + is_loading: client.is_populating_mt5_account_list, + is_eu: client.is_eu, + is_logged_in: client.is_logged_in, + is_eu_country: client.is_eu_country, + landing_companies: client.landing_companies, + is_fully_authenticated: client.is_fully_authenticated, + setAccountSettings: client.setAccountSettings, + toggleJurisdictionModal: modules.cfd.toggleJurisdictionModal, + residence: client.residence, + toggleCFDVerificationModal: modules.cfd.toggleCFDVerificationModal, + setJurisdictionSelectedShortcode: modules.cfd.setJurisdictionSelectedShortcode, + account_status: client.account_status, +}))(JurisdictionModal); diff --git a/packages/cfd/src/Containers/mt5-account-opening-real-financial-stp-modal.tsx b/packages/cfd/src/Containers/mt5-account-opening-real-financial-stp-modal.tsx deleted file mode 100644 index b53fa06e5708..000000000000 --- a/packages/cfd/src/Containers/mt5-account-opening-real-financial-stp-modal.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { Modal, MobileDialog, DesktopWrapper, MobileWrapper } from '@deriv/components'; -import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; -import CFDFinancialStpRealAccountSignup from 'Containers/cfd-financial-stp-real-account-signup'; -import { TMT5AccountOpeningRealFinancialStpModal } from './props.types'; -import RootStore from 'Stores/index'; - -const MT5AccountOpeningRealFinancialStpModal = ({ - disableApp, - disableMt5FinancialStpModal, - enableApp, - is_mt5_financial_stp_modal_open, -}: TMT5AccountOpeningRealFinancialStpModal) => ( - - - - - - - - - - - - -); - -export default connect(({ ui, modules }: RootStore) => ({ - disableApp: ui.disableApp, - disableMt5FinancialStpModal: modules.cfd.disableMt5FinancialStpModal, - enableApp: ui.enableApp, - is_mt5_financial_stp_modal_open: modules.cfd.is_mt5_financial_stp_modal_open, -}))(MT5AccountOpeningRealFinancialStpModal); diff --git a/packages/cfd/src/Containers/mt5-compare-table-content.tsx b/packages/cfd/src/Containers/mt5-compare-table-content.tsx new file mode 100644 index 000000000000..c08fe1ba05a1 --- /dev/null +++ b/packages/cfd/src/Containers/mt5-compare-table-content.tsx @@ -0,0 +1,617 @@ +import React from 'react'; +import classNames from 'classnames'; +import { Table, Div100vhContainer, Button, Text, Popover } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import { isDesktop, WS, getIdentityStatusInfo, CFD_PLATFORMS } from '@deriv/shared'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; +import { TTradingPlatformAvailableAccount } from '../Components/props.types'; +import { DetailsOfEachMT5Loginid, GetSettings, GetAccountSettingsResponse, GetAccountStatus } from '@deriv/api-types'; + +type TRowItem = { + text: string | Array; + tooltip_msg?: string; +}; + +type TValues = Record; + +type TInstrumentsRowProps = { + attr: string; + val: TValues; +}; + +type TModalContentProps = { + id: string; + attribute: string; + values: TValues; +}; + +type TFooterButtonData = { label: string; action: string }; + +type TOpenAccountTransferMeta = { + category: string; + type?: string; +}; + +type TDMT5CompareModalContentProps = { + account_settings: GetSettings; + setAccountSettings: (get_settings_response: GetSettings) => void; + account_type: { + type: string; + category: string; + }; + setAccountType: (account_type: TOpenAccountTransferMeta) => void; + clearCFDError: () => void; + current_list: Record; + has_real_account: boolean; + is_logged_in: boolean; + is_demo_tab: boolean; + is_real_enabled: boolean; + openDerivRealAccountNeededModal: () => void; + openPasswordModal: (account_type: TOpenAccountTransferMeta) => void; + toggleCompareAccounts: () => void; + toggleCFDVerificationModal: () => void; + trading_platform_available_accounts: TTradingPlatformAvailableAccount[]; + authentication_status: { + document_status: string; + identity_status: string; + }; + toggleCFDPersonalDetailsModal: () => void; + setJurisdictionSelectedShortcode: (shortcode: string) => void; + show_eu_related: boolean; + account_status: GetAccountStatus; + upgradeable_landing_companies: unknown[]; +}; + +const eucontent: TModalContentProps[] = [ + { + id: 'jurisdiction', + attribute: localize('Jurisdiction'), + values: { + financial_maltainvest: { text: localize('Malta Financial Services Authority') }, + }, + }, + { + id: 'counterparty', + attribute: localize('Counterparty company'), + values: { + financial_maltainvest: { text: localize('Deriv Investments (Europe) Limited') }, + }, + }, + { + id: 'regulator', + attribute: localize('Regulator'), + values: { + financial_maltainvest: { + text: localize('Malta Financial Services Authority (MFSA) (Licence no. IS/70156)'), + }, + }, + }, + + { + id: 'leverage', + attribute: localize('Maximum leverage'), + values: { + financial_maltainvest: { text: localize('Up to 1:30') }, + }, + }, + + { + id: 'instruments', + attribute: localize('Trading instruments'), + values: { + financial_maltainvest: { + text: [ + localize('Forex'), + localize('Stocks'), + localize('Stock indices'), + localize('Synthetic indices'), + localize('Cryptocurrencies'), + ], + }, + }, + }, +]; +const content: TModalContentProps[] = [ + { + id: 'jurisdiction', + attribute: localize('Jurisdiction'), + values: { + synthetic_svg: { text: localize('St. Vincent & Grenadines') }, + synthetic_bvi: { text: localize('British Virgin Islands') }, + financial_svg: { text: localize('St. Vincent & Grenadines') }, + financial_bvi: { text: localize('British Virgin Islands') }, + financial_vanuatu: { text: localize('Vanuatu') }, + financial_labuan: { + text: localize('Labuan'), + tooltip_msg: localize( + 'Choosing this jurisdiction will give you a Financial STP account. Your trades will go directly to the market and have tighter spreads.' + ), + }, + }, + }, + { + id: 'counterparty', + attribute: localize('Counterparty company'), + values: { + synthetic_svg: { text: localize('Deriv (SVG) LLC') }, + synthetic_bvi: { text: localize('Deriv (BVI) Ltd') }, + financial_svg: { text: localize('Deriv (SVG) LLC') }, + financial_bvi: { text: localize('Deriv (BVI) Ltd') }, + financial_vanuatu: { text: localize('Deriv (V) Ltd') }, + financial_labuan: { text: localize('Deriv (FX) Ltd') }, + }, + }, + { + id: 'regulator', + attribute: localize('Regulator'), + values: { + synthetic_svg: { text: localize('-') }, + synthetic_bvi: { + text: localize('British Virgin Islands Financial Services Commission (licence no. SIBA/L/18/1114)'), + }, + financial_svg: { text: localize('-') }, + financial_bvi: { + text: localize('British Virgin Islands Financial Services Commission (licence no. SIBA/L/18/1114)'), + }, + financial_vanuatu: { + text: localize('Vanuatu Financial Services Commission'), + }, + financial_labuan: { text: localize('Labuan Financial Services Authority (Licence no. MB/18/0024)') }, + }, + }, + + { + id: 'leverage', + attribute: localize('Maximum leverage'), + values: { + synthetic_svg: { text: localize('Up to 1:1000') }, + synthetic_bvi: { text: localize('Up to 1:1000') }, + financial_vanuatu: { text: localize('Up to 1:1000') }, + financial_labuan: { text: localize('Up to 1:100') }, + }, + }, + + { + id: 'instruments', + attribute: localize('Trading instruments'), + values: { + synthetic_svg: { text: localize('Synthetics') }, + financial_svg: { + text: [ + localize('Forex: standard/micro'), + localize('Stocks'), + localize('Stock indices'), + localize('Commodities'), + localize('Basket indices'), + localize('Cryptocurrencies'), + ], + }, + financial_vanuatu: { + text: [localize('Forex'), localize('Commodities')], + }, + financial_labuan: { text: [localize('Forex'), localize('Cryptocurrencies')] }, + }, + }, +]; + +const footer_buttons: TFooterButtonData[] = [ + { label: localize('Add'), action: 'synthetic_svg' }, + { label: localize('Add'), action: 'synthetic_bvi' }, + { label: localize('Add'), action: 'financial_svg' }, + { label: localize('Add'), action: 'financial_bvi' }, + { label: localize('Add'), action: 'financial_vanuatu' }, + { label: localize('Add'), action: 'financial_labuan' }, +]; +const eu_footer_button: TFooterButtonData[] = [{ label: localize('Add'), action: 'financial_maltainvest' }]; + +const DMT5CompareModalContent = ({ + authentication_status, + account_settings, + setAccountSettings, + setAccountType, + clearCFDError, + current_list, + has_real_account, + is_logged_in, + is_demo_tab, + is_real_enabled, + openDerivRealAccountNeededModal, + openPasswordModal, + toggleCFDVerificationModal, + toggleCFDPersonalDetailsModal, + toggleCompareAccounts, + trading_platform_available_accounts, + show_eu_related, + setJurisdictionSelectedShortcode, + account_status, + upgradeable_landing_companies, +}: TDMT5CompareModalContentProps) => { + const [has_submitted_personal_details, setHasSubmittedPersonalDetails] = React.useState(false); + + const available_accounts_keys = trading_platform_available_accounts.map( + account => `${account.market_type === 'gaming' ? 'synthetic' : account.market_type}_${account.shortcode}` + ); + const logged_out_available_accounts_count = show_eu_related ? 1 : 6; + const available_accounts_count = is_logged_in + ? available_accounts_keys.length + : logged_out_available_accounts_count; + const synthetic_accounts_count = + !is_logged_in && !show_eu_related + ? 2 + : available_accounts_keys.filter(key => key.startsWith('synthetic')).length; + const financial_accounts_count = + !is_logged_in && !show_eu_related + ? 4 + : available_accounts_keys.filter(key => key.startsWith('financial')).length || 1; + + const poa_status = authentication_status?.document_status; + const poi_status = authentication_status?.identity_status; + + const { need_poi_for_vanuatu, idv_acknowledged, poa_acknowledged, poi_acknowledged, poa_poi_verified } = + getIdentityStatusInfo(account_status); + + React.useEffect(() => { + if (!has_submitted_personal_details) { + let get_settings_response: GetSettings = {}; + if (!account_settings) { + WS.authorized.storage.getSettings().then((response: GetAccountSettingsResponse) => { + get_settings_response = response.get_settings as GetSettings; + setAccountSettings(response.get_settings as GetSettings); + }); + } else { + get_settings_response = account_settings; + } + const { citizen, place_of_birth, tax_residence, tax_identification_number, account_opening_reason } = + get_settings_response as GetSettings; + if (citizen && place_of_birth && tax_residence && tax_identification_number && account_opening_reason) { + setHasSubmittedPersonalDetails(true); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const getAvailableAccountsContent = (_content: TModalContentProps[]) => { + if (!is_logged_in) return _content; + return _content.map(row_data => { + const available_accounts_values = Object.entries(row_data.values).reduce( + (acc, [key, value]) => (available_accounts_keys.includes(key) ? { ...acc, [key]: value } : acc), + {} as TValues + ); + const content_data = { ...row_data, values: {} as TValues }; + if (available_accounts_keys.length < 6 && !show_eu_related) { + // order of the values matters for data to be correctly displayed in the table + const sorted_values = [ + 'synthetic_svg', + 'synthetic_bvi', + 'financial_svg', + 'financial_bvi', + 'financial_vanuatu', + 'financial_labuan', + ]; + content_data.values = sorted_values.reduce( + (acc, el) => (available_accounts_keys.includes(el) ? { ...acc, [el]: undefined } : acc), + {} + ); + available_accounts_keys.forEach(key => { + if (row_data.id === 'leverage' && (key === 'financial_svg' || key === 'financial_bvi')) { + content_data.values[key] = row_data.values.financial_vanuatu; + } else if (row_data.id === 'instruments' && key === 'synthetic_bvi') { + content_data.values[key] = row_data.values.synthetic_svg; + } else if (row_data.id === 'instruments' && key === 'financial_bvi') { + content_data.values[key] = row_data.values.financial_svg; + } + }); + } + return { ...content_data, values: { ...content_data.values, ...available_accounts_values } }; + }); + }; + + const getAvailableAccountsFooterButtons = (_footer_button_data: TFooterButtonData[]) => { + return _footer_button_data.filter(data => available_accounts_keys.includes(data.action)); + }; + + const onSelectRealAccount = (item: TFooterButtonData) => { + const poi_poa_verified = poi_status === 'verified' && poa_status === 'verified'; + const account_type = item.action.startsWith('financial') ? 'financial' : 'synthetic'; + + const type_of_account = { + category: is_demo_tab ? 'demo' : 'real', + type: account_type, + }; + clearCFDError(); + setAccountType(type_of_account); + + switch (item.action) { + case 'synthetic_svg': + setJurisdictionSelectedShortcode('svg'); + openPasswordModal(type_of_account); + break; + case 'financial_svg': + setJurisdictionSelectedShortcode('svg'); + if (poi_poa_verified && !has_submitted_personal_details) { + toggleCFDPersonalDetailsModal(); + } else { + openPasswordModal(type_of_account); + } + break; + case 'synthetic_bvi': + case 'financial_bvi': + setJurisdictionSelectedShortcode('bvi'); + if (poi_poa_verified) { + if (!has_submitted_personal_details) { + toggleCFDPersonalDetailsModal(); + } else { + openPasswordModal(type_of_account); + } + } else { + toggleCFDVerificationModal(); + } + break; + case 'financial_maltainvest': + setJurisdictionSelectedShortcode('maltainvest'); + if (poi_poa_verified) { + openPasswordModal(type_of_account); + } else { + toggleCFDVerificationModal(); + } + break; + + case 'financial_labuan': + setJurisdictionSelectedShortcode('labuan'); + if (poi_poa_verified) { + if (!has_submitted_personal_details) { + toggleCFDPersonalDetailsModal(); + } else { + openPasswordModal(type_of_account); + } + } else { + toggleCFDVerificationModal(); + } + break; + + case 'financial_vanuatu': + setJurisdictionSelectedShortcode('vanuatu'); + if (need_poi_for_vanuatu) { + toggleCFDVerificationModal(); + } else if (poi_poa_verified) { + if (!has_submitted_personal_details) { + toggleCFDPersonalDetailsModal(); + } else { + openPasswordModal(type_of_account); + } + } else { + toggleCFDVerificationModal(); + } + break; + + default: + } + }; + + const onButtonClick = (item: TFooterButtonData) => { + const should_show_missing_real_account = + is_logged_in && !has_real_account && upgradeable_landing_companies?.length > 0 && is_real_enabled; + toggleCompareAccounts(); + if (should_show_missing_real_account) { + openDerivRealAccountNeededModal(); + } else onSelectRealAccount(item); + }; + + const modal_content = show_eu_related ? eucontent : content; + const modal_footer = show_eu_related ? eu_footer_button : footer_buttons; + const getContentSize = (id: string) => { + if (id === 'counterparty' || id === 'leverage') return isDesktop() ? 'xxs' : 'xxxs'; + return isDesktop() ? 'xxxs' : 'xxxxs'; + }; + + const InstrumentsRow = ({ attr, val }: TInstrumentsRowProps) => ( + + + + {attr} + + + + {Object.keys(val).map(rowKey => ( + + {Array.isArray(val[rowKey]?.text) ? ( + (val[rowKey]?.text as []).map((item, index) => ( + + {item} + + )) + ) : ( + + {val[rowKey]?.text} + + )} + + ))} + + ); + + const Row = ({ id, attribute, values }: TModalContentProps) => { + const is_leverage = id === 'leverage'; + if (id === 'instruments') { + return ; + } + return ( + + + + {attribute} + + + + {Object.keys(values).map(item => ( + + <> + + {values[item]?.text} + + {values[item]?.tooltip_msg && ( + + )} + + + ))} + + ); + }; + + const should_show_pending_status = (item: TFooterButtonData) => { + const type = item.action.split('_')[1]; + if (type === 'svg') { + return false; + } else if (type === 'vanuatu') { + if (need_poi_for_vanuatu) { + return false; + } + return poa_acknowledged && poi_acknowledged && !poa_poi_verified; + } + return poa_acknowledged && (idv_acknowledged || poi_acknowledged) && !poa_poi_verified; + }; + + return ( + +
+
+ + + + + {!show_eu_related && synthetic_accounts_count > 0 && ( + + {localize('Synthetic')} + + )} + {financial_accounts_count > 0 && ( + + {show_eu_related ? localize('CFDs') : localize('Financial')} + + )} + + + + + {getAvailableAccountsContent(modal_content).map(row => ( + + ))} + + {is_logged_in && ( + + + {getAvailableAccountsFooterButtons(modal_footer).map((item, index) => ( + + {should_show_pending_status(item) ? ( +
+ + {localize('Pending verification')} + +
+ ) : ( + + )} +
+ ))} +
+ )} +
+
+
+
+ ); +}; + +export default connect(({ modules, client }: RootStore) => ({ + account_type: modules.cfd.account_type, + account_settings: client.account_settings, + authentication_status: client.authentication_status, + has_real_account: client.has_active_real_account, + setAccountSettings: client.setAccountSettings, + setAccountType: modules.cfd.setAccountType, + clearCFDError: modules.cfd.clearCFDError, + current_list: modules.cfd.current_list, + has_real_mt5_login: client.has_real_mt5_login, + setJurisdictionSelectedShortcode: modules.cfd.setJurisdictionSelectedShortcode, + toggleCFDVerificationModal: modules.cfd.toggleCFDVerificationModal, + toggleCFDPersonalDetailsModal: modules.cfd.toggleCFDPersonalDetailsModal, + trading_platform_available_accounts: client.trading_platform_available_accounts, + account_status: client.account_status, + upgradeable_landing_companies: client.upgradeable_landing_companies, +}))(DMT5CompareModalContent); diff --git a/packages/cfd/src/Containers/mt5-trade-modal.tsx b/packages/cfd/src/Containers/mt5-trade-modal.tsx new file mode 100644 index 000000000000..59b03433e1bb --- /dev/null +++ b/packages/cfd/src/Containers/mt5-trade-modal.tsx @@ -0,0 +1,327 @@ +import React from 'react'; +import { + Button, + Icon, + DesktopWrapper, + Div100vhContainer, + Modal, + MobileWrapper, + Money, + PageOverlay, + Popover, + Text, + UILoader, +} from '@deriv/components'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; +import { localize } from '@deriv/translations'; +import { DetailsOfEachMT5Loginid } from '@deriv/api-types'; +import { CFDAccountCopy } from '../Components/cfd-account-copy'; +import { TAccountIconValues, TPasswordBoxProps, TTradingPlatformAccounts } from '../Components/props.types'; +import { CFD_PLATFORMS, getCFDAccountDisplay, getCFDPlatformLabel, getUrlBase, getCFDAccountKey } from '@deriv/shared'; +import { getPlatformMt5DownloadLink, getMT5WebTerminalLink } from '../Helpers/constants'; + +type TMT5TradeModalProps = { + mt5_trade_account: Required; + disableApp: () => void; + enableApp: () => void; + is_eu_user: boolean; + is_open: boolean; + onPasswordManager: ( + arg1: string | undefined, + arg2: string, + arg3: string, + arg4: string, + arg5: string | undefined + ) => void; + toggleModal: () => void; +}; + +export type TSpecBoxProps = { + value: string | undefined; + is_bold?: boolean; +}; + +const PasswordBox = ({ platform, onClick }: TPasswordBoxProps) => ( +
+
+ + *************** + +
+ +
+); + +const SpecBox = ({ value, is_bold }: TSpecBoxProps) => ( +
+ + {value} + + +
+); + +const account_icons: { [key: string]: TAccountIconValues } = { + mt5: { + synthetic: 'IcMt5SyntheticPlatform', + financial: 'IcMt5FinancialPlatform', + cfd: 'IcMt5CfdPlatform', + }, +}; + +const getTitle = (market_type: string, is_eu_user: boolean) => { + if (is_eu_user) localize('MT5 CFDs MFSA'); + return market_type; +}; + +const MT5TradeModal = ({ + mt5_trade_account, + disableApp, + enableApp, + is_eu_user, + is_open, + onPasswordManager, + toggleModal, +}: TMT5TradeModalProps) => { + const getCompanyShortcode = () => { + if ( + (mt5_trade_account.account_type === 'demo' && + mt5_trade_account.market_type === 'financial' && + mt5_trade_account.landing_company_short === 'labuan') || + mt5_trade_account.account_type === 'real' + ) { + return mt5_trade_account.landing_company_short; + } + return undefined; + }; + const getHeadingTitle = () => + getCFDAccountDisplay({ + market_type: mt5_trade_account.market_type, + sub_account_type: mt5_trade_account.sub_account_type, + platform: CFD_PLATFORMS.MT5, + is_eu: is_eu_user, + shortcode: getCompanyShortcode(), + is_mt5_trade_modal: true, + }); + const getPageContent = () => ( +
+
+ +
+ + {getHeadingTitle()} + + {(mt5_trade_account as TTradingPlatformAccounts)?.display_login && ( + + {(mt5_trade_account as TTradingPlatformAccounts)?.display_login} + + )} +
+ {mt5_trade_account?.display_balance && ( + + + + )} +
+
+
+ {localize('Broker')} + +
+
+ {localize('Server')} + +
+
+ {localize('Login ID')} + +
+
+ {localize('Password')} +
+ { + const account_type = getCFDAccountKey({ + market_type: mt5_trade_account.market_type, + sub_account_type: mt5_trade_account.sub_account_type, + platform: CFD_PLATFORMS.DMT5, + shortcode: mt5_trade_account.landing_company_short, + }); + onPasswordManager( + mt5_trade_account?.login, + getTitle(mt5_trade_account.market_type, is_eu_user), + mt5_trade_account.account_type, + account_type, + (mt5_trade_account as DetailsOfEachMT5Loginid)?.server + ); + toggleModal(); + }} + /> +
+
+
+
+
+ + + {localize('MetaTrader 5 web')} + + + + {localize('Open')} + + +
+
+ + + {localize('MetaTrader 5 Windows app')} + + + + {localize('Download')} + + +
+
+ + + {localize('MetaTrader 5 MacOS app')} + + + + {localize('Download')} + + +
+
+ + + {localize('MetaTrader 5 Linux app')} + + + + {localize('Learn more')} + + +
+
+
+ +
+ + + {localize('Scan the QR code to download Deriv MT5.')} + +
+
+
+ ); + + return ( + }> + + + {getPageContent()} + + + + + + {getPageContent()} + + + + + ); +}; + +export default connect(({ modules, ui }: RootStore) => ({ + disableApp: ui.disableApp, + enableApp: ui.enableApp, + mt5_trade_account: modules.cfd.mt5_trade_account, +}))(MT5TradeModal); diff --git a/packages/cfd/src/Containers/props.types.ts b/packages/cfd/src/Containers/props.types.ts index 88b243ea92f4..8999274458cc 100644 --- a/packages/cfd/src/Containers/props.types.ts +++ b/packages/cfd/src/Containers/props.types.ts @@ -1,8 +1,29 @@ import { RouteComponentProps } from 'react-router'; -import { DetailsOfEachMT5Loginid, VerifyEmailResponse } from '@deriv/api-types'; +import { + DetailsOfEachMT5Loginid, + GetSettings, + LandingCompany, + ResidenceList, + VerifyEmailResponse, +} from '@deriv/api-types'; import { FormikHelpers as FormikActions } from 'formik'; import { TCFDPasswordFormValues } from './cfd-password-modal'; +export type TCFDPersonalDetailsModalProps = { + account_settings: GetSettings; + enableApp: () => void; + disableApp: () => void; + getChangeableFields: () => string[]; + is_open: boolean; + openPasswordModal: () => void; + toggleCFDPersonalDetailsModal: () => void; + toggleJurisdictionModal: () => void; + is_fully_authenticated: boolean; + landing_company: LandingCompany; + residence_list: ResidenceList; + setAccountSettings: (account_settings: GetSettings) => void; +}; + type CFD_Platform = 'dxtrade' | 'mt5'; export type TCFDChangePasswordConfirmationProps = { @@ -26,8 +47,8 @@ export type TCFDDashboardContainer = { export type TMT5AccountOpeningRealFinancialStpModal = { enableApp: () => void; disableApp: () => void; - disableMt5FinancialStpModal: () => void; - is_mt5_financial_stp_modal_open: boolean; + toggleCFDVerificationModal: () => void; + is_cfd_verification_modal_visible: boolean; }; export type TMissingRealAccount = { @@ -48,7 +69,7 @@ export type TPasswordResetAndTradingPasswordManager = { }; export type TResetPasswordIntent = { - current_list: Array & Record; + current_list: Record; children({ ...props }): React.ReactElement; is_eu: boolean; }; @@ -59,7 +80,7 @@ export type TError = { }; export type TCFDResetPasswordModal = RouteComponentProps & { - current_list: Array & Record; + current_list: Record; email: string; is_cfd_reset_password_modal_enabled: boolean; is_eu: boolean; @@ -124,6 +145,7 @@ export type TCFDPasswordManagerTabContent = { export type TCFDPasswordManagerModal = { enableApp: () => void; email: string; + is_eu: boolean; disableApp: () => void; is_visible: boolean; platform: CFD_Platform; diff --git a/packages/cfd/src/Helpers/constants.ts b/packages/cfd/src/Helpers/constants.ts index b8e481f52c59..24d87b4ecebf 100644 --- a/packages/cfd/src/Helpers/constants.ts +++ b/packages/cfd/src/Helpers/constants.ts @@ -32,6 +32,8 @@ const getPlatformMt5DownloadLink = (platform: string | undefined = undefined) => return 'https://download.mql5.com/cdn/web/metaquotes.software.corp/mt5/MetaTrader5.dmg'; case 'ios': return 'https://download.mql5.com/cdn/mobile/mt5/ios?server=Deriv-Demo,Deriv-Server'; + case 'huawei': + return 'https://appgallery.huawei.com/#/app/C102015329'; case 'android': return 'https://download.mql5.com/cdn/mobile/mt5/android?server=Deriv-Demo,Deriv-Server'; default: diff --git a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts index b037d6c92d05..309fa122b899 100644 --- a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts +++ b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts @@ -91,12 +91,48 @@ export const getMtCompanies = (is_eu: boolean) => { title: localize('Synthetic'), short_title: synthetic_config.short_title, }, + synthetic_svg: { + mt5_account_type: synthetic_config.account_type, + leverage: synthetic_config.leverage, + title: localize('Synthetic SVG'), + short_title: synthetic_config.short_title, + }, + synthetic_bvi: { + mt5_account_type: synthetic_config.account_type, + leverage: synthetic_config.leverage, + title: localize('Synthetic BVI'), + short_title: synthetic_config.short_title, + }, financial: { mt5_account_type: financial_config.account_type, leverage: financial_config.leverage, title: is_eu ? localize('CFDs') : localize('Financial'), short_title: financial_config.short_title, }, + financial_svg: { + mt5_account_type: financial_config.account_type, + leverage: financial_config.leverage, + title: is_eu ? localize('CFDs') : localize('Financial SVG'), + short_title: financial_config.short_title, + }, + financial_bvi: { + mt5_account_type: financial_config.account_type, + leverage: financial_config.leverage, + title: is_eu ? localize('CFDs') : localize('Financial BVI'), + short_title: financial_config.short_title, + }, + financial_fx: { + mt5_account_type: financial_config.account_type, + leverage: financial_config.leverage, + title: is_eu ? localize('CFDs') : localize('Financial Labuan'), + short_title: financial_config.short_title, + }, + financial_v: { + mt5_account_type: financial_config.account_type, + leverage: financial_config.leverage, + title: is_eu ? localize('CFDs') : localize('Financial Vanuatu'), + short_title: financial_config.short_title, + }, financial_stp: { mt5_account_type: financial_stp_config.account_type, leverage: financial_stp_config.leverage, diff --git a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js index e3012d1ea31d..116b3f0f797d 100644 --- a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js +++ b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js @@ -5,11 +5,17 @@ import { getDxCompanies, getMtCompanies } from './Helpers/cfd-config'; export default class CFDStore extends BaseStore { @observable is_compare_accounts_visible = false; + @observable is_cfd_personal_details_modal_visible = false; + @observable is_jurisdiction_modal_visible = false; + @observable is_mt5_trade_modal_visible = false; + @observable jurisdiction_selected_shortcode = ''; + @observable account_type = { category: undefined, type: undefined, }; + @observable mt5_trade_account = {}; @observable new_account_response = {}; @observable map_type = {}; @observable has_cfd_error = false; @@ -20,17 +26,19 @@ export default class CFDStore extends BaseStore { @observable is_cfd_password_modal_enabled = false; @observable is_cfd_reset_password_modal_enabled = false; - @observable is_cfd_pending_dialog_open = false; - @observable current_account = undefined; // this is a tmp value, don't rely on it, unless you set it first. @observable error_type = undefined; + @observable is_cfd_verification_modal_visible = false; @observable dxtrade_tokens = { demo: '', real: '', }; + real_synthetic_accounts_existing_data = []; + real_financial_accounts_existing_data = []; + constructor({ root_store }) { super({ root_store }); @@ -44,11 +52,6 @@ export default class CFDStore extends BaseStore { ); } - @computed - get has_cfd_account() { - return this.current_list.length > 0; - } - @computed get account_title() { return this.account_type.category @@ -58,11 +61,11 @@ export default class CFDStore extends BaseStore { @computed get current_list() { - const list = []; + const list = {}; this.root_store.client.mt5_login_list.forEach(account => { // e.g. mt5.real.financial_stp - list[getAccountListKey(account, CFD_PLATFORMS.MT5)] = { + list[getAccountListKey(account, CFD_PLATFORMS.MT5, account.landing_company_short)] = { ...account, }; }); @@ -106,8 +109,8 @@ export default class CFDStore extends BaseStore { checkShouldOpenAccount() { const account_type = sessionStorage.getItem('open_cfd_account_type'); if (account_type) { - const [category, type, set_password] = account_type.split('.'); - this.createCFDAccount({ category, type, set_password }); + const [category, platform, type, set_password] = account_type.split('.'); + this.createCFDAccount({ category, platform, type, set_password }); sessionStorage.removeItem('open_cfd_account_type'); } } @@ -136,17 +139,27 @@ export default class CFDStore extends BaseStore { } @action.bound - createCFDAccount({ category, type, set_password }) { + createCFDAccount({ category, platform, type, set_password }) { this.clearCFDError(); this.setAccountType({ category, type, }); - - if (category === 'real') { - this.realCFDSignup(set_password); - } else { - this.demoCFDSignup(); + if (platform === CFD_PLATFORMS.DXTRADE) { + if (category === 'real') { + this.realCFDSignup(set_password); + } else { + this.demoCFDSignup(); + } + } else if (platform === CFD_PLATFORMS.MT5) { + if (category === 'real') { + this.toggleJurisdictionModal(); + } else { + if (this.root_store.client.is_eu) { + this.setJurisdictionSelectedShortcode('maltainvest'); + } else this.setJurisdictionSelectedShortcode('svg'); + this.demoCFDSignup(); + } } } @@ -178,14 +191,28 @@ export default class CFDStore extends BaseStore { const name = this.getName(); const leverage = this.mt5_companies[this.account_type.category][this.account_type.type].leverage; const type_request = getAccountTypeFields(this.account_type); + const { address_line_1, address_line_2, address_postcode, address_city, address_state, country_code, phone } = + this.root_store.client.account_settings; return WS.mt5NewAccount({ mainPassword: values.password, email: this.root_store.client.email_address, leverage, name, + address: address_line_1 || address_line_2, + city: address_city, + country: country_code, + phone, + state: address_state, + zipCode: address_postcode, ...(values.server ? { server: values.server } : {}), - ...type_request, + ...(this.jurisdiction_selected_shortcode ? { company: this.jurisdiction_selected_shortcode } : {}), + ...(this.jurisdiction_selected_shortcode !== 'labuan' + ? type_request + : { + account_type: 'financial', + mt5_account_type: 'financial_stp', + }), }); } @@ -227,9 +254,7 @@ export default class CFDStore extends BaseStore { @action.bound enableMt5FinancialStpModal() { - if (this.account_type.category === 'real' && this.account_type.type === 'financial_stp') { - this.is_mt5_financial_stp_modal_open = true; - } + this.is_mt5_financial_stp_modal_open = true; } @action.bound @@ -245,6 +270,11 @@ export default class CFDStore extends BaseStore { }; } + @action.bound + setMT5TradeAccount(mt5_trade_account) { + this.mt5_trade_account = mt5_trade_account; + } + @action.bound setError(state, obj) { this.has_cfd_error = state; @@ -407,6 +437,26 @@ export default class CFDStore extends BaseStore { this.is_compare_accounts_visible = !this.is_compare_accounts_visible; } + @action.bound + getRealSyntheticAccountsExistingData(real_synthetic_accounts_existing_data) { + this.real_synthetic_accounts_existing_data = real_synthetic_accounts_existing_data; + } + + @action.bound + getRealFinancialAccountsExistingData(real_financial_accounts_existing_data) { + this.real_financial_accounts_existing_data = real_financial_accounts_existing_data; + } + + @action.bound + toggleJurisdictionModal() { + this.is_jurisdiction_modal_visible = !this.is_jurisdiction_modal_visible; + } + + @action.bound + toggleMT5TradeModal() { + this.is_mt5_trade_modal_visible = !this.is_mt5_trade_modal_visible; + } + @action.bound disableMt5FinancialStpModal() { this.is_mt5_financial_stp_modal_open = false; @@ -479,21 +529,6 @@ export default class CFDStore extends BaseStore { this.root_store.ui.setTopUpInProgress(false); } - @action.bound - closeCFDPendingDialog() { - this.is_cfd_pending_dialog_open = false; - } - - @action.bound - openPendingDialog() { - setTimeout( - runInAction(() => { - this.is_cfd_pending_dialog_open = true; - }), - 300 - ); - } - @action.bound sendVerifyEmail() { return WS.verifyEmail(this.root_store.client.email, 'trading_platform_investor_password_reset'); @@ -527,6 +562,11 @@ export default class CFDStore extends BaseStore { }); } + @action.bound + toggleCFDPersonalDetailsModal() { + this.is_cfd_personal_details_modal_visible = !this.is_cfd_personal_details_modal_visible; + } + static async changePassword({ login, old_password, new_password, password_type }) { let response; @@ -548,4 +588,14 @@ export default class CFDStore extends BaseStore { return response?.error?.message; } + + @action.bound + setJurisdictionSelectedShortcode(shortcode) { + this.jurisdiction_selected_shortcode = shortcode; + } + + @action.bound + toggleCFDVerificationModal() { + this.is_cfd_verification_modal_visible = !this.is_cfd_verification_modal_visible; + } } diff --git a/packages/cfd/src/sass/cfd-dashboard.scss b/packages/cfd/src/sass/cfd-dashboard.scss index 0a9eff005bf4..92aa08737d6a 100644 --- a/packages/cfd/src/sass/cfd-dashboard.scss +++ b/packages/cfd/src/sass/cfd-dashboard.scss @@ -197,11 +197,15 @@ } } &-link:not(:first-child) { - margin-left: 1.6rem; + margin-left: 0.8rem; } @include mobile { margin-left: unset; margin-right: unset; + &-links { + display: flex; + flex-direction: column; + } } } } @@ -223,13 +227,16 @@ margin-bottom: 1.6rem; } } + &__download-center--mt5 { + border-top: unset; + padding-top: unset; + } &__maintenance { @include typeface(--small-center-normal-black, none); display: flex; justify-content: center; align-items: center; margin: 2.4rem auto; - max-width: 75rem; &-icon { margin-right: 0.8rem; @@ -439,6 +446,163 @@ } } +.cfd-jurisdiction-card--synthetic, +.cfd-jurisdiction-card--financial { + border: solid 1px var(--border-normal); + border-radius: 0.8rem; + display: flex; + justify-content: space-between; + flex-direction: column; + min-height: 38rem; + width: 27.6em; + position: relative; + padding: 1.6rem; + @include mobile { + margin-bottom: 2rem; + } + + &:hover { + box-shadow: 0 2px 8px 0 var(--shadow-menu); + } + + &--disabled { + border: solid 1px var(--border-disabled); + } + + @include desktop { + height: 100%; + margin: 0 0.8rem; + } + + &__wrapper { + padding: 0; + margin-top: 2.4rem; + display: flex; + justify-content: center; + align-items: center; + + @include mobile { + flex-direction: column; + } + } + &--selected { + border: solid 1px #377cfc; + border-radius: 4px; + } + + &__verification-status, + &__verification-status--pending, + &__verification-status--POA_POI, + &__verification-status--verified { + width: 100%; + min-height: 2.4rem; + display: flex; + + * { + margin: auto; + } + + &--pending { + background-color: #ffad3a; + color: #333333; + border-radius: 0.5rem; + } + + &--verified { + background-color: #4bb4b3; + border-radius: 0.5rem; + &-text { + color: #fff; + } + } + + &--POA_POI { + background-color: #ec3f3f; + color: #fff; + border-radius: 0.5rem; + } + } + + &__h2-header { + margin: 1.4rem 0 2.4rem; + } + + &__footer { + font-weight: 400; + font-size: 10px; + line-height: 14px; + color: #333333; + padding: 0.5rem 0.8rem; + margin-top: auto; + text-align: center; + &--none { + background-color: #f2f3f4; + } + } + + &__footer--none { + background-color: var(--general-section-1); + color: #333333; + margin-top: auto; + padding: 0.3rem; + } + + &__footnote { + display: flex; + flex-direction: column; + justify-content: center; + margin: 2.4rem auto 0; + @include desktop { + width: 99.2rem; + } + + &--pending { + color: #ffad3a; + margin-top: 2.4rem; + } + } + + &__jurisdiction-checkbox { + display: flex; + justify-content: center; + margin-top: 1.6rem; + } + + &__over-header { + background-color: #dfeaff; + top: -1rem; + left: 1.4rem; + z-index: 10; + width: 90%; + height: 4rem; + position: absolute; + border-radius: 4px; + margin-bottom: 1rem; + + & > p { + font-size: 16px; + text-align: center; + } + } + + &__bullet-wrapper { + display: flex; + margin-bottom: 1rem; + + &--checkmark { + margin-right: 1rem; + } + } +} + +.cfd-jurisdiction-card--synthetic { + padding: 2.4rem; +} + +.cfd-modal--custom-exit { + display: none; +} + .cfd-real-accounts-display { transition: margin-bottom 0.3s ease-in-out; margin-bottom: var(--cfd-real-acc-margin-bottom); @@ -462,17 +626,78 @@ border-radius: 4px; display: flex; flex-flow: column nowrap; - min-height: 37rem; + min-height: 24rem; width: 30.4em; position: relative; @include desktop { - height: 100%; + height: fit-content; + } + + &__balance { + margin-bottom: 0.8rem; + &--region { + border: 1px solid #2a3052; + border-radius: 1rem; + background-color: #2a3052; + padding: 0.2rem 0.8rem; + } + &--value { + @include typeface(--title-left-bold-black); + color: var(--text-profit-success); + padding: 0.8rem; + } + } + + &--login-id { + padding: 0 0.8rem; + } + + &--login-id-demo { + padding: 0.8rem 0.8rem 0; + } + + &__item { + width: 90%; + background-color: var(--general-section-1); + border-radius: 8px; + margin-bottom: 0.8rem; + + &--banner { + position: relative; + transform: rotate(45deg); + border-bottom: 1.8rem solid #85acb0; + border-left: 1.8rem solid transparent; + border-right: 1.8rem solid transparent; + height: 0; + width: 7rem; + @include desktop { + left: 21.8rem; + } + @include mobile { + margin-left: 1.8rem; + } + top: 1rem; + color: #fff; + font-weight: bold; + line-height: 18px; + white-space: nowrap; + text-align: center; + + &--demo { + border-bottom-color: var(--brand-secondary); + } + &--server { + border-bottom-color: $color-blue-2; + } + @include mobile { + left: calc(100vw - 14.2rem); + } + } } &__wrapper { display: grid; grid-template-rows: 1fr; - height: 100%; justify-content: center; @include mobile { @@ -483,14 +708,10 @@ margin-bottom: 2.4rem; } } - - @include desktop { - height: 100%; - } } &__logged-out { - min-height: 29rem; + min-height: 12rem; } &__add-server { @@ -564,10 +785,6 @@ color: var(--text-general); line-height: 1.45; } - &--balance { - @include typeface(--title-left-bold-black); - color: var(--text-profit-success); - } &__banner { position: absolute; transform: rotate(45deg); @@ -643,7 +860,6 @@ &__cta { display: flex; flex-direction: column; - margin-top: auto; &-wrapper { align-items: center; @@ -809,6 +1025,24 @@ } } } + + &__manage--mt5 { + display: flex; + width: 100%; + margin-left: 0.4rem; + padding-top: 0.2rem; + + .dc-btn { + min-width: 12rem; + margin-bottom: 1.6rem; + height: 4rem; + + &:not(:last-child) { + margin-right: 0.6rem; + } + } + } + &__action-wrapper { margin: 0 auto 1.3rem; padding-top: 1rem; @@ -827,7 +1061,7 @@ width: calc(100% - 3.2rem); margin-left: 1.6rem; border-top: 1px solid var(--general-section-1); - margin-top: 1rem; + margin: 1rem 0 1.6rem 1.6rem; } @include mobile { width: calc(100vw - 3.2rem); @@ -840,6 +1074,241 @@ } } +.cfd-trade-modal-container { + width: inherit; +} + +.cfd-trade-modal { + display: flex; + margin: 2.4rem; + align-items: center; + gap: 0.8rem; + &--paragraph { + @include typeface(--paragraph-left-normal-black, none); + color: var(--text-less-prominent); + line-height: 1.45; + } + &__desc { + display: flex; + flex-direction: column; + flex-grow: 1; + } + &__password { + &-box { + display: flex; + align-items: center; + gap: 0.8rem; + } + &-text { + overflow: hidden; + } + &-action { + padding: 0; + height: 1.5rem; + .dc-btn__icon { + padding-right: 0; + } + } + } + &__specs { + padding: 1.6rem; + width: 100%; + + &-table { + width: 100%; + + &-attribute .cfd-trade-modal--paragraph { + color: var(--text-general); + margin-right: 2.4rem; + } + &-data { + .cfd-trade-modal--paragraph { + @include typeface(--paragraph-left-bold-black, none); + line-height: 1.45; + } + } + } + } + &__login-specs { + margin: 0 2.4rem; + display: flex; + flex-direction: column; + gap: 0.1rem; + :first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + } + :last-child { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + } + &-item { + display: flex; + padding: 0.5rem 0.8rem; + align-items: center; + justify-content: space-between; + background: var(--general-section-1); + } + } + &__spec-box { + display: flex; + gap: 1rem; + align-items: center; + } + &__spec-text { + font-family: Courier, monospace; + overflow: hidden; + } + &__download-center { + border-top: 2px solid var(--general-section-1); + padding-top: 2rem; + padding-bottom: 5.8rem; + + &-app { + display: flex; + flex-direction: column; + margin-top: 1.6rem; + &--option { + display: flex; + gap: 1.6rem; + align-items: center; + padding: 1.6rem 2.4rem; + border-top: 1px solid var(--border-disabled); + &:last-child { + border-bottom: 1px solid var(--border-disabled); + } + &-item { + flex-grow: 1; + } + &-link { + align-items: center; + display: flex; + justify-content: center; + text-decoration: none; + @include typeface(--paragraph-center-bold-black, none); + background-color: transparent; + border: 1px solid var(--border-disabled); + color: var(--text-less-prominent); + + &:hover { + background-color: var(--button-secondary-hover); + } + } + } + } + + &-options { + display: flex; + justify-content: center; + align-items: center; + margin: 1.6rem; + &--desktop { + display: block; + align-items: baseline; + flex-flow: column nowrap; + + &-links { + display: flex; + flex-direction: column; + } + &-row { + display: flex; + align-items: baseline; + justify-content: center; + margin-bottom: 3.1rem; + + > svg:first-child { + margin-bottom: 0.4rem; + margin-right: 0.8rem; + } + a > svg { + margin-top: 0.8rem; + margin-right: 0.8rem; + } + } + &-download { + display: grid; + grid-auto-flow: column; + grid-gap: 0.8rem; + justify-content: center; + + a { + margin-top: 0.4rem; + } + } + } + &--mobile { + align-items: center; + display: flex; + flex-flow: column nowrap; + margin-left: 4.7rem; + + &-devices { + margin-bottom: 1.6em; + svg:first-child { + margin-right: 0.8em; + } + } + &-link:not(:first-child) { + margin-left: 1.6rem; + } + &-links { + display: flex; + @include mobile { + flex-direction: column; + } + } + @include mobile { + margin-left: unset; + margin-right: unset; + } + } + &--qrcode { + display: flex; + flex-direction: column; + padding: 0.8rem; + margin: 0 0.8rem; + align-items: center; + justify-content: center; + border: 1px solid var(--border-disabled); + border-radius: 5px; + max-width: 14rem; + @include mobile { + margin-left: 1.6rem; + } + } + @include mobile { + align-items: flex-start; + } + } + &--heading { + @include typeface(--title-center-bold-black, none); + color: var(--text-general); + line-height: 1.5; + margin-left: 2.1rem; + margin-bottom: 4.2rem; + @include desktop { + margin-left: 0; + text-align: center; + } + } + &--hint { + margin-top: 1.6rem; + } + @include mobile { + margin-bottom: 1.6rem; + } + } + &__mobile-view { + .dc-page-overlay__content { + flex-direction: column; + } + &-wrapper { + overflow: scroll; + } + } +} + .cfd-password-manager { margin: 5.6rem auto 3.2rem; width: 100%; @@ -946,17 +1415,17 @@ } .cfd-financial-stp-modal { - display: grid; - grid-template-rows: 13rem minmax(10rem, 1fr); + display: flex; height: 100%; position: relative; width: 100%; - .dc-modal-footer { - position: fixed; - padding: unset; - bottom: 1.6rem; - right: 1.6rem; + &__body { + width: 100%; + .poi-form-on-signup { + display: grid; + grid-template-rows: minmax(20rem, 1fr); + } } &__form { @@ -981,26 +1450,7 @@ &__heading { padding: unset; } - &__header { - &-steps { - padding-bottom: 0.8rem; - width: 100%; - &-title { - color: var(--brand-red-coral); - font-size: 1.4rem; - font-weight: bold; - line-height: 20px; - padding: 1.6rem 2.4rem 0.8rem; - } - &-subtitle { - color: var(--text-prominent); - line-height: 18px; - font-size: 1.2rem; - font-weight: bold; - padding: 0 2.4rem; - } - } - } + .dc-form-submit-button { background-color: var(--color-white); } @@ -1049,6 +1499,30 @@ } } +.cfd-personal-details-modal { + grid-template-rows: 8rem minmax(10rem, 1fr); + + &__heading-container { + padding-top: 2.4rem; + } + + &__form { + .dc-modal-footer { + width: 100%; + padding: 1.6rem 2.4rem; + margin-top: 7.7rem; + bottom: 0; + right: 0; + display: flex; + justify-content: flex-end; + } + + .dc-autocomplete { + margin-bottom: 3.6rem; + } + } +} + .dc-modal { &__container { min-width: initial; @@ -1112,6 +1586,9 @@ display: grid; grid-template-rows: minmax(10rem, 1fr) 7.2rem; height: 100%; + .dc-modal-footer { + border-top: 1px solid var(--general-active); + } } &__file-upload { padding-top: 0.8rem; @@ -1178,6 +1655,7 @@ &__field-area { max-width: 556px; margin: 0 auto; + padding: 3rem 0; & .dc-dropdown__display-placeholder-text, & .dc-input__label, @@ -1538,5 +2016,203 @@ align-items: flex-end; } } +.cfd-real-compare-accounts { + display: flex; + flex-flow: column nowrap; + flex-grow: 1; + background: inherit; + height: 100%; + position: relative; + &-row-eu { + grid-template-columns: 1fr 1fr; + } + @for $column_count from 1 through 7 { + .cfd-real-compare-accounts__row-with-columns-count-#{$column_count} { + grid-template-columns: repeat($column_count, 1fr); + } + } + &__table-header { + grid-template-columns: 0.9fr 1.39fr 2.74fr; + } + @for $financial_accounts_count from 0 through 6 { + @for $synthetic_accounts_count from 0 through 2 { + .cfd-real-compare-accounts__table-header-for-synthetic-#{$synthetic_accounts_count}-financial-#{$financial_accounts_count} { + @if $synthetic_accounts_count > 0 and $financial_accounts_count > 0 { + grid-template-columns: 1fr ($synthetic_accounts_count + fr) ($financial_accounts_count + fr); + } @else if $synthetic_accounts_count == 0 and $financial_accounts_count == 0 { + grid-template-columns: 1fr; + } @else if $synthetic_accounts_count == 0 { + grid-template-columns: 1fr ($financial_accounts_count + fr); + } @else { + grid-template-columns: 1fr ($synthetic_accounts_count + fr); + } + } + } + } + &__table-header-item { + justify-content: center; + } + + &__table-row { + grid-template-columns: 0.9fr 0.72fr 0.67fr 0.72fr 0.67fr 0.65fr 0.7fr; + &--leverage { + grid-template-columns: 0.9fr 0.72fr 0.67fr 2.04fr 0.7fr; + } + &--instruments { + grid-template-columns: 0.9fr 1.39fr 1.39fr 0.65fr 0.7fr; + } + } + + &__table-row-item { + flex-direction: column; + justify-content: center; + &--tooltip { + flex-direction: row; + } + } + &__table-footer { + grid-template-columns: 0.9fr 0.72fr 0.67fr 0.72fr 0.67fr 0.65fr 0.7fr; + height: 5.8rem; + &__item { + height: 5.8rem; + justify-content: center; + &--verification-pending { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 8px; + background: rgba(255, 68, 79, 0.16); + opacity: 0.32; + border-radius: 4px; + width: 100%; + .dc-text { + font-style: normal; + font-weight: 700; + color: var(--brand-red-coral); + } + } + } + &__button { + width: 100%; + } + } + + .dc-table { + margin: 0 25px; + + &__header { + border: none; + height: 4rem; + top: 0; + z-index: 10; + } + &__cell:not(.cfd-real-compare-accounts__table-empty-cell), + &__head:not(.cfd-real-compare-accounts__table-empty-cell) { + padding: 0.8rem; + border: 1px solid var(--general-active); + margin-left: -1px; + margin-bottom: -1px; + } + &__cell { + padding: 1rem 0.8rem; + } + &__row { + border-bottom: none; + min-height: 4rem; + } + + &--scrollbar { + display: block; // Safari needs this to work properly! + } + } + &-modal { + &__wrapper { + display: flex; + justify-content: center; + margin-top: 2.4rem; + } + } + @include mobile { + height: 100%; + font-size: 1.2rem; + + .dc-table { + height: 100%; + margin: 25px; + overflow-x: auto; + &__cell { + &--fixed { + background-color: var(--general-main-1); + .dc-text { + font-size: var(--text-size-xxxs); + text-align: left; + } + } + } + } + &__table { + &-header, + &-footer, + &-row, + &-row--leverage, + &-row--instruments { + width: 250vw; + } + } + .cfd-real-compare-accounts { + &__table-empty-cell.dc-table { + &__cell--fixed { + margin-left: -1px; + border: 1px solid var(--general-active); + border-width: 1px 1px 0px 0px; + } + &__head { + border-top: none; + } + } + &-row-eu { + width: unset; + height: unset; + } + } + @for $column_count from 1 through 7 { + .cfd-real-compare-accounts__row-with-columns-count-#{$column_count} { + width: calc(250vw / 7 * #{$column_count}); + } + } + @for $financial_accounts_count from 0 through 6 { + @for $synthetic_accounts_count from 0 through 2 { + .cfd-real-compare-accounts__table-header-for-synthetic-#{$synthetic_accounts_count}-financial-#{$financial_accounts_count} { + width: calc(250vw / 7 * (#{$synthetic_accounts_count} + #{$financial_accounts_count} + 1)); + } + } + } + } +} +.dc-modal-header__title--cfd-real-compare-accounts { + font-size: var(--text-size-sm); + line-height: 3rem; +} + +.cfd-real-compare-accounts-mobile-header { + height: fit-content; + border-bottom: none; + .dc-text { + font-size: var(--text-size-s); + } +} +.cfd-compare-accounts-tooltip { + margin-left: 0.8rem; + &--msg { + font-size: var(--text-size-xxs); + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 8px; + width: 276px; + border-radius: 4px; + } +} /* stylelint-enable */ diff --git a/packages/cfd/src/sass/cfd.scss b/packages/cfd/src/sass/cfd.scss index a948857bb30f..8bea09fa00e7 100644 --- a/packages/cfd/src/sass/cfd.scss +++ b/packages/cfd/src/sass/cfd.scss @@ -392,3 +392,33 @@ margin-top: 4rem; } } + +.dc-modal__container_cfd-financial-stp-modal { + .dc-modal-header { + border-bottom: 1px solid var(--general-section-1); + } +} +.poi-poa-submitted { + &__message-content { + align-items: center; + display: flex; + flex-direction: column; + height: auto; + justify-content: center; + padding: 10rem 3rem 7rem; + line-height: 5rem; + .dc-btn { + margin-top: 2rem; + } + } + &__text { + padding-top: 1.6rem; + } + &__svg-footer { + display: flex; + margin: 1.6rem 0; + .dc-btn { + margin: 0.5rem; + } + } +} diff --git a/packages/components/src/components/dialog/dialog.scss b/packages/components/src/components/dialog/dialog.scss index 1e310629cddf..11b61a95fb2d 100644 --- a/packages/components/src/components/dialog/dialog.scss +++ b/packages/components/src/components/dialog/dialog.scss @@ -51,7 +51,7 @@ } &__dialog { max-width: 560px; - max-height: 320px; + max-height: 338px; min-width: 440px; min-height: 176px; margin-top: -#{$HEADER_HEIGHT}; diff --git a/packages/components/src/components/dropdown/dropdown.scss b/packages/components/src/components/dropdown/dropdown.scss index 413416070550..31057d9bfd6c 100644 --- a/packages/components/src/components/dropdown/dropdown.scss +++ b/packages/components/src/components/dropdown/dropdown.scss @@ -267,6 +267,10 @@ min-width: 15rem; width: 100%; + &:not(.cfd-personal-details-modal__form *) { + margin-top: unset; + } + // keep