diff --git a/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx b/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx index d68fd756fd75..f5342532bb5f 100644 --- a/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx +++ b/packages/account/src/Components/currency-selector/__tests__/currency-selector.spec.tsx @@ -26,8 +26,8 @@ describe('', () => { is_virtual: 1, landing_company_shortcode: 'virtual', trading: {}, - token: 'a1-sLGGrhfYPkeEprxEop2T591cLKbuN', - email: 'test+qw@deriv.com', + token: '', + email: '', session_start: 1651059038, excluded_until: '', landing_company_name: 'virtual', @@ -273,8 +273,8 @@ describe('', () => { is_virtual: 1, landing_company_shortcode: 'svg', trading: {}, - token: 'a1-sLGGrhfYPkeEprxEop2T591cLKbuN', - email: 'test+qw@deriv.com', + token: '', + email: '', session_start: 1651059038, excluded_until: '', landing_company_name: 'svg', diff --git a/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx b/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx index 6082f7f6e4bf..8cee4c674c0e 100644 --- a/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx +++ b/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button, Icon, Loading } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { getAuthenticationStatusInfo } from '@deriv/shared'; +import { getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared'; import IconMessageContent from 'Components/icon-message-content'; import { GetAccountStatus } from '@deriv/api-types'; @@ -43,8 +43,9 @@ const PoiPoaDocsSubmitted = ({ const getDescription = () => { const { manual_status, poi_verified_for_vanuatu_maltainvest, poi_verified_for_bvi_labuan, poa_pending } = getAuthenticationStatusInfo(account_status); - const is_vanuatu_or_maltainvest_selected = - jurisdiction_selected_shortcode === 'vanuatu' || jurisdiction_selected_shortcode === 'maltainvest'; + const is_vanuatu_or_maltainvest_selected = [Jurisdiction.VANUATU, Jurisdiction.MALTA_INVEST].includes( + jurisdiction_selected_shortcode + ); if ( (is_vanuatu_or_maltainvest_selected && poi_verified_for_vanuatu_maltainvest && poa_pending) || (!is_vanuatu_or_maltainvest_selected && poi_verified_for_bvi_labuan && poa_pending) || diff --git a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx b/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx index 01468524278d..32797922eb16 100644 --- a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx +++ b/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx @@ -1,6 +1,6 @@ /* eslint-disable react-hooks/exhaustive-deps */ import React from 'react'; -import { WS } from '@deriv/shared'; +import { WS, Jurisdiction } from '@deriv/shared'; import Unsupported from 'Components/poi/status/unsupported'; import OnfidoUpload from './onfido-sdk-view.jsx'; import { identity_status_codes, submission_status_code, service_code } from './proof-of-identity-utils'; @@ -30,7 +30,7 @@ const POISubmissionForMT5 = ({ is_idv_supported && Number(idv_submissions_left) > 0 && !is_idv_disallowed && - jurisdiction_selected_shortcode !== 'vanuatu' + jurisdiction_selected_shortcode !== Jurisdiction.VANUATU ) { setSubmissionService(service_code.idv); } else if (onfido_submissions_left && is_onfido_supported) { diff --git a/packages/appstore/src/components/cfds-listing/cfds-listing.scss b/packages/appstore/src/components/cfds-listing/cfds-listing.scss index 44d35d7421ed..dbcbb1d3060d 100644 --- a/packages/appstore/src/components/cfds-listing/cfds-listing.scss +++ b/packages/appstore/src/components/cfds-listing/cfds-listing.scss @@ -1,19 +1,16 @@ .cfd-jurisdiction-card--synthetic, .cfd-jurisdiction-card--financial { - border: solid 1px var(--border-normal); - border-radius: 0.8rem; + border: solid 2px var(--border-normal); + border-radius: $BORDER_RADIUS * 4; display: flex; justify-content: space-between; flex-direction: column; - min-height: 36rem; - width: 27.6em; - position: relative; - padding: 1.6rem; - @include mobile { - margin-bottom: 2rem; - } + height: 100%; + width: 100%; + cursor: pointer; + transition: all 0.1s ease-in; - &:hover { + &:not(.selected-card):hover { box-shadow: 0 2px 8px 0 var(--shadow-menu); } @@ -21,99 +18,116 @@ border: solid 1px var(--border-disabled); } - @include desktop { - height: auto; - margin: 0 0.8rem; - } - &__wrapper { - padding: 0; - margin-top: 4.8rem; + margin: 4rem 6rem 2rem; display: flex; justify-content: center; - + gap: 2rem; @include mobile { + margin: 0; + padding: 4rem; + gap: 4rem; flex-direction: column; align-items: center; + overflow-y: scroll; + height: 60%; } } &--selected { - border: solid 1px $color-blue; - border-radius: 4px; + border: solid 2px $color-green; + box-shadow: 0 1.2rem 1.8rem 0.8rem var(--shadow-menu); } - &__verification-status, - &__verification-status--pending, - &__verification-status--failed, - &__verification-status--account_added, - &__verification-status--poi_verified, - &__verification-status--not_submitted, - &__verification-status--hint { - width: 100%; - min-height: 2.4rem; - display: flex; - - * { - margin: auto; - } - - &--pending { - background-color: $color-yellow; - border-radius: 0.5rem; + &__card { + &-content { + &-container { + display: flex; + flex-direction: column; + height: 100%; + } + &-over-header { + background: var(--text-info-blue-background); + height: 4rem; + width: 100%; + padding: 0.5rem; + border-radius: 1.4rem 1.4rem 0 0; + &-blank { + height: 4rem; + border-radius: 1.4rem; + @include mobile { + height: 2rem; + } + } + } + &-footer { + width: 100%; + &-text { + background: var(--brand-secondary); + height: 4rem; + padding: 1rem; + border-radius: 0 0 1.4rem 1.4rem; + } + } } - - &--poi_verified { - background: var(--text-status-info-blue); - border-radius: 0.5rem; + &-flipped-container { + gap: 2rem; + padding: 4rem 2rem; } - &--account_added { - background-color: $color-green-1; - border-radius: 0.5rem; + &-section-container { + display: flex; + flex-direction: column; + gap: 1.2rem; + height: 100%; + margin: 0 2rem; } + } - &--failed { - background-color: $color-red-1; - border-radius: 0.5rem; - } - &--not_submitted { - background-color: var(--general-section-1); - padding: 0.3rem; - border-radius: 0.5rem; + &__h2-header { + min-height: 5rem; + margin: 1rem 2rem; + @include mobile { + margin-bottom: 2rem; + min-height: auto; } } + &__footer-wrapper { + display: flex; + flex-direction: column; + justify-content: space-between; @include mobile { + min-height: auto; background-color: var(--general-main-1); width: 100%; height: 100%; position: sticky; bottom: 0; - max-height: 20rem; z-index: 12; } - .dc-modal-footer { - @include desktop { - position: fixed; - bottom: 0; - width: 100%; - } - } } - &__h2-header { - margin: 1.4rem 0 2.4rem; + + &__footnotes-container { + display: flex; + flex-direction: column; + gap: 1rem; + margin: 1rem; + @include desktop { + min-height: 6rem; + } + @include mobile { + gap: 0; + margin: 0; + } } + &__footnote { display: flex; - flex-direction: column; justify-content: center; - margin: 1.6rem 2.4rem; - @include mobile { margin: unset; padding: 1.6rem 0.8rem; box-shadow: 0px -4px 4px rgba(0, 0, 0, 0.08); } - &--pending { color: $color-yellow; } @@ -129,33 +143,157 @@ &__over-header { background-color: #dfeaff; - top: -1rem; + top: -2rem; left: 1.4rem; z-index: 10; width: 90%; height: 4rem; position: absolute; - border-radius: 4px; + border-radius: $BORDER_RADIUS * 2; margin-bottom: 1rem; - + border: 1px solid var(--text-info-blue); & > p { font-size: 16px; text-align: center; } } +} - &__bullet-wrapper { +.cfd-card { + &-perspective { + -webkit-perspective: 100rem; + perspective: 100rem; + @include mobile { + width: 100%; + } + } + &-container { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-transition: all 0.25s ease-in; + transition: all 0.25s ease-in; + width: 29rem; + &.synthetic { + min-height: 48rem; + } + &.financial { + min-height: 54rem; + } + @include mobile { + height: 48rem; + width: 100%; + } + } + &-flipped { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + &-front, + &-back { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + position: absolute; + top: 0; + left: 0; + } + &-front { + z-index: 2; + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + } + &-back { + -webkit-transform: rotateY(-180deg); + transform: rotateY(-180deg); + } + &-section { + width: 100%; display: flex; - margin-bottom: 1rem; - - &--checkmark { - margin-right: 1rem; + flex-direction: column; + gap: 0.8rem; + &-divider { + width: 100%; + border-bottom: 2px solid var(--border-divider); + } + &-title-indicator { + padding: 0.6rem 1.2rem; + border-radius: $BORDER_RADIUS; + &-icon-container { + display: flex; + gap: 0.5rem; + } + &__red-darker { + background: $color-red-8; + } + &__red-dark { + background: $color-red-9; + } + &__red-light { + background: $color-red-10; + } + &__yellow-dark { + background: $color-yellow-1; + } + &__yellow-light { + background: $color-yellow-2; + } + &__violet-dark { + background: $color-violet; + } + &__brown-dark { + background: $color-brown; + } + } + &-description-height { + @include desktop { + &-assets { + min-height: 3.4rem; + } + &-verifications, + &-regulator { + min-height: 5rem; + } + } + } + } + &-back-section { + &-items-container { + display: flex; + flex-direction: column; + gap: 1.2rem; + } + &-items-sub-container { + display: flex; + align-items: flex-start; + gap: 1rem; + } + &-back-button { + -webkit-transition: transform 0.25s linear; + transition: transform 0.25s linear; + } + &-text-icon-aligned { + margin-top: -0.3rem; + } + } + &-clickable-description-link { + color: var(--text-red); + &:hover { + text-decoration: underline; + } + } + &-title-container { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + } + &-disabled { + pointer-events: none; + &-flat { + border: solid 1px var(--border-normal); } } -} - -.cfd-jurisdiction-card--synthetic { - padding: 2.4rem; } .cfd-modal--custom-exit { @@ -1804,9 +1942,8 @@ } .dc-modal__container_jurisdiction-modal { - min-height: 664px; .dc-modal-header { - border-bottom: 1px solid var(--general-section-1); + border-bottom: 2px solid var(--general-section-1); } } diff --git a/packages/cfd/src/Components/props.types.ts b/packages/cfd/src/Components/props.types.ts index 3dae634df84c..0ac5915362ae 100644 --- a/packages/cfd/src/Components/props.types.ts +++ b/packages/cfd/src/Components/props.types.ts @@ -68,6 +68,73 @@ export type TTradingPlatformAvailableAccount = { sub_account_type: string; }; +export type TCardFlipStatus = { + svg: boolean; + bvi: boolean; + labuan: boolean; + vanuatu: boolean; + maltainvest: boolean; +}; + +export type TClickableDescription = { + type: 'text' | 'link'; + text: string; +}; + +export type TJurisdictionCardSectionTitleIndicators = { + type: 'displayText' | 'displayIcons'; + display_text?: string; + display_text_skin_color?: string; +}; + +export type TJurisdictionCardSection = { + key: string; + title: string; + title_indicators?: TJurisdictionCardSectionTitleIndicators; + description?: string; + clickable_description?: TClickableDescription[]; +}; + +export type TJurisdictionCardVerificationStatus = 'Pending' | 'Verified' | 'Failed' | 'Default'; + +export type TJurisdictionCardItemVerificationItem = + | 'document_number' + | 'selfie' + | 'identity_document' + | 'name_and_address' + | 'not_applicable'; + +export type TJurisdictionCardItemVerification = TJurisdictionCardItemVerificationItem[]; + +export type TJurisdictionCardItems = { + header: string; + over_header?: string; + contents: TJurisdictionCardSection[]; + is_over_header_available: boolean; + verification_docs?: TJurisdictionCardItemVerification; +}; + +export type TJurisdictionVerificationSection = { + icon: string; + text: string; +}; + +export type TJurisdictionVerificationItems = { + document_number?: TJurisdictionVerificationSection; + selfie?: TJurisdictionVerificationSection; + identity_document?: TJurisdictionVerificationSection; + name_and_address?: TJurisdictionVerificationSection; + not_applicable?: TJurisdictionVerificationSection; +}; + +type TJurisdictionVerificationColors = 'yellow' | 'red' | 'green'; + +export type TJurisdictionVerificationStatus = { + icon: string; + text: string; + color: TJurisdictionVerificationColors; +}; + export type TExistingData = DetailsOfEachMT5Loginid & DetailsOfEachMT5Loginid[]; export type TCFDAccountCard = { diff --git a/packages/cfd/src/Constants/jurisdiction-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents.ts deleted file mode 100644 index e47a5e95d456..000000000000 --- a/packages/cfd/src/Constants/jurisdiction-contents.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { localize } from '@deriv/translations'; - -type TJurisdictionCardItems = { - header: string; - over_header?: string; - synthetic_contents: Array; - financial_contents: Array; - is_over_header_available: boolean; -}; -type TJurisdictionContent = { - svg: TJurisdictionCardItems; - vanuatu: TJurisdictionCardItems; - labuan: TJurisdictionCardItems; - maltainvest: TJurisdictionCardItems; - bvi: TJurisdictionCardItems; -}; - -export const getJurisdictionContents = (): TJurisdictionContent => ({ - svg: { - is_over_header_available: false, - header: localize('St. Vincent & Grenadines'), - synthetic_contents: [ - `${localize('Selecting this will onboard you through Deriv (SVG) LLC (company no. 273 LLC 2020)')}`, - `${localize('30+ assets: synthetics, basket indices and derived FX')}`, - `${localize('Leverage up to 1:1000')}`, - ], - financial_contents: [ - `${localize('Selecting this will onboard you through Deriv (SVG) LLC (company no. 273 LLC 2020)')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize( - '165+ assets: forex (standard/micro), stocks, stock indices, commodities, and cryptocurrencies' - )}`, - `${localize('Leverage up to 1:1000')}`, - ], - }, - vanuatu: { - is_over_header_available: false, - header: localize('Vanuatu'), - synthetic_contents: [ - `${localize('Regulated by the Vanuatu Financial Services Commission')}`, - `${localize('30+ assets: synthetics, basket indices and derived FX')}`, - `${localize('Leverage up to 1:1000')}`, - ], - financial_contents: [ - `${localize('Regulated by the Vanuatu Financial Services Commission')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize('90+ assets: forex, stock indices, commodities and cryptocurrencies')}`, - `${localize('Leverage up to 1:1000')}`, - ], - }, - labuan: { - over_header: localize('Straight-through processing'), - is_over_header_available: true, - header: localize('Labuan'), - synthetic_contents: [ - `${localize('Regulated by the Labuan Financial Services Authority (Licence no. MB/18/0024)')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize('80+ assets: forex and cryptocurrencies')}`, - `${localize('Leverage up to 1:100')}`, - ], - financial_contents: [ - `${localize('Regulated by the Labuan Financial Services Authority (Licence no. MB/18/0024)')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize('80+ assets: forex and cryptocurrencies')}`, - `${localize('Leverage up to 1:100')}`, - `${localize('Straight-through processing')}`, - ], - }, - maltainvest: { - is_over_header_available: false, - header: localize('Malta'), - synthetic_contents: [ - `${localize('Regulated by the Malta Financial Services Authority (MFSA) (licence no. IS/70156)')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize('150+ assets: forex, stocks, stock indices, synthetics, commodities and cryptocurrencies')}`, - `${localize('Leverage up to 1:30')}`, - ], - financial_contents: [ - `${localize('Regulated by the Malta Financial Services Authority (MFSA) (licence no. IS/70156)')}`, - `${localize('Registered with the Financial Commission')}`, - `${localize('150+ assets: forex, stocks, stock indices, synthetics, commodities and cryptocurrencies')}`, - `${localize('Leverage up to 1:30')}`, - ], - }, - bvi: { - is_over_header_available: false, - header: localize('British Virgin Islands'), - synthetic_contents: [ - `${localize( - 'Regulated by the British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)' - )}`, - `${localize('30+ assets: synthetics, basket indices and derived FX')}`, - `${localize('Leverage up to 1:1000')}`, - ], - financial_contents: [ - `${localize( - 'Regulated by the British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)' - )}`, - `${localize('Registered with the Financial Commission')}`, - `${localize( - '165+ assets: forex (standard/micro), stocks, stock indices, commodities, and cryptocurrencies' - )}`, - `${localize('Leverage up to 1:1000')}`, - ], - }, -}); diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts new file mode 100644 index 000000000000..3a5d05f69429 --- /dev/null +++ b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts @@ -0,0 +1,276 @@ +import { Jurisdiction } from '@deriv/shared'; +import { localize } from '@deriv/translations'; +import { + TJurisdictionCardItemVerification, + TJurisdictionCardSection, + TJurisdictionCardSectionTitleIndicators, + TJurisdictionCardItems, + TClickableDescription, +} from 'Components/props.types'; +import { TJurisdictionCardType } from 'Containers/props.types'; + +const getJurisdictionHeader = (card_type: TJurisdictionCardType): string => { + switch (card_type) { + case Jurisdiction.SVG: + return localize('St. Vincent & Grenadines'); + case Jurisdiction.BVI: + return localize('British Virgin Islands'); + case Jurisdiction.VANUATU: + return localize('Vanuatu'); + case Jurisdiction.LABUAN: + return localize('Labuan'); + case Jurisdiction.MALTA_INVEST: + return localize('Malta'); + default: + return ''; + } +}; + +const getAssetsTitleIndicators = ( + card_type: TJurisdictionCardType, + is_synthetic: boolean +): TJurisdictionCardSectionTitleIndicators | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + case Jurisdiction.BVI: + return is_synthetic + ? { + type: 'displayText', + display_text: localize('40+'), + display_text_skin_color: 'red-darker', + } + : { + type: 'displayText', + display_text: localize('170+'), + display_text_skin_color: 'red-light', + }; + case Jurisdiction.VANUATU: + return is_synthetic + ? { + type: 'displayText', + display_text: localize('40+'), + display_text_skin_color: 'red-darker', + } + : { + type: 'displayText', + display_text: localize('90+'), + display_text_skin_color: 'red-dark', + }; + case Jurisdiction.LABUAN: + return is_synthetic + ? undefined + : { + type: 'displayText', + display_text: localize('90+'), + display_text_skin_color: 'red-dark', + }; + case Jurisdiction.MALTA_INVEST: + return { + type: 'displayText', + display_text: localize('140+'), + display_text_skin_color: 'red-light', + }; + default: + return undefined; + } +}; + +const getAssetsDescription = (card_type: TJurisdictionCardType, is_synthetic: boolean): string | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + case Jurisdiction.BVI: + return is_synthetic + ? localize('Synthetics, Basket indices and Derived FX') + : localize('Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies'); + case Jurisdiction.VANUATU: + return is_synthetic + ? localize('Synthetics, Basket indices and Derived FX') + : localize('Forex, Stock indices, Commodities and Cryptocurrencies'); + case Jurisdiction.LABUAN: + return localize('Forex and Cryptocurrencies'); + case Jurisdiction.MALTA_INVEST: + return localize('Synthetics, Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies'); + default: + return undefined; + } +}; + +const getLeverageTitleIndicators = ( + card_type: TJurisdictionCardType, + is_synthetic: boolean +): TJurisdictionCardSectionTitleIndicators | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + case Jurisdiction.BVI: + case Jurisdiction.VANUATU: + return { + type: 'displayText', + display_text: localize('1:1000'), + display_text_skin_color: 'yellow-light', + }; + case Jurisdiction.LABUAN: + return is_synthetic + ? undefined + : { + type: 'displayText', + display_text: localize('1:100'), + display_text_skin_color: 'yellow-dark', + }; + case Jurisdiction.MALTA_INVEST: + return { + type: 'displayText', + display_text: localize('1:30'), + display_text_skin_color: 'brown-dark', + }; + default: + return undefined; + } +}; + +const getSpreadsFromTitleIndicators = ( + card_type: TJurisdictionCardType, + is_synthetic: boolean +): TJurisdictionCardSectionTitleIndicators | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + case Jurisdiction.LABUAN: + return is_synthetic + ? undefined + : { + type: 'displayText', + display_text: localize('0.6 pips'), + display_text_skin_color: 'violet-dark', + }; + case Jurisdiction.BVI: + case Jurisdiction.VANUATU: + return is_synthetic + ? undefined + : { + type: 'displayText', + display_text: localize('0.5 pips'), + display_text_skin_color: 'violet-dark', + }; + case Jurisdiction.MALTA_INVEST: + return { + type: 'displayText', + display_text: localize('0.5 pips'), + display_text_skin_color: 'violet-dark', + }; + default: + return undefined; + } +}; + +const getVerificationsTitleIndicators = ( + card_type: TJurisdictionCardType, + is_synthetic: boolean +): TJurisdictionCardSectionTitleIndicators | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + case Jurisdiction.BVI: + case Jurisdiction.VANUATU: + case Jurisdiction.LABUAN: + return { type: 'displayIcons' }; + case Jurisdiction.MALTA_INVEST: + return is_synthetic ? undefined : { type: 'displayIcons' }; + default: + return undefined; + } +}; + +const getVerificationsDescription = (card_type: TJurisdictionCardType): string | undefined => { + return card_type === Jurisdiction.SVG + ? localize('You will need to submit proof of identity and address once you reach certain thresholds.') + : undefined; +}; + +const getVerificationsClickableDescription = ( + card_type: TJurisdictionCardType +): TClickableDescription[] | undefined => { + return card_type !== Jurisdiction.SVG + ? [ + { type: 'link', text: localize('Learn more') }, + { type: 'text', text: localize('about verifications needed.') }, + ] + : undefined; +}; + +const getRegulatorDescription = (card_type: TJurisdictionCardType): string | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + return localize('Deriv (SVG) LLC (company no. 273 LLC 2020)'); + case Jurisdiction.BVI: + return localize('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)'); + case Jurisdiction.VANUATU: + return localize('Vanuatu Financial Services Commission'); + case Jurisdiction.LABUAN: + return localize('Labuan Financial Services Authority (licence no. MB/18/0024)'); + case Jurisdiction.MALTA_INVEST: + return localize('Malta Financial Services Authority (MFSA) (licence no. IS/70156)'); + default: + return undefined; + } +}; + +const getContents = (card_type: TJurisdictionCardType, is_synthetic: boolean): TJurisdictionCardSection[] => { + const card_sections: TJurisdictionCardSection[] = [ + { + key: 'assets', + title: localize('Assets'), + title_indicators: getAssetsTitleIndicators(card_type, is_synthetic), + description: getAssetsDescription(card_type, is_synthetic), + }, + { + key: 'leverage', + title: localize('Leverage'), + title_indicators: getLeverageTitleIndicators(card_type, is_synthetic), + }, + { + key: 'spreadsFrom', + title: localize('Spreads from'), + title_indicators: getSpreadsFromTitleIndicators(card_type, is_synthetic), + }, + { + key: 'verifications', + title: localize('Verifications'), + title_indicators: getVerificationsTitleIndicators(card_type, is_synthetic), + description: getVerificationsDescription(card_type), + clickable_description: getVerificationsClickableDescription(card_type), + }, + { + key: 'regulator', + title: localize('Regulator/EDR'), + description: getRegulatorDescription(card_type), + }, + ]; + if ([Jurisdiction.SVG, Jurisdiction.BVI, Jurisdiction.VANUATU].includes(card_type) && is_synthetic) { + card_sections.splice(2, 1); + } + return card_sections; +}; + +const getVerificationDocs = (card_type: TJurisdictionCardType): TJurisdictionCardItemVerification | undefined => { + switch (card_type) { + case Jurisdiction.SVG: + return ['not_applicable']; + case Jurisdiction.BVI: + case Jurisdiction.VANUATU: + case Jurisdiction.LABUAN: + return ['document_number', 'name_and_address']; + case Jurisdiction.MALTA_INVEST: + return ['selfie', 'identity_document', 'name_and_address']; + default: + return undefined; + } +}; + +export const getJurisdictionContentsFor = ( + card_type: TJurisdictionCardType, + is_synthetic: boolean +): TJurisdictionCardItems => ({ + is_over_header_available: card_type === Jurisdiction.LABUAN, + over_header: card_type === Jurisdiction.LABUAN ? localize('Straight-through processing') : undefined, + header: getJurisdictionHeader(card_type), + contents: getContents(card_type, is_synthetic), + verification_docs: getVerificationDocs(card_type), +}); diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts new file mode 100644 index 000000000000..00fb59980008 --- /dev/null +++ b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts @@ -0,0 +1,49 @@ +import { localize } from '@deriv/translations'; +import { TJurisdictionVerificationItems, TJurisdictionVerificationStatus } from 'Components/props.types'; + +type TJurisdictionVerificationContents = { + short_description: string; + required_verification_docs: TJurisdictionVerificationItems; + status_references: Array; +}; + +export const jurisdictionVerificationContents = (): TJurisdictionVerificationContents => ({ + short_description: localize('We need you to submit these in order to get this account:'), + required_verification_docs: { + document_number: { + icon: 'IcDocumentNumberVerification', + text: localize('Document number (identity card, passport)'), + }, + selfie: { + icon: 'IcSelfieVerification', + text: localize('A selfie of yourself.'), + }, + identity_document: { + icon: 'IcIdentityDocumentVerification', + text: localize('A copy of your identity document (identity card, passport)'), + }, + name_and_address: { + icon: 'IcNameAndAddressVerification', + text: localize( + 'A recent utility bill (electricity, water or gas) or recent bank statement or government-issued letter with your name and address.' + ), + }, + not_applicable: { + icon: 'IcNotApplicableVerification', + text: '', + }, + }, + status_references: [ + { + icon: 'IcVerificationStatusYellow', + text: localize('Your document is pending for verification.'), + color: 'yellow', + }, + { + icon: 'IcVerificationStatusRed', + text: localize('Verification failed. Resubmit during account creation.'), + color: 'red', + }, + { icon: 'IcVerificationStatusGreen', text: localize('Your document is verified.'), color: 'green' }, + ], +}); diff --git a/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js b/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js index 24c17abd8632..d4741dbd08fb 100644 --- a/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js +++ b/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import { Router } from 'react-router'; import { createBrowserHistory } from 'history'; -import { WS, getErrorMessages, validPassword } from '@deriv/shared'; +import { WS, getErrorMessages, validPassword, Jurisdiction } from '@deriv/shared'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import CFDPasswordModal from '../cfd-password-modal'; @@ -61,7 +61,7 @@ describe('', () => { is_cfd_password_modal_enabled: true, is_cfd_success_dialog_enabled: false, is_dxtrade_allowed: false, - jurisdiction_selected_shortcode: 'svg', + jurisdiction_selected_shortcode: Jurisdiction.SVG, platform: 'mt5', has_cfd_error: false, landing_companies: {}, @@ -247,7 +247,7 @@ describe('', () => { account_type: { category: 'real', type: 'financial' }, is_eu: true, is_fully_authenticated: false, - jurisdiction_selected_shortcode: 'bvi', + jurisdiction_selected_shortcode: Jurisdiction.BVI, }; render( diff --git a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx b/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx index 6631c4ff3c9b..5e77900cb668 100644 --- a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx +++ b/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx @@ -14,7 +14,7 @@ import { localize } from '@deriv/translations'; import RootStore from '../Stores/index'; import { PoiPoaDocsSubmitted } from '@deriv/account'; import { connect } from '../Stores/connect'; -import { getAuthenticationStatusInfo, isMobile, WS } from '@deriv/shared'; +import { getAuthenticationStatusInfo, isMobile, WS, Jurisdiction } from '@deriv/shared'; import { AccountStatusResponse } from '@deriv/api-types'; import { TCFDDbviOnboardingProps } from './props.types'; import CFDFinancialStpRealAccountSignup from './cfd-financial-stp-real-account-signup'; @@ -63,13 +63,13 @@ const CFDDbviOnboarding = ({ if (get_account_status?.authentication) { const { poi_acknowledged_for_vanuatu_maltainvest, poi_acknowledged_for_bvi_labuan, poa_acknowledged } = getAuthenticationStatusInfo(get_account_status); - if (jurisdiction_selected_shortcode === 'vanuatu') { + if (jurisdiction_selected_shortcode === Jurisdiction.VANUATU) { setShowSubmittedModal( poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged && has_submitted_cfd_personal_details ); - } else if (jurisdiction_selected_shortcode === 'maltainvest') { + } else if (jurisdiction_selected_shortcode === Jurisdiction.MALTA_INVEST) { setShowSubmittedModal(poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged); } else setShowSubmittedModal( 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 06b4a8088b38..08f9b4fa3c01 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,6 +1,6 @@ import React from 'react'; import { Div100vhContainer } from '@deriv/components'; -import { isDesktop, getAuthenticationStatusInfo } from '@deriv/shared'; +import { isDesktop, getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared'; import { connect } from '../Stores/connect'; import { LandingCompany, ResidenceList, GetSettings, StatesList, GetAccountStatus } from '@deriv/api-types'; import CFDPOA from '../Components/cfd-poa'; @@ -112,17 +112,15 @@ const CFDFinancialStpRealAccountSignup = (props: TCFDFinancialStpRealAccountSign }; const should_show_poi = () => { - if (jurisdiction_selected_shortcode === 'vanuatu' || jurisdiction_selected_shortcode === 'maltainvest') { + if ([Jurisdiction.VANUATU, Jurisdiction.MALTA_INVEST].includes(jurisdiction_selected_shortcode)) { return need_poi_for_vanuatu_maltainvest; } return need_poi_for_bvi_labuan; }; - const should_show_poa = !( - authentication_status.document_status === 'pending' || authentication_status.document_status === 'verified' - ); + const should_show_poa = !['pending', 'verified'].includes(authentication_status.document_status); const should_show_personal_details = - !has_submitted_cfd_personal_details && jurisdiction_selected_shortcode !== 'maltainvest'; + !has_submitted_cfd_personal_details && jurisdiction_selected_shortcode !== Jurisdiction.MALTA_INVEST; const verification_configs = [ ...(should_show_poi() ? [poi_config] : []), diff --git a/packages/cfd/src/Containers/cfd-password-modal.tsx b/packages/cfd/src/Containers/cfd-password-modal.tsx index f019569dd3e4..f46c9ee72260 100644 --- a/packages/cfd/src/Containers/cfd-password-modal.tsx +++ b/packages/cfd/src/Containers/cfd-password-modal.tsx @@ -23,6 +23,7 @@ import { getLegalEntityName, isDesktop, isMobile, + Jurisdiction, routes, validLength, validPassword, @@ -184,12 +185,12 @@ const ReviewMessageForMT5 = ({ return ( ); - } else if (['bvi', 'vanuatu'].includes(jurisdiction_selected_shortcode)) { + } else if ([Jurisdiction.BVI, Jurisdiction.VANUATU].includes(jurisdiction_selected_shortcode)) { if (manual_status === 'pending') { return ; } return ; - } else if (['labuan', 'maltainvest'].includes(jurisdiction_selected_shortcode)) { + } else if ([Jurisdiction.LABUAN, Jurisdiction.MALTA_INVEST].includes(jurisdiction_selected_shortcode)) { return ; } return null; @@ -652,16 +653,23 @@ const CFDPasswordModal = ({ const [is_selected_mt5_verified, setIsSelectedMT5Verified] = React.useState(false); const getVerificationStatus = () => { - if (jurisdiction_selected_shortcode === 'svg') { - setIsSelectedMT5Verified(true); - } else if (jurisdiction_selected_shortcode === 'bvi') { - setIsSelectedMT5Verified(poi_verified_for_bvi_labuan); - } else if (jurisdiction_selected_shortcode === 'vanuatu') { - setIsSelectedMT5Verified(poi_verified_for_vanuatu_maltainvest); - } else if (jurisdiction_selected_shortcode === 'labuan') { - setIsSelectedMT5Verified(poi_verified_for_bvi_labuan && poa_verified); - } else if (jurisdiction_selected_shortcode === 'maltainvest') { - setIsSelectedMT5Verified(poi_verified_for_vanuatu_maltainvest && poa_verified); + switch (jurisdiction_selected_shortcode) { + case Jurisdiction.SVG: + setIsSelectedMT5Verified(true); + break; + case Jurisdiction.BVI: + setIsSelectedMT5Verified(poi_verified_for_bvi_labuan); + break; + case Jurisdiction.VANUATU: + setIsSelectedMT5Verified(poi_verified_for_vanuatu_maltainvest); + break; + case Jurisdiction.LABUAN: + setIsSelectedMT5Verified(poi_verified_for_bvi_labuan && poa_verified); + break; + case Jurisdiction.MALTA_INVEST: + setIsSelectedMT5Verified(poi_verified_for_vanuatu_maltainvest && poa_verified); + break; + default: } }; @@ -802,7 +810,7 @@ const CFDPasswordModal = ({ ].short_title; const jurisdiction_label = jurisdiction_selected_shortcode && getFormattedJurisdictionCode(jurisdiction_selected_shortcode); - const mt5_platform_label = jurisdiction_selected_shortcode !== 'maltainvest' ? 'MT5' : ''; + const mt5_platform_label = jurisdiction_selected_shortcode !== Jurisdiction.MALTA_INVEST ? 'MT5' : ''; if (category === 'real') { return ( diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-back.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-back.spec.tsx new file mode 100644 index 000000000000..842819030173 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-back.spec.tsx @@ -0,0 +1,91 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import JurisdictionCardBack from '../jurisdiction-card-back'; + +describe('', () => { + type TMockProps = { + card_classname: string; + toggleCardFlip: jest.Mock; + is_card_selected: boolean; + verification_docs: ( + | 'document_number' + | 'name_and_address' + | 'selfie' + | 'identity_document' + | 'not_applicable' + )[]; + }; + + const mock_props: TMockProps = { + card_classname: 'test_classname', + is_card_selected: false, + toggleCardFlip: jest.fn(), + verification_docs: [], + }; + + const exampleVerificationMessage = () => { + expect(screen.getByText('Your document is pending for verification.')).toBeInTheDocument(); + expect(screen.getByText('Verification failed. Resubmit during account creation.')).toBeInTheDocument(); + expect(screen.getByText('Your document is verified.')).toBeInTheDocument(); + }; + + it('should render JurisdictionCardBack without any required submission if verification_docs is empty', () => { + render(); + const container = screen.getByTestId('dt_jurisdiction_card_back'); + expect(container).toHaveClass( + 'test_classname__card-content-container', + 'test_classname__card-flipped-container' + ); + expect(screen.getByText('We need you to submit these in order to get this account:')).toBeInTheDocument(); + expect(screen.queryByText('A selfie of yourself.')).not.toBeInTheDocument(); + expect(screen.queryByText('Document number (identity card, passport)')).not.toBeInTheDocument(); + expect( + screen.queryByText( + 'A recent utility bill (electricity, water or gas) or recent bank statement or government-issued letter with your name and address.' + ) + ).not.toBeInTheDocument(); + expect( + screen.queryByText('A copy of your identity document (identity card, passport)') + ).not.toBeInTheDocument(); + exampleVerificationMessage(); + }); + + it('should render JurisdictionCardBack display required document_number and name_and_address submission', () => { + mock_props.verification_docs = ['document_number', 'name_and_address']; + render(); + expect(screen.queryByText('A selfie of yourself.')).not.toBeInTheDocument(); + expect( + screen.queryByText('A copy of your identity document (identity card, passport)') + ).not.toBeInTheDocument(); + expect(screen.getByText('We need you to submit these in order to get this account:')).toBeInTheDocument(); + expect(screen.getByText('Document number (identity card, passport)')).toBeInTheDocument(); + expect( + screen.getByText( + 'A recent utility bill (electricity, water or gas) or recent bank statement or government-issued letter with your name and address.' + ) + ).toBeInTheDocument(); + exampleVerificationMessage(); + }); + + it('should render JurisdictionCardBack display required selfie, identity_document and name_and_address submission', () => { + mock_props.verification_docs = ['selfie', 'identity_document', 'name_and_address']; + render(); + expect(screen.getByText('We need you to submit these in order to get this account:')).toBeInTheDocument(); + expect(screen.getByText('A selfie of yourself.')).toBeInTheDocument(); + expect(screen.getByText('A copy of your identity document (identity card, passport)')).toBeInTheDocument(); + expect( + screen.getByText( + 'A recent utility bill (electricity, water or gas) or recent bank statement or government-issued letter with your name and address.' + ) + ).toBeInTheDocument(); + exampleVerificationMessage(); + expect(screen.queryByText('Document number (identity card, passport)')).not.toBeInTheDocument(); + }); + + it('should render JurisdictionCardBack and include selected_card classname if is_card_selected is true', () => { + mock_props.is_card_selected = true; + render(); + const container = screen.getByTestId('dt_jurisdiction_card_back_container'); + expect(container).toHaveClass('test_classname--selected', 'selected-card'); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-front.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-front.spec.tsx new file mode 100644 index 000000000000..49bb588b8afd --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-front.spec.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import JurisdictionCardFront from '../jurisdiction-card-front'; +import { render, screen } from '@testing-library/react'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionCardFront', () => { + const p2p_status: 'none' | 'active' | 'temp_ban' | 'perm_ban' = 'active'; + const prompt_client_to_authenticate: 0 | 1 = 1; + const mock_props = { + account_status: { + currency_config: { usd: {} }, + p2p_status, + prompt_client_to_authenticate, + risk_classification: '', + status: [], + }, + disabled: false, + type_of_card: Jurisdiction.SVG, + card_classname: 'jurisdiction_test', + toggleCardFlip: jest.fn(), + card_values: { + contents: [ + { + key: '', + title: '', + description: '', + title_indicators: { + type: 'displayText' as const, + display_text: '', + display_text_skin_color: '', + }, + }, + ], + header: 'Test Header', + over_header: 'Test Over Header', + is_over_header_available: false, + }, + card_data: [ + { + key: 'Test1', + title: 'Test Title 1', + description: 'Test Description 1', + title_indicators: { + type: 'displayText' as const, + display_text: 'Test 1', + display_text_skin_color: '', + }, + }, + { + key: 'Test2', + title: 'Test Title 2', + description: 'Test Description 2', + title_indicators: { + type: 'displayText' as const, + display_text: 'Test 2', + display_text_skin_color: '', + }, + }, + ], + is_card_selected: false, + verification_docs: [], + }; + + it('should render JurisdictionCardFront without over header', () => { + render(); + expect(screen.getByText('Test Header')).toBeInTheDocument(); + expect(screen.getByText('Test Title 1')).toBeInTheDocument(); + expect(screen.getByText('Test 1')).toBeInTheDocument(); + expect(screen.getByText('Test Description 1')).toBeInTheDocument(); + expect(screen.getByText('Test Title 2')).toBeInTheDocument(); + expect(screen.getByText('Test 2')).toBeInTheDocument(); + expect(screen.getByText('Test Description 2')).toBeInTheDocument(); + expect(screen.queryByText('Test Over Header')).not.toBeInTheDocument(); + }); + + it('should render JurisdictionCardFront with over header', () => { + mock_props.card_values.is_over_header_available = true; + render(); + expect(screen.getByText('Test Over Header')).toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-section.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-section.spec.tsx new file mode 100644 index 000000000000..a38700c92acf --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card-section.spec.tsx @@ -0,0 +1,126 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import JurisdictionCardSection from '../jurisdiction-card-section'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionCardSection', () => { + type TMockProps = { + account_status: { + authentication: { + document: { + status: 'none' | 'pending' | 'verified' | 'expired' | 'rejected' | undefined; + }; + identity: { + services: { + idv: { + status: 'none' | 'pending' | 'verified' | 'expired' | 'rejected' | undefined; + }; + onfido: { + status: 'none' | 'pending' | 'verified' | 'expired' | 'rejected' | undefined; + }; + manual: { + status: 'none' | 'pending' | 'verified' | 'expired' | 'rejected' | undefined; + }; + }; + }; + needs_verification: string[]; + }; + currency_config: { + [k: string]: { + is_deposit_suspended?: 0 | 1; + is_withdrawal_suspended?: 0 | 1; + }; + }; + p2p_status: 'none'; + prompt_client_to_authenticate: 0; + risk_classification: string; + status: string[]; + }; + card_section_item: { + key: string; + title: string; + title_indicators?: { + type: 'displayText'; + display_text: string; + display_text_skin_color: string; + }; + description?: string; + clickable_description?: [{ type: 'link' | 'text'; text: string }]; + }; + type_of_card: 'svg' | 'bvi' | 'vanuatu' | 'labuan' | 'maltainvest'; + toggleCardFlip: jest.Mock; + verification_docs: ['document_number' | 'selfie' | 'identity_document' | 'name_and_address' | 'not_applicable']; + }; + const mock_props: TMockProps = { + account_status: { + authentication: { + document: { + status: 'none', + }, + identity: { + services: { + idv: { + status: 'none', + }, + onfido: { + status: 'none', + }, + manual: { + status: 'none', + }, + }, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none', + prompt_client_to_authenticate: 0, + risk_classification: '', + status: [''], + }, + card_section_item: { + key: '', + title: 'Test Title', + title_indicators: { + type: 'displayText', + display_text: 'Test Title Indicators Text', + display_text_skin_color: '', + }, + description: 'Test Description', + }, + type_of_card: Jurisdiction.SVG, + toggleCardFlip: jest.fn(), + verification_docs: ['not_applicable'], + }; + + it('should render JurisdictionCardSection component', () => { + render(); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.getByText('Test Title Indicators Text')).toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + }); + + it('should render JurisdictionCardSection component with clickable description', () => { + const mock_props_with_clickable_description = { + ...mock_props, + card_section_item: { + ...mock_props.card_section_item, + clickable_description: [{ type: 'link' as const, text: 'Test Link' }], + }, + }; + + render(); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.getByText('Test Title Indicators Text')).toBeInTheDocument(); + expect(screen.getByText('Test Link')).toBeInTheDocument(); + expect(screen.queryByText('Test Description')).not.toBeInTheDocument(); + }); + + it('should render JurisdictionCardSection component without displaying title indicators if it is empty', () => { + mock_props.card_section_item.title_indicators = undefined; + render(); + expect(screen.getByText('Test Title')).toBeInTheDocument(); + expect(screen.queryByText('Test Title Indicators Text')).not.toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card.spec.tsx new file mode 100644 index 000000000000..c829772cd3b5 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-card.spec.tsx @@ -0,0 +1,257 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import JurisdictionCard from '../jurisdiction-card'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionCard', () => { + type TMockProps = { + account_status: { + authentication: { + document: { + status: 'none' | 'pending' | 'expired' | 'verified' | 'rejected'; + }; + identity: { + services: { + idv: { + status: 'none' | 'pending' | 'expired' | 'verified' | 'rejected'; + }; + onfido: { + status: 'none' | 'pending' | 'expired' | 'verified' | 'rejected'; + }; + manual: { + status: 'none' | 'pending' | 'expired' | 'verified' | 'rejected'; + }; + }; + }; + needs_verification: string[]; + }; + currency_config: { + [k: string]: { is_deposit_suspended?: 0 | 1; is_withdrawal_suspended?: 0 | 1 }; + }; + p2p_status: 'none' | 'active' | 'temp_ban' | 'perm_ban'; + prompt_client_to_authenticate: 0 | 1; + risk_classification: string; + status: string[]; + }; + account_type: 'financial' | 'synthetic'; + disabled: boolean; + is_onfido_design: boolean; + jurisdiction_selected_shortcode: string; + setJurisdictionSelectedShortcode: jest.Mock; + type_of_card: 'svg' | 'bvi' | 'labuan' | 'maltainvest' | 'vanuatu'; + }; + + let mock_props: TMockProps = { + account_status: { + authentication: { + document: { + status: 'none', + }, + identity: { + services: { + idv: { + status: 'none', + }, + onfido: { + status: 'none', + }, + manual: { + status: 'none', + }, + }, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none', + prompt_client_to_authenticate: 0, + risk_classification: '', + status: [''], + }, + account_type: 'financial', + disabled: false, + is_onfido_design: false, + jurisdiction_selected_shortcode: '', + setJurisdictionSelectedShortcode: jest.fn(), + type_of_card: Jurisdiction.SVG, + }; + beforeEach(() => { + mock_props = { + account_status: { + authentication: { + document: { + status: 'none', + }, + identity: { + services: { + idv: { + status: 'none', + }, + onfido: { + status: 'none', + }, + manual: { + status: 'none', + }, + }, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none', + prompt_client_to_authenticate: 0, + risk_classification: '', + status: [''], + }, + account_type: 'financial', + disabled: false, + is_onfido_design: false, + jurisdiction_selected_shortcode: '', + setJurisdictionSelectedShortcode: jest.fn(), + type_of_card: Jurisdiction.SVG, + }; + }); + + it('should render JurisdictionCard with svg card', () => { + render(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('170+')).toBeInTheDocument(); + expect(screen.getByText('Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.6 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with vanuatu card', () => { + mock_props.type_of_card = Jurisdiction.VANUATU; + render(); + expect(screen.getByText('Vanuatu')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('90+')).toBeInTheDocument(); + expect(screen.getByText('Forex, Stock indices, Commodities and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.5 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect(screen.getByText('Learn more')).toBeInTheDocument(); + expect(screen.getByText('about verifications needed.')).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Vanuatu Financial Services Commission')).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with maltainvest card', () => { + mock_props.type_of_card = Jurisdiction.MALTA_INVEST; + render(); + expect(screen.getByText('Malta')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('140+')).toBeInTheDocument(); + expect( + screen.getByText('Synthetics, Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies') + ).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:30')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.5 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect(screen.getByText('Learn more')).toBeInTheDocument(); + expect(screen.getByText('about verifications needed.')).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect( + screen.getByText('Malta Financial Services Authority (MFSA) (licence no. IS/70156)') + ).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with bvi card', () => { + mock_props.type_of_card = Jurisdiction.BVI; + render(); + expect(screen.getByText('British Virgin Islands')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('170+')).toBeInTheDocument(); + expect(screen.getByText('Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.5 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect(screen.getByText('Learn more')).toBeInTheDocument(); + expect(screen.getByText('about verifications needed.')).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect( + screen.getByText('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)') + ).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with labuan card', () => { + mock_props.type_of_card = Jurisdiction.LABUAN; + render(); + expect(screen.getByText('Straight-through processing')).toBeInTheDocument(); + expect(screen.getByText('Labuan')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('90+')).toBeInTheDocument(); + expect(screen.getByText('Forex and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:100')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.6 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect(screen.getByText('Learn more')).toBeInTheDocument(); + expect(screen.getByText('about verifications needed.')).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Labuan Financial Services Authority (licence no. MB/18/0024)')).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with synthetic account_type', () => { + mock_props.account_type = 'synthetic'; + render(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('40+')).toBeInTheDocument(); + expect(screen.getByText('Synthetics, Basket indices and Derived FX')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + }); + + it('should render JurisdictionCard with disabled to be true', () => { + mock_props.disabled = true; + render(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + }); + + it('should render JurisdictionCard on the back', () => { + render(); + expect(screen.getByText('We need you to submit these in order to get this account:')).toBeInTheDocument(); + expect(screen.getByText('Your document is pending for verification.')).toBeInTheDocument(); + expect(screen.getByText('Verification failed. Resubmit during account creation.')).toBeInTheDocument(); + expect(screen.getByText('Your document is verified.')).toBeInTheDocument(); + }); + + it('should click on JurisdictionCard and render setJurisdictionSelectedShortCode function', () => { + render(); + const jurisdiction_card = screen.getByTestId('dt_jurisdiction_card'); + jurisdiction_card.click(); + expect(mock_props.setJurisdictionSelectedShortcode).toHaveBeenCalledWith('svg'); + }); + + it('should click on Learn More and include cfd-card-flipped into classnames', () => { + mock_props.type_of_card = Jurisdiction.BVI; + render(); + const learn_more = screen.getByText('Learn more'); + learn_more.click(); + expect(screen.getByTestId('dt_jurisdiction_card')).toHaveClass('cfd-card-flipped'); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-clickable-description.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-clickable-description.spec.tsx new file mode 100644 index 000000000000..a481b9d0f949 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-clickable-description.spec.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import JurisdictionClickableDescription from '../jurisdiction-clickable-description'; + +describe('JurisdictionClickableDescription', () => { + type TClickableDescription = { text: string; type: 'link' | 'text' }; + type TMockProps = { + clickable_description: TClickableDescription[]; + toggleCardFlip: jest.Mock; + }; + + const mock_props: TMockProps = { + clickable_description: [ + { + text: 'Click here', + type: 'link', + }, + { + text: 'to learn more about the documents required for verification.', + type: 'text', + }, + ], + toggleCardFlip: jest.fn(), + }; + + it('should render JurisdictionClickableDescription', () => { + render(); + const container = screen.getByTestId('dt_jurisdiction_clickable_description'); + expect(container).toHaveClass('cfd-card-clickable-description-link'); + expect(screen.getByText('Click here')).toBeInTheDocument(); + expect(screen.getByText('to learn more about the documents required for verification.')).toBeInTheDocument(); + }); + + it('should call toggleCardFlip when link is clicked', () => { + render(); + screen.getByText('Click here').click(); + expect(mock_props.toggleCardFlip).toHaveBeenCalled(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-checkbox.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-checkbox.spec.tsx new file mode 100644 index 000000000000..cd3c68591b2f --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-checkbox.spec.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import JurisdictionModalCheckbox from '../jurisdiction-modal-checkbox'; +import RootStore from 'Stores/index'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionModalCheckbox', () => { + const mock_store = { + client: {}, + common: {}, + ui: {}, + }; + const mockRootStore = new RootStore(mock_store); + + const mock_props = { + class_name: '', + is_checked: false, + jurisdiction_selected_shortcode: '', + onCheck: jest.fn(), + context: mockRootStore, + should_restrict_bvi_account_creation: false, + should_restrict_vanuatu_account_creation: false, + }; + + it('should not render JurisdictionModalCheckbox when jurisdiction is not selected', () => { + render(); + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + }); + + it('should render labuan account and displays checkbox', () => { + render(); + expect(screen.queryByRole('checkbox')).toBeInTheDocument(); + }); + + it('should render function onCheck when checkbox is clicked for labuan account', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + fireEvent.click(checkbox); + expect(mock_props.onCheck).toHaveBeenCalled(); + }); + + it('should render svg account without displaying checkbox', () => { + render(); + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + }); + + it('should render bvi account without restriction and displays checkbox', () => { + render(); + expect(screen.queryByRole('checkbox')).toBeInTheDocument(); + }); + + it('should render function onCheck when checkbox is clicked for bvi account without restriction', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + fireEvent.click(checkbox); + expect(mock_props.onCheck).toHaveBeenCalled(); + }); + + it('should render bvi account with restriction and does not display checkbox', () => { + render( + + ); + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + }); + + it('should render vanuatu account without restriction and displays checkbox', () => { + render(); + expect(screen.queryByRole('checkbox')).toBeInTheDocument(); + }); + + it('should render function onCheck when checkbox is clicked for vanuatu account without restriction', () => { + render(); + const checkbox = screen.getByRole('checkbox'); + fireEvent.click(checkbox); + expect(mock_props.onCheck).toHaveBeenCalled(); + }); + + it('should render vanuatu account with restriction and does not display checkbox', () => { + render( + + ); + expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-content.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-content.spec.tsx new file mode 100644 index 000000000000..04accae4ccb9 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-content.spec.tsx @@ -0,0 +1,313 @@ +import React from 'react'; +import RootStore from 'Stores/index'; +import { render, screen } from '@testing-library/react'; +import { Jurisdiction } from '@deriv/shared'; +import JurisdictionModalContent from '../jurisdiction-modal-content'; + +describe('JurisdictionModalContent', () => { + const mock_store = { + common: {}, + client: {}, + ui: {}, + }; + const mock_context = new RootStore(mock_store); + const mock_props = { + account_status: mock_context.client, + account_type: '', + is_onfido_design: false, + is_virtual: false, + jurisdiction_selected_shortcode: '', + setJurisdictionSelectedShortcode: jest.fn(), + synthetic_available_accounts: [ + { + market_type: 'gaming' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.SVG, + sub_account_type: '', + }, + { + market_type: 'gaming' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.BVI, + sub_account_type: '', + }, + { + market_type: 'gaming' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.VANUATU, + sub_account_type: '', + }, + ], + financial_available_accounts: [ + { + market_type: 'financial' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.SVG, + sub_account_type: '', + }, + { + market_type: 'financial' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.BVI, + sub_account_type: '', + }, + { + market_type: 'financial' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.VANUATU, + sub_account_type: '', + }, + { + market_type: 'financial' as const, + name: '', + requirements: { + after_first_deposit: { + financial_assessment: [''], + }, + compliance: { + mt5: [''], + tax_information: [''], + }, + signup: [''], + }, + shortcode: Jurisdiction.LABUAN, + sub_account_type: '', + }, + ], + context: mock_context, + real_synthetic_accounts_existing_data: [], + real_financial_accounts_existing_data: [], + card_flip_status: { + svg: false, + bvi: false, + vanuatu: false, + labuan: false, + maltainvest: false, + }, + flipCard: jest.fn(), + }; + + it('should display cfd-jurisdiction-card--synthetic__wrapper in class name', () => { + render(); + const container = screen.getByTestId('dt-jurisdiction-modal-content'); + expect(container).toHaveClass('cfd-jurisdiction-card--synthetic__wrapper'); + }); + + it('should display 3 types of jurisdiction card for synthetics account', () => { + render(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('British Virgin Islands')).toBeInTheDocument(); + expect(screen.getByText('Vanuatu')).toBeInTheDocument(); + }); + + it('should display content of 3 types of jurisdiction correctly for synthetics account', () => { + render(); + expect(screen.getAllByText('Assets')).toHaveLength(3); + expect(screen.getAllByText('Synthetics, Basket indices and Derived FX')).toHaveLength(3); + expect(screen.getAllByText('40+')).toHaveLength(3); + expect(screen.getAllByText('Leverage')).toHaveLength(3); + expect(screen.getAllByText('1:1000')).toHaveLength(3); + expect(screen.getAllByText('Verifications')).toHaveLength(3); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getAllByText('Learn more')).toHaveLength(2); + expect(screen.getAllByText('about verifications needed.')).toHaveLength(2); + expect(screen.getAllByText('Regulator/EDR')).toHaveLength(3); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + expect( + screen.getByText('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)') + ).toBeInTheDocument(); + expect(screen.getByText('Vanuatu Financial Services Commission')).toBeInTheDocument(); + }); + + it('should display cfd-jurisdiction-card--financial__wrapper in class name', () => { + render(); + const container = screen.getByTestId('dt-jurisdiction-modal-content'); + expect(container).toHaveClass('cfd-jurisdiction-card--financial__wrapper'); + }); + + it('should display 4 types of jurisdiction card for financial account', () => { + render(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('British Virgin Islands')).toBeInTheDocument(); + expect(screen.getByText('Vanuatu')).toBeInTheDocument(); + expect(screen.getByText('Labuan')).toBeInTheDocument(); + }); + + it('should display content of 4 types of jurisdiction correctly for synthetics account', () => { + render(); + expect(screen.getAllByText('Assets')).toHaveLength(4); + expect(screen.getAllByText('Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies')).toHaveLength(2); + expect(screen.getByText('Forex, Stock indices, Commodities and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Forex and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getAllByText('Leverage')).toHaveLength(4); + expect(screen.getAllByText('1:1000')).toHaveLength(3); + expect(screen.getByText('1:100')).toBeInTheDocument(); + expect(screen.getAllByText('Spreads from')).toHaveLength(4); + expect(screen.getAllByText('0.6 pips')).toHaveLength(2); + expect(screen.getAllByText('0.5 pips')).toHaveLength(2); + expect(screen.getAllByText('Verifications')).toHaveLength(4); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getAllByText('Learn more')).toHaveLength(3); + expect(screen.getAllByText('about verifications needed.')).toHaveLength(3); + expect(screen.getAllByText('Regulator/EDR')).toHaveLength(4); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + expect( + screen.getByText('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)') + ).toBeInTheDocument(); + expect(screen.getByText('Vanuatu Financial Services Commission')).toBeInTheDocument(); + expect(screen.getByText('Labuan Financial Services Authority (licence no. MB/18/0024)')).toBeInTheDocument(); + }); + + it('should display only financial maltainvest for MF clients', () => { + mock_props.financial_available_accounts = [ + { ...mock_props.financial_available_accounts[0], shortcode: Jurisdiction.MALTA_INVEST }, + ]; + mock_props.synthetic_available_accounts = []; + render(); + const container = screen.getByTestId('dt-jurisdiction-modal-content'); + expect(container).toHaveClass('cfd-jurisdiction-card--financial__wrapper'); + expect(screen.queryByText('St. Vincent & Grenadines')).not.toBeInTheDocument(); + expect(screen.queryByText('British Virgin Islands')).not.toBeInTheDocument(); + expect(screen.queryByText('Vanuatu')).not.toBeInTheDocument(); + expect(screen.queryByText('Labuan')).not.toBeInTheDocument(); + expect(screen.getByText('Malta')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('140+')).toBeInTheDocument(); + expect( + screen.getByText('Synthetics, Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies') + ).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:30')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.5 pips')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect(screen.getByText('Learn more')).toBeInTheDocument(); + expect(screen.getByText('about verifications needed.')).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect( + screen.getByText('Malta Financial Services Authority (MFSA) (licence no. IS/70156)') + ).toBeInTheDocument(); + }); + + it('should display only financial svg for highrisk clients', () => { + mock_props.financial_available_accounts = [ + { ...mock_props.financial_available_accounts[0], shortcode: Jurisdiction.SVG }, + ]; + mock_props.synthetic_available_accounts = [ + { ...mock_props.synthetic_available_accounts[0], shortcode: Jurisdiction.SVG }, + ]; + render(); + const container = screen.getByTestId('dt-jurisdiction-modal-content'); + expect(container).toHaveClass('cfd-jurisdiction-card--financial__wrapper'); + expect(screen.queryByText('British Virgin Islands')).not.toBeInTheDocument(); + expect(screen.queryByText('Vanuatu')).not.toBeInTheDocument(); + expect(screen.queryByText('Labuan')).not.toBeInTheDocument(); + expect(screen.queryByText('Malta')).not.toBeInTheDocument(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + expect(screen.getByText('170+')).toBeInTheDocument(); + expect(screen.getByText('Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies')).toBeInTheDocument(); + expect(screen.getByText('Spreads from')).toBeInTheDocument(); + expect(screen.getByText('0.6 pips')).toBeInTheDocument(); + }); + + it('should display only synthetic svg for highrisk clients', () => { + mock_props.financial_available_accounts = [ + { ...mock_props.financial_available_accounts[0], shortcode: Jurisdiction.SVG }, + ]; + mock_props.synthetic_available_accounts = [ + { ...mock_props.synthetic_available_accounts[0], shortcode: Jurisdiction.SVG }, + ]; + render(); + const container = screen.getByTestId('dt-jurisdiction-modal-content'); + expect(container).toHaveClass('cfd-jurisdiction-card--synthetic__wrapper'); + expect(screen.queryByText('British Virgin Islands')).not.toBeInTheDocument(); + expect(screen.queryByText('Vanuatu')).not.toBeInTheDocument(); + expect(screen.queryByText('Labuan')).not.toBeInTheDocument(); + expect(screen.queryByText('Malta')).not.toBeInTheDocument(); + expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument(); + expect(screen.getByText('Assets')).toBeInTheDocument(); + expect(screen.getByText('Leverage')).toBeInTheDocument(); + expect(screen.getByText('1:1000')).toBeInTheDocument(); + expect(screen.getByText('Verifications')).toBeInTheDocument(); + expect( + screen.getByText('You will need to submit proof of identity and address once you reach certain thresholds.') + ).toBeInTheDocument(); + expect(screen.getByText('Regulator/EDR')).toBeInTheDocument(); + expect(screen.getByText('Deriv (SVG) LLC (company no. 273 LLC 2020)')).toBeInTheDocument(); + expect(screen.getByText('40+')).toBeInTheDocument(); + expect(screen.getByText('Synthetics, Basket indices and Derived FX')).toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-foot-note.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-foot-note.spec.tsx new file mode 100644 index 000000000000..ff4227723950 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-modal-foot-note.spec.tsx @@ -0,0 +1,213 @@ +import React from 'react'; +import JurisdictionModalFootNote from '../jurisdiction-modal-foot-note'; +import { render, screen } from '@testing-library/react'; +import RootStore from 'Stores/index'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionModalFootNote', () => { + const mock_store = { + common: {}, + client: {}, + ui: {}, + }; + const mock_context = new RootStore(mock_store); + const mock_props = { + account_status: { + authentication: { + document: { + status: 'none' as const, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none' as const, + prompt_client_to_authenticate: 0 as const, + risk_classification: '', + status: [''], + }, + account_type: '', + context: mock_context, + card_classname: '', + jurisdiction_selected_shortcode: Jurisdiction.SVG, + should_restrict_bvi_account_creation: false, + should_restrict_vanuatu_account_creation: false, + }; + it('should render JurisdictionModalFootNote', () => { + render(); + expect(screen.getByTestId('dt-jurisdiction-footnote')).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote with className', () => { + render(); + const container = screen.getByTestId('dt-jurisdiction-footnote'); + expect(container).toHaveClass('mock_jurisdiction__footnote'); + }); + + it('should render JurisdictionModalFootNote and show svg message', () => { + render( + + ); + expect( + screen.getByText('Add your Deriv MT5 Derived account under Deriv (SVG) LLC (company no. 273 LLC 2020).') + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote without bvi_restriction and show bvi message', () => { + render( + + ); + expect( + screen.getByText( + 'Add your Deriv MT5 Derived account under Deriv (BVI) Ltd, regulated by the British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114).' + ) + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote with bvi_restriction and show bvi restriction message', () => { + render( + + ); + expect( + screen.getByText('To create this account first we need you to resubmit your proof of address.') + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote with bvi_restriction and poa is pending, then display resubmit poa message', () => { + const mock_account_status = { + authentication: { + document: { + status: 'pending' as const, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none' as const, + prompt_client_to_authenticate: 0 as const, + risk_classification: '', + status: [''], + }; + render( + + ); + const poa_message = screen.getByText( + 'You can open this account once your submitted documents have been verified.' + ); + expect(poa_message).toBeInTheDocument(); + expect(poa_message).toHaveClass('mock_jurisdiction__footnote--pending'); + }); + + it('should render JurisdictionModalFootNote without vanuatu_restriction and show vanuatu message', () => { + render( + + ); + expect( + screen.getByText( + 'Add Your Deriv MT5 Derived account under Deriv (V) Ltd, regulated by the Vanuatu Financial Services Commission.' + ) + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote with vanuatu_restriction and show vanuatu restriction message', () => { + render( + + ); + expect( + screen.getByText('To create this account first we need you to resubmit your proof of address.') + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote with vanuatu_restriction and poa is pending, then display resubmit poa message', () => { + const mock_account_status = { + authentication: { + document: { + status: 'pending' as const, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none' as const, + prompt_client_to_authenticate: 0 as const, + risk_classification: '', + status: [''], + }; + render( + + ); + const poa_message = screen.getByText( + 'You can open this account once your submitted documents have been verified.' + ); + expect(poa_message).toBeInTheDocument(); + expect(poa_message).toHaveClass('mock_jurisdiction__footnote--pending'); + }); + + it('should render JurisdictionModalFootNote show labuan message', () => { + render( + + ); + expect( + screen.getByText( + 'Add your Deriv MT5 Derived STP account under Deriv (FX) Ltd regulated by Labuan Financial Services Authority (Licence no. MB/18/0024).' + ) + ).toBeInTheDocument(); + }); + + it('should render JurisdictionModalFootNote show maltainvest message', () => { + render( + + ); + expect( + screen.getByText( + 'Add your Deriv MT5 CFDs account under Deriv Investments (Europe) Limited, regulated by the Malta Financial Services Authority (MFSA) (licence no. IS/70156).' + ) + ).toBeInTheDocument(); + }); + + it('should not render JurisdictionModalFootNote when jurisdiction_shortcode is empty', () => { + render(); + expect(screen.queryByTestId('dt-jurisdiction-footnote')).not.toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-title-indicator.spec.tsx b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-title-indicator.spec.tsx new file mode 100644 index 000000000000..271e3eb81aa2 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/__test__/jurisdiction-title-indicator.spec.tsx @@ -0,0 +1,193 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import JurisdictionTitleIndicator from '../jurisdiction-title-indicator'; +import { TJurisdictionTitleIndicatorProps } from 'Containers/props.types'; +import { Jurisdiction } from '@deriv/shared'; + +describe('JurisdictionTitleIndicator', () => { + const mock_props: TJurisdictionTitleIndicatorProps = { + title_indicators: { + type: 'displayText', + display_text: 'Test Display Text', + }, + type_of_card: Jurisdiction.BVI, + account_status: { + authentication: { + document: { + status: 'none', + }, + identity: { + services: { + idv: { + status: 'none', + }, + onfido: { + status: 'none', + }, + manual: { + status: 'none', + }, + }, + }, + needs_verification: [], + }, + currency_config: {}, + p2p_status: 'none', + prompt_client_to_authenticate: 0, + risk_classification: '', + status: [''], + }, + verification_docs: ['not_applicable'], + }; + it('should render JurisdictionTitleIndicator with displayText', () => { + render(); + expect(screen.getByText('Test Display Text')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons', () => { + mock_props.title_indicators.type = 'displayIcons'; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Default icon variant', () => { + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['document_number']; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Default_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Pending icon variant', () => { + if (mock_props.account_status.authentication?.identity?.services?.idv?.status) { + mock_props.account_status.authentication.identity.services.idv.status = 'pending'; + } + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'pending'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'pending'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['document_number']; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Pending_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Failed icon variant', () => { + if (mock_props.account_status.authentication?.identity?.services?.idv?.status) { + mock_props.account_status.authentication.identity.services.idv.status = 'rejected'; + } + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'rejected'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'rejected'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['document_number']; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Failed_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Verified icon variant', () => { + if (mock_props.account_status.authentication?.identity?.services?.idv?.status) { + mock_props.account_status.authentication.identity.services.idv.status = 'verified'; + } + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'verified'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'verified'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['document_number']; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Verified_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Pending icon variant with type_of_card to be Vanuatu', () => { + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'pending'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'pending'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['selfie']; + mock_props.type_of_card = Jurisdiction.VANUATU; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Pending_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Pending icon variant with type_of_card to be MaltaInvest', () => { + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'pending'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'pending'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['identity_document']; + mock_props.type_of_card = Jurisdiction.MALTA_INVEST; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Pending_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Failed icon variant with type_of_card to be Vanuatu', () => { + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'rejected'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'rejected'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['selfie']; + mock_props.type_of_card = Jurisdiction.VANUATU; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Failed_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Verified icon variant with type_of_card to be Vanuatu', () => { + if (mock_props.account_status.authentication?.identity?.services?.onfido?.status) { + mock_props.account_status.authentication.identity.services.onfido.status = 'verified'; + } + if (mock_props.account_status.authentication?.identity?.services?.manual?.status) { + mock_props.account_status.authentication.identity.services.manual.status = 'verified'; + } + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['selfie']; + mock_props.type_of_card = Jurisdiction.VANUATU; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Verified_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Pending icon variant when verification_document is name_and_address and type_of_card to be svg', () => { + if (mock_props.account_status.authentication?.document?.status) + mock_props.account_status.authentication.document.status = 'pending'; + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['name_and_address']; + mock_props.type_of_card = Jurisdiction.SVG; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Pending_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Failed icon variant when verification_document is name_and_address and type_of_card to be svg', () => { + if (mock_props.account_status.authentication?.document?.status) + mock_props.account_status.authentication.document.status = 'rejected'; + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['name_and_address']; + mock_props.type_of_card = Jurisdiction.SVG; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Failed_icon')).toBeInTheDocument(); + }); + + it('should render JurisdictionTitleIndicator with displayIcons and Verified icon variant when verification_document is name_and_address and type_of_card to be svg', () => { + if (mock_props.account_status.authentication?.document?.status) + mock_props.account_status.authentication.document.status = 'verified'; + mock_props.title_indicators.type = 'displayIcons'; + mock_props.verification_docs = ['name_and_address']; + mock_props.type_of_card = Jurisdiction.SVG; + render(); + expect(screen.getByTestId('dt_jurisdiction_title_indicator_Verified_icon')).toBeInTheDocument(); + }); +}); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-back.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-back.tsx new file mode 100644 index 000000000000..52431c484a6a --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-back.tsx @@ -0,0 +1,71 @@ +import classNames from 'classnames'; +import React from 'react'; +import { Icon, Text } from '@deriv/components'; +import { jurisdictionVerificationContents } from 'Constants/jurisdiction-contents/jurisdiction-verification-contents'; +import { TJurisdictionCardBackProps } from 'Containers/props.types'; + +const JurisdictionCardBack = ({ + card_classname, + is_card_selected, + toggleCardFlip, + verification_docs, +}: TJurisdictionCardBackProps) => ( +
+
+
+ +
+ + {jurisdictionVerificationContents().short_description} + +
+ {verification_docs?.map(verification_item => ( +
+
+ +
+ + {jurisdictionVerificationContents().required_verification_docs[verification_item]?.text} + +
+ ))} +
+
+
+ {jurisdictionVerificationContents().status_references.map(status_item => ( +
+
+ +
+ + {status_item.text} + +
+ ))} +
+
+
+); + +export default JurisdictionCardBack; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx deleted file mode 100644 index 0ddd4b06fc90..000000000000 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import React from 'react'; -import RootStore from '../../Stores/index'; -import { connect } from '../../Stores/connect'; -import { getAuthenticationStatusInfo } from '@deriv/shared'; -import { Text } from '@deriv/components'; -import { Localize } from '@deriv/translations'; -import { TVerificationStatusBannerProps } from '../props.types'; - -const VerificationStatusBanner = ({ - account_status, - account_type, - card_classname, - disabled, - context, - is_virtual, - type_of_card, - should_restrict_bvi_account_creation, - should_restrict_vanuatu_account_creation, - real_synthetic_accounts_existing_data, - real_financial_accounts_existing_data, -}: TVerificationStatusBannerProps) => { - const { - poi_not_submitted_for_vanuatu_maltainvest, - poi_and_poa_not_submitted, - poi_resubmit_for_vanuatu_maltainvest, - poi_resubmit_for_bvi_labuan, - need_poa_resubmission, - need_poi_for_bvi_labuan, - poa_pending, - poi_acknowledged_for_vanuatu_maltainvest, - poi_acknowledged_for_bvi_labuan, - poa_not_submitted, - } = getAuthenticationStatusInfo(account_status); - - const getAccountTitle = () => { - switch (account_type) { - case 'synthetic': - return 'Derived'; - case 'financial': - return 'Financial'; - default: - return ''; - } - }; - - const is_svg = type_of_card === 'svg'; - const is_vanuatu = type_of_card === 'vanuatu'; - const is_bvi = type_of_card === 'bvi'; - const is_labuan = type_of_card === 'labuan'; - const is_maltainvest = type_of_card === 'maltainvest'; - - const getTypeTitle = () => { - switch (type_of_card) { - case 'bvi': - return 'BVI'; - case 'vanuatu': - return 'Vanuatu'; - case 'labuan': - return 'STP'; - default: - return ''; - } - }; - - const isAccountCreated = () => - account_type === 'synthetic' - ? real_synthetic_accounts_existing_data?.some(account => account.landing_company_short === type_of_card) - : real_financial_accounts_existing_data?.some(account => account.landing_company_short === type_of_card); - - if (disabled && isAccountCreated()) { - // account added - return ( -
- - - -
- ); - } else if (is_virtual && !is_svg) { - return ( -
- - - -
- ); - } else if (is_svg) { - return ( -
- - - -
- ); - } else if (poi_and_poa_not_submitted) { - // if poi or poa is not submitted - return ( -
- - - -
- ); - } else if (is_vanuatu && poi_not_submitted_for_vanuatu_maltainvest) { - return ( -
- - - -
- ); - } else if ( - (is_bvi && should_restrict_bvi_account_creation) || - (is_vanuatu && should_restrict_vanuatu_account_creation) - ) { - if (poa_pending) { - return ( -
- - - -
- ); - } - return ( -
- - - -
- ); - } else if ( - ((is_bvi || is_labuan) && poi_acknowledged_for_vanuatu_maltainvest && poa_not_submitted) || - ((is_vanuatu || is_maltainvest) && poi_acknowledged_for_bvi_labuan && poa_not_submitted) - ) { - return ( -
- - - -
- ); - } else if ( - ((is_bvi || is_labuan) && need_poi_for_bvi_labuan && need_poa_resubmission) || - ((is_vanuatu || is_maltainvest) && poi_resubmit_for_vanuatu_maltainvest && need_poa_resubmission) - ) { - return ( -
- - - -
- ); - } else if ( - ((is_bvi || is_labuan) && poi_resubmit_for_bvi_labuan) || - ((is_vanuatu || is_maltainvest) && poi_resubmit_for_vanuatu_maltainvest) - ) { - return ( -
- - - -
- ); - } else if (!is_svg && need_poa_resubmission) { - return ( -
- - - -
- ); - } - return null; -}; - -const JurisdictionCardBanner = (props: TVerificationStatusBannerProps) => { - return ( -
- -
- ); -}; - -export default connect(({ modules: { cfd }, client }: RootStore) => ({ - account_status: client.account_status, - is_virtual: client.is_virtual, - should_restrict_bvi_account_creation: client.should_restrict_bvi_account_creation, - should_restrict_vanuatu_account_creation: client.should_restrict_vanuatu_account_creation, - real_financial_accounts_existing_data: cfd.real_financial_accounts_existing_data, - real_synthetic_accounts_existing_data: cfd.real_synthetic_accounts_existing_data, -}))(JurisdictionCardBanner); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-front.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-front.tsx new file mode 100644 index 000000000000..7a08da70dac3 --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-front.tsx @@ -0,0 +1,82 @@ +import classNames from 'classnames'; +import React from 'react'; +import { Text } from '@deriv/components'; +import { Localize } from '@deriv/translations'; +import { TJurisdictionCardFrontProps } from 'Containers/props.types'; +import JurisdictionCardSection from './jurisdiction-card-section'; + +const JurisdictionCardFront = ({ + account_status, + card_classname, + card_data, + card_values, + disabled, + is_card_selected, + toggleCardFlip, + type_of_card, + verification_docs, +}: TJurisdictionCardFrontProps) => ( +
+
+ {card_values.is_over_header_available ? ( + + + + ) : ( +
+ )} + + + +
+ {card_data.map((item, index) => ( + + + {index < card_data.length - 1 &&
} + + ))} +
+ {disabled && ( +
+ + + +
+ )} +
+
+); + +export default JurisdictionCardFront; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-section.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-section.tsx new file mode 100644 index 000000000000..ee7e068062ce --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-section.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Text } from '@deriv/components'; +import { TJurisdictionCardSectionProps } from '../props.types'; +import JurisdictionClickableDescription from './jurisdiction-clickable-description'; +import JurisdictionTitleIndicator from './jurisdiction-title-indicator'; + +const JurisdictionCardSection = ({ + account_status, + card_section_item, + toggleCardFlip, + type_of_card, + verification_docs, +}: TJurisdictionCardSectionProps) => ( +
+
+ + {card_section_item.title} + + {card_section_item.title_indicators && ( + + )} +
+ {(card_section_item.clickable_description || card_section_item.description) && ( +
+ {card_section_item.clickable_description ? ( + + ) : ( + card_section_item.description && ( + + {card_section_item.description} + + ) + )} +
+ )} +
+); + +export default JurisdictionCardSection; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx index bee3284893ce..7e93df75e2b9 100644 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx @@ -1,96 +1,70 @@ -import React from 'react'; import classNames from 'classnames'; -import { Icon, Text, Popover } from '@deriv/components'; -import { Localize, localize } from '@deriv/translations'; -import { getJurisdictionContents } from '../../Constants/jurisdiction-contents'; -import { TJurisdictionCardProps, TJurisdictionCardType } from '../props.types'; -import JurisdictionCardBanner from './jurisdiction-card-banner'; +import React from 'react'; +import { Jurisdiction } from '@deriv/shared'; +import { getJurisdictionContentsFor } from '../../Constants/jurisdiction-contents/jurisdiction-contents'; +import { TJurisdictionCardProps } from '../props.types'; +import JurisdictionCardBack from './jurisdiction-card-back'; +import JurisdictionCardFront from './jurisdiction-card-front'; const JurisdictionCard = ({ + account_status, account_type, disabled, - context, + is_onfido_design = false, jurisdiction_selected_shortcode, - financial_available_accounts, setJurisdictionSelectedShortcode, - synthetic_available_accounts, type_of_card, }: TJurisdictionCardProps) => { const card_classname = `cfd-jurisdiction-card--${account_type}`; - const number_of_synthetic_accounts_to_be_shown = synthetic_available_accounts?.length; - const number_of_financial_accounts_to_be_shown = financial_available_accounts?.length; - const is_synthetic = account_type === 'synthetic'; - const [number_of_cards] = React.useState( - is_synthetic ? number_of_synthetic_accounts_to_be_shown : number_of_financial_accounts_to_be_shown - ); - - const card_values = getJurisdictionContents()[type_of_card as TJurisdictionCardType]; - - const card_data = is_synthetic ? card_values.synthetic_contents : card_values.financial_contents; + const card_values = getJurisdictionContentsFor(type_of_card, is_synthetic); + const card_data = card_values.contents; + const [is_card_flipped, setIsCardFlipped] = React.useState(false); + const is_card_selected = jurisdiction_selected_shortcode === type_of_card; + let verification_docs = card_values.verification_docs; const cardSelection = (cardType: string) => { setJurisdictionSelectedShortcode(jurisdiction_selected_shortcode === cardType ? '' : cardType); }; - const Checkmark = () => ( - - ); + const toggleCardFlip: React.MouseEventHandler = event => { + event.stopPropagation(); + setIsCardFlipped(!is_card_flipped); + }; + + if ([Jurisdiction.BVI, Jurisdiction.VANUATU, Jurisdiction.LABUAN].includes(type_of_card) && is_onfido_design) { + verification_docs = ['selfie', 'identity_document', 'name_and_address']; + } return ( - +
undefined : () => cardSelection(type_of_card)} - style={[1, 2, 3].includes(number_of_cards) ? { width: '32em' } : { width: '27.6em' }} > - {card_values.is_over_header_available && ( -
- - - -
- )} -
- - - - {card_data.map((item, index) => ( -
-
- -
- - - - {/Straight-through processing/.test(item) && ( - - )} -
- ))} -
- +
- +
); }; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-clickable-description.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-clickable-description.tsx new file mode 100644 index 000000000000..81d5aa1b502a --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-clickable-description.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { Text } from '@deriv/components'; +import { TJurisdictionClickableDescriptionProps } from 'Containers/props.types'; + +const JurisdictionClickableDescription = ({ + clickable_description, + toggleCardFlip, +}: TJurisdictionClickableDescriptionProps) => ( +
+ {clickable_description.map(description_part => { + return description_part.type === 'link' ? ( + + + {description_part.text} + +   + + ) : ( + + {description_part.text} + + ); + })} +
+); + +export default JurisdictionClickableDescription; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-checkbox.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-checkbox.tsx index 6b453405b1e1..7de131031f52 100644 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-checkbox.tsx +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-checkbox.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { Checkbox, StaticUrl, Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; +import { isMobile, Jurisdiction } from '@deriv/shared'; import { Localize } from '@deriv/translations'; import { TJurisdictionCheckBoxProps } from '../props.types'; @@ -14,17 +14,15 @@ const JurisdictionCheckBox = ({ should_restrict_vanuatu_account_creation, }: TJurisdictionCheckBoxProps) => { const shouldShowCheckBox = () => { - if (jurisdiction_selected_shortcode) { - if ( - jurisdiction_selected_shortcode === 'svg' || - (jurisdiction_selected_shortcode === 'bvi' && should_restrict_bvi_account_creation) || - (jurisdiction_selected_shortcode === 'vanuatu' && should_restrict_vanuatu_account_creation) - ) { - return false; - } - return true; + if ( + !jurisdiction_selected_shortcode || + jurisdiction_selected_shortcode === Jurisdiction.SVG || + (jurisdiction_selected_shortcode === Jurisdiction.BVI && should_restrict_bvi_account_creation) || + (jurisdiction_selected_shortcode === Jurisdiction.VANUATU && should_restrict_vanuatu_account_creation) + ) { + return false; } - return false; + return true; }; const dbvi_company_names: { [key: string]: { [key: string]: string } } = { diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content-wrapper.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content-wrapper.tsx new file mode 100644 index 000000000000..d6bb85a883ce --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content-wrapper.tsx @@ -0,0 +1,234 @@ +import React from 'react'; +import { Button, Modal } from '@deriv/components'; +import { getAuthenticationStatusInfo, isMobile, Jurisdiction } from '@deriv/shared'; +import { localize } from '@deriv/translations'; +import { TJurisdictionModalContentWrapperProps } from '../props.types'; +import { connect } from '../../Stores/connect'; +import RootStore from '../../Stores/index'; +import JurisdictionModalContent from './jurisdiction-modal-content'; +import JurisdictionCheckBox from './jurisdiction-modal-checkbox'; +import JurisdictionModalFootNote from './jurisdiction-modal-foot-note'; + +const JurisdictionModalContentWrapper = ({ + account_status, + account_type, + context, + fetchAccountSettings, + has_submitted_cfd_personal_details, + is_jurisdiction_modal_visible, + is_virtual, + jurisdiction_selected_shortcode, + openPasswordModal, + real_financial_accounts_existing_data, + real_synthetic_accounts_existing_data, + residence, + residence_list, + setJurisdictionSelectedShortcode, + should_restrict_bvi_account_creation, + should_restrict_vanuatu_account_creation, + show_eu_related_content, + toggleCFDVerificationModal, + trading_platform_available_accounts, + toggleJurisdictionModal, + updateMT5Status, +}: TJurisdictionModalContentWrapperProps) => { + const [checked, setChecked] = React.useState(false); + + const { + poi_or_poa_not_submitted, + poi_acknowledged_for_bvi_labuan, + poi_acknowledged_for_vanuatu_maltainvest, + poa_acknowledged, + need_poa_resubmission, + } = getAuthenticationStatusInfo(account_status); + + React.useEffect(() => { + if (is_jurisdiction_modal_visible) { + if (!is_virtual) { + updateMT5Status(); + fetchAccountSettings(); + } + setJurisdictionSelectedShortcode(''); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [is_jurisdiction_modal_visible]); + + React.useEffect(() => { + if (jurisdiction_selected_shortcode) { + setChecked(false); + } + }, [jurisdiction_selected_shortcode, is_jurisdiction_modal_visible]); + + const financial_available_accounts = trading_platform_available_accounts.filter( + available_account => + available_account.market_type === 'financial' && + (show_eu_related_content + ? available_account.shortcode === 'maltainvest' + : available_account.shortcode !== 'maltainvest') + ); + + const synthetic_available_accounts = trading_platform_available_accounts.filter( + available_account => + available_account.market_type === 'gaming' && + (show_eu_related_content + ? available_account.shortcode === 'maltainvest' + : available_account.shortcode !== 'maltainvest') + ); + + const is_svg_selected = jurisdiction_selected_shortcode === Jurisdiction.SVG; + const is_bvi_selected = jurisdiction_selected_shortcode === Jurisdiction.BVI; + const is_vanuatu_selected = jurisdiction_selected_shortcode === Jurisdiction.VANUATU; + const is_labuan_selected = jurisdiction_selected_shortcode === Jurisdiction.LABUAN; + const is_maltainvest_selected = jurisdiction_selected_shortcode === Jurisdiction.MALTA_INVEST; + + const is_idv_country = + residence_list.find(elem => elem?.value === residence)?.identity?.services?.idv?.is_country_supported === 1; + const has_idv_attempts = (account_status?.authentication?.identity?.services?.idv?.submissions_left ?? 0) > 0; + const is_onfido_design = !is_idv_country || (is_idv_country && !has_idv_attempts); + + const isNextButtonDisabled = () => { + if (jurisdiction_selected_shortcode) { + const is_account_created = + account_type.type === 'synthetic' + ? real_synthetic_accounts_existing_data?.some( + account => account.landing_company_short === jurisdiction_selected_shortcode + ) + : real_financial_accounts_existing_data?.some( + account => account.landing_company_short === jurisdiction_selected_shortcode + ); + + if (!is_account_created) { + if ( + is_svg_selected || + (is_bvi_selected && should_restrict_bvi_account_creation && need_poa_resubmission) || + (is_vanuatu_selected && should_restrict_vanuatu_account_creation && need_poa_resubmission) + ) { + return false; + } + return !checked; + } + return true; + } + return true; + }; + + const onSelectRealAccount = () => { + const type_of_account = { + category: account_type.category, + type: account_type.type, + }; + + if (is_svg_selected) { + openPasswordModal(type_of_account); + } else if (is_vanuatu_selected) { + if ( + poi_acknowledged_for_vanuatu_maltainvest && + !poi_or_poa_not_submitted && + !should_restrict_vanuatu_account_creation && + poa_acknowledged && + has_submitted_cfd_personal_details + ) { + openPasswordModal(type_of_account); + } else { + toggleCFDVerificationModal(); + } + } else if (is_bvi_selected) { + if ( + poi_acknowledged_for_bvi_labuan && + !poi_or_poa_not_submitted && + !should_restrict_bvi_account_creation && + poa_acknowledged && + has_submitted_cfd_personal_details + ) { + openPasswordModal(type_of_account); + } else { + toggleCFDVerificationModal(); + } + } else if (is_labuan_selected) { + if (poi_acknowledged_for_bvi_labuan && poa_acknowledged && has_submitted_cfd_personal_details) { + openPasswordModal(type_of_account); + } else { + toggleCFDVerificationModal(); + } + } else if (is_maltainvest_selected) { + if (poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged) { + openPasswordModal(type_of_account); + } else { + toggleCFDVerificationModal(); + } + } + }; + + return ( + + +
+
+ + setChecked(!checked)} + class_name={`cfd-jurisdiction-card--${account_type.type}__jurisdiction-checkbox`} + jurisdiction_selected_shortcode={jurisdiction_selected_shortcode} + should_restrict_bvi_account_creation={should_restrict_bvi_account_creation} + should_restrict_vanuatu_account_creation={should_restrict_vanuatu_account_creation} + /> +
+ + + +
+
+ ); +}; +export default connect(({ modules: { cfd }, client, traders_hub }: RootStore) => ({ + account_status: client.account_status, + account_type: cfd.account_type, + fetchAccountSettings: client.fetchAccountSettings, + has_submitted_cfd_personal_details: cfd.has_submitted_cfd_personal_details, + is_jurisdiction_modal_visible: cfd.is_jurisdiction_modal_visible, + is_virtual: client.is_virtual, + jurisdiction_selected_shortcode: cfd.jurisdiction_selected_shortcode, + real_financial_accounts_existing_data: cfd.real_financial_accounts_existing_data, + real_synthetic_accounts_existing_data: cfd.real_synthetic_accounts_existing_data, + residence: client.residence, + residence_list: client.residence_list, + setJurisdictionSelectedShortcode: cfd.setJurisdictionSelectedShortcode, + should_restrict_bvi_account_creation: client.should_restrict_bvi_account_creation, + should_restrict_vanuatu_account_creation: client.should_restrict_vanuatu_account_creation, + show_eu_related_content: traders_hub.show_eu_related_content, + toggleCFDVerificationModal: cfd.toggleCFDVerificationModal, + trading_platform_available_accounts: client.trading_platform_available_accounts, + toggleJurisdictionModal: cfd.toggleJurisdictionModal, + updateMT5Status: client.updateMT5Status, +}))(JurisdictionModalContentWrapper); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx index 800cfc63a5e9..64585fb31e5d 100644 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx @@ -1,15 +1,17 @@ import React from 'react'; +import { Jurisdiction } from '@deriv/shared'; import { TJurisdictionModalContentProps } from '../props.types'; import JurisdictionCard from './jurisdiction-card'; const JurisdictionModalContent = ({ + account_status, account_type, + is_onfido_design = false, is_virtual, jurisdiction_selected_shortcode, setJurisdictionSelectedShortcode, synthetic_available_accounts, financial_available_accounts, - context, real_synthetic_accounts_existing_data, real_financial_accounts_existing_data, }: TJurisdictionModalContentProps) => { @@ -28,28 +30,31 @@ const JurisdictionModalContent = ({ ? real_synthetic_accounts_existing_data?.some(account => account.landing_company_short === type_of_card) : real_financial_accounts_existing_data?.some(account => account.landing_company_short === type_of_card); }; - const jurisdiction_cards_array = ['svg', 'bvi', 'vanuatu', 'labuan', 'maltainvest']; + const jurisdiction_cards_array = [ + Jurisdiction.SVG, + Jurisdiction.BVI, + Jurisdiction.VANUATU, + Jurisdiction.LABUAN, + Jurisdiction.MALTA_INVEST, + ]; return ( - -
- {jurisdiction_cards_array.map( - card => - cardsToBeShown(card) && ( - - ) - )} -
-
+
+ {jurisdiction_cards_array.map( + card => + cardsToBeShown(card) && ( + + ) + )} +
); }; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx index a9f4ddec1090..d8c4d305fb1c 100644 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Text } from '@deriv/components'; +import { getAuthenticationStatusInfo, isMobile, Jurisdiction } from '@deriv/shared'; import { Localize } from '@deriv/translations'; -import { getAuthenticationStatusInfo, isMobile } from '@deriv/shared'; import { TJurisdictionModalFootNoteProps } from '../props.types'; const FooterNote = ({ @@ -17,7 +17,7 @@ const FooterNote = ({ const { poa_pending } = getAuthenticationStatusInfo(account_status); - if (jurisdiction_selected_shortcode === 'svg') { + if (jurisdiction_selected_shortcode === Jurisdiction.SVG) { return ( ); } else if ( - (jurisdiction_selected_shortcode === 'bvi' && should_restrict_bvi_account_creation) || - (jurisdiction_selected_shortcode === 'vanuatu' && should_restrict_vanuatu_account_creation) + (jurisdiction_selected_shortcode === Jurisdiction.BVI && should_restrict_bvi_account_creation) || + (jurisdiction_selected_shortcode === Jurisdiction.VANUATU && should_restrict_vanuatu_account_creation) ) { return poa_pending ? ( ); - } else if (jurisdiction_selected_shortcode === 'bvi') { + } else if (jurisdiction_selected_shortcode === Jurisdiction.BVI) { return ( ); - } else if (jurisdiction_selected_shortcode === 'vanuatu') { + } else if (jurisdiction_selected_shortcode === Jurisdiction.VANUATU) { return ( ); - } else if (jurisdiction_selected_shortcode === 'labuan') { + } else if (jurisdiction_selected_shortcode === Jurisdiction.LABUAN) { return ( ); - } else if (jurisdiction_selected_shortcode === 'maltainvest') { + } else if (jurisdiction_selected_shortcode === Jurisdiction.MALTA_INVEST) { return ( ); @@ -68,18 +68,22 @@ const FooterNote = ({ const JurisdictionModalFootNote = (props: TJurisdictionModalFootNoteProps) => { return ( -
- - - -
+ + {props.jurisdiction_selected_shortcode && ( +
+ + + +
+ )} +
); }; diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx index 60bf787fcf05..6bb1325fa1b6 100644 --- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx @@ -1,214 +1,27 @@ import React from 'react'; -import { Button, DesktopWrapper, MobileDialog, MobileWrapper, Modal, UILoader } from '@deriv/components'; +import { DesktopWrapper, MobileDialog, MobileWrapper, Modal, UILoader } from '@deriv/components'; import { localize } from '@deriv/translations'; import { connect } from '../../Stores/connect'; import RootStore from '../../Stores/index'; -import JurisdictionModalContent from './jurisdiction-modal-content'; -import { getAuthenticationStatusInfo, isMobile } from '@deriv/shared'; import { TJurisdictionModalProps } from '../props.types'; -import JurisdictionCheckBox from './jurisdiction-modal-checkbox'; -import JurisdictionModalFootNote from './jurisdiction-modal-foot-note'; +import JurisdictionModalContentWrapper from './jurisdiction-modal-content-wrapper'; const JurisdictionModal = ({ - account_status, account_type, + context, disableApp, enableApp, is_jurisdiction_modal_visible, - context, - is_virtual, - jurisdiction_selected_shortcode, openPasswordModal, - real_synthetic_accounts_existing_data, - real_financial_accounts_existing_data, - trading_platform_available_accounts, - toggleJurisdictionModal, - setJurisdictionSelectedShortcode, - should_restrict_bvi_account_creation, - should_restrict_vanuatu_account_creation, show_eu_related_content, - toggleCFDVerificationModal, - updateMT5Status, - fetchAccountSettings, - has_submitted_cfd_personal_details, + toggleJurisdictionModal, }: TJurisdictionModalProps) => { - const [checked, setChecked] = React.useState(false); - - const { - poi_or_poa_not_submitted, - poi_acknowledged_for_bvi_labuan, - poi_acknowledged_for_vanuatu_maltainvest, - poa_acknowledged, - need_poa_resubmission, - } = getAuthenticationStatusInfo(account_status); - - React.useEffect(() => { - if (is_jurisdiction_modal_visible) { - if (!is_virtual) { - updateMT5Status(); - fetchAccountSettings(); - } - setJurisdictionSelectedShortcode(''); - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [is_jurisdiction_modal_visible]); - - React.useEffect(() => { - if (jurisdiction_selected_shortcode) { - setChecked(false); - } - }, [jurisdiction_selected_shortcode, is_jurisdiction_modal_visible]); - - const financial_available_accounts = trading_platform_available_accounts.filter( - available_account => - available_account.market_type === 'financial' && - (show_eu_related_content - ? available_account.shortcode === 'maltainvest' - : available_account.shortcode !== 'maltainvest') - ); - - const synthetic_available_accounts = trading_platform_available_accounts.filter( - available_account => - available_account.market_type === 'gaming' && - (show_eu_related_content - ? available_account.shortcode === 'maltainvest' - : available_account.shortcode !== 'maltainvest') - ); - const modal_title = show_eu_related_content - ? localize('Jurisdiction for your Deriv MT5 CFDs account') - : localize('Choose a jurisdiction for your MT5 {{account_type}} account', { + ? localize('Choose a jurisdiction for your Deriv MT5 CFDs account') + : localize('Choose a jurisdiction for your Deriv MT5 {{account_type}} account', { account_type: account_type.type === 'synthetic' ? 'Derived' : 'Financial', }); - const is_svg_selected = jurisdiction_selected_shortcode === 'svg'; - const is_bvi_selected = jurisdiction_selected_shortcode === 'bvi'; - const is_vanuatu_selected = jurisdiction_selected_shortcode === 'vanuatu'; - const is_labuan_selected = jurisdiction_selected_shortcode === 'labuan'; - const is_maltainvest_selected = jurisdiction_selected_shortcode === 'maltainvest'; - - const isNextButtonDisabled = () => { - if (jurisdiction_selected_shortcode) { - const is_account_created = - account_type.type === 'synthetic' - ? real_synthetic_accounts_existing_data?.some( - account => account.landing_company_short === jurisdiction_selected_shortcode - ) - : real_financial_accounts_existing_data?.some( - account => account.landing_company_short === jurisdiction_selected_shortcode - ); - - if (!is_account_created) { - if ( - is_svg_selected || - (is_bvi_selected && should_restrict_bvi_account_creation && need_poa_resubmission) || - (is_vanuatu_selected && should_restrict_vanuatu_account_creation && need_poa_resubmission) - ) { - return false; - } - return !checked; - } - return true; - } - return true; - }; - - const onSelectRealAccount = () => { - const type_of_account = { - category: account_type.category, - type: account_type.type, - }; - - if (is_svg_selected) { - openPasswordModal(type_of_account); - } else if (is_vanuatu_selected) { - if ( - poi_acknowledged_for_vanuatu_maltainvest && - !poi_or_poa_not_submitted && - !should_restrict_vanuatu_account_creation && - poa_acknowledged && - has_submitted_cfd_personal_details - ) { - openPasswordModal(type_of_account); - } else { - toggleCFDVerificationModal(); - } - } else if (is_bvi_selected) { - if ( - poi_acknowledged_for_bvi_labuan && - !poi_or_poa_not_submitted && - !should_restrict_bvi_account_creation && - poa_acknowledged && - has_submitted_cfd_personal_details - ) { - openPasswordModal(type_of_account); - } else { - toggleCFDVerificationModal(); - } - } else if (is_labuan_selected) { - if (poi_acknowledged_for_bvi_labuan && poa_acknowledged && has_submitted_cfd_personal_details) { - openPasswordModal(type_of_account); - } else { - toggleCFDVerificationModal(); - } - } else if (is_maltainvest_selected) { - if (poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged) { - openPasswordModal(type_of_account); - } else { - toggleCFDVerificationModal(); - } - } - }; - const ModalContent = () => ( - - -
- - setChecked(!checked)} - class_name={`cfd-jurisdiction-card--${account_type.type}__jurisdiction-checkbox`} - jurisdiction_selected_shortcode={jurisdiction_selected_shortcode} - should_restrict_bvi_account_creation={should_restrict_bvi_account_creation} - should_restrict_vanuatu_account_creation={should_restrict_vanuatu_account_creation} - /> - - - -
-
- ); - return (
}> @@ -223,9 +36,9 @@ const JurisdictionModal = ({ toggleModal={toggleJurisdictionModal} type='button' context={context} - width={account_type.type === 'synthetic' ? '1040px' : '1200px'} + width={account_type.type === 'synthetic' ? '1160px' : '1300px'} > - + @@ -236,7 +49,7 @@ const JurisdictionModal = ({ visible={is_jurisdiction_modal_visible} onClose={toggleJurisdictionModal} > - + @@ -244,27 +57,11 @@ const JurisdictionModal = ({ ); }; -export default connect(({ modules: { cfd }, ui, client, traders_hub }: RootStore) => ({ +export default connect(({ modules: { cfd }, ui, traders_hub }: RootStore) => ({ account_type: cfd.account_type, - account_settings: client.account_settings, - account_status: client.account_status, - content_flag: traders_hub.content_flag, disableApp: ui.disableApp, enableApp: ui.enableApp, is_jurisdiction_modal_visible: cfd.is_jurisdiction_modal_visible, - is_virtual: client.is_virtual, - jurisdiction_selected_shortcode: cfd.jurisdiction_selected_shortcode, - real_financial_accounts_existing_data: cfd.real_financial_accounts_existing_data, - real_synthetic_accounts_existing_data: cfd.real_synthetic_accounts_existing_data, - setAccountSettings: client.setAccountSettings, - setJurisdictionSelectedShortcode: cfd.setJurisdictionSelectedShortcode, - should_restrict_bvi_account_creation: client.should_restrict_bvi_account_creation, - should_restrict_vanuatu_account_creation: client.should_restrict_vanuatu_account_creation, show_eu_related_content: traders_hub.show_eu_related_content, - trading_platform_available_accounts: client.trading_platform_available_accounts, - toggleCFDVerificationModal: cfd.toggleCFDVerificationModal, toggleJurisdictionModal: cfd.toggleJurisdictionModal, - updateMT5Status: client.updateMT5Status, - fetchAccountSettings: client.fetchAccountSettings, - has_submitted_cfd_personal_details: cfd.has_submitted_cfd_personal_details, }))(JurisdictionModal); diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-title-indicator.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-title-indicator.tsx new file mode 100644 index 000000000000..13dd1d564e4a --- /dev/null +++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-title-indicator.tsx @@ -0,0 +1,100 @@ +import React from 'react'; +import classNames from 'classnames'; +import { Icon, Text } from '@deriv/components'; +import { getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared'; +import { jurisdictionVerificationContents } from 'Constants/jurisdiction-contents/jurisdiction-verification-contents'; +import { TJurisdictionTitleIndicatorProps } from 'Containers/props.types'; +import { TJurisdictionCardItemVerificationItem, TJurisdictionCardVerificationStatus } from 'Components/props.types'; + +const JurisdictionTitleIndicator = ({ + account_status, + title_indicators, + type_of_card, + verification_docs, +}: TJurisdictionTitleIndicatorProps) => { + const { + poi_pending_for_bvi_labuan, + poi_resubmit_for_bvi_labuan, + poi_verified_for_bvi_labuan, + poi_pending_for_vanuatu_maltainvest, + poi_resubmit_for_vanuatu_maltainvest, + poi_verified_for_vanuatu_maltainvest, + poa_pending, + need_poa_resubmission, + poa_verified, + } = getAuthenticationStatusInfo(account_status); + + const getVerificationIconVariant = (verification_document: TJurisdictionCardItemVerificationItem): string => { + let icon_variant: TJurisdictionCardVerificationStatus = 'Default'; + if ([Jurisdiction.BVI, Jurisdiction.LABUAN].includes(type_of_card)) { + if (['document_number', 'selfie', 'identity_document'].includes(verification_document)) { + if (poi_pending_for_bvi_labuan) { + icon_variant = 'Pending'; + } else if (poi_resubmit_for_bvi_labuan) { + icon_variant = 'Failed'; + } else if (poi_verified_for_bvi_labuan) { + icon_variant = 'Verified'; + } + } + } else if ([Jurisdiction.VANUATU, Jurisdiction.MALTA_INVEST].includes(type_of_card)) { + if (['document_number', 'selfie', 'identity_document'].includes(verification_document)) { + if (poi_pending_for_vanuatu_maltainvest) { + icon_variant = 'Pending'; + } else if (poi_resubmit_for_vanuatu_maltainvest) { + icon_variant = 'Failed'; + } else if (poi_verified_for_vanuatu_maltainvest) { + icon_variant = 'Verified'; + } + } + } + if (verification_document === 'name_and_address') { + if (poa_pending) { + icon_variant = 'Pending'; + } else if (need_poa_resubmission) { + icon_variant = 'Failed'; + } else if (poa_verified) { + icon_variant = 'Verified'; + } + } + return icon_variant; + }; + + return title_indicators.type === 'displayText' ? ( + + {title_indicators.display_text} + + ) : ( +
+ {verification_docs?.map(verification_document => ( +
+ +
+ ))} +
+ ); +}; + +export default JurisdictionTitleIndicator; diff --git a/packages/cfd/src/Containers/mt5-compare-table-content.tsx b/packages/cfd/src/Containers/mt5-compare-table-content.tsx index e3853ab0663f..40ab17dff174 100644 --- a/packages/cfd/src/Containers/mt5-compare-table-content.tsx +++ b/packages/cfd/src/Containers/mt5-compare-table-content.tsx @@ -2,7 +2,7 @@ import React from 'react'; import classNames from 'classnames'; import { Table, Button, Text, Popover } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { isDesktop, WS, getAuthenticationStatusInfo, CFD_PLATFORMS, ContentFlag } from '@deriv/shared'; +import { isDesktop, WS, getAuthenticationStatusInfo, CFD_PLATFORMS, ContentFlag, Jurisdiction } from '@deriv/shared'; import { connect } from '../Stores/connect'; import RootStore from '../Stores/index'; import { @@ -312,13 +312,13 @@ const DMT5CompareModalContent = ({ case 'synthetic_svg': case 'financial_svg': setAppstorePlatform(CFD_PLATFORMS.MT5); - setJurisdictionSelectedShortcode('svg'); + setJurisdictionSelectedShortcode(Jurisdiction.SVG); openPasswordModal(type_of_account); break; case 'synthetic_bvi': case 'financial_bvi': setAppstorePlatform(CFD_PLATFORMS.MT5); - setJurisdictionSelectedShortcode('bvi'); + setJurisdictionSelectedShortcode(Jurisdiction.BVI); if ( poi_acknowledged_for_bvi_labuan && !poi_or_poa_not_submitted && @@ -334,7 +334,7 @@ const DMT5CompareModalContent = ({ case 'synthetic_vanuatu': case 'financial_vanuatu': setAppstorePlatform(CFD_PLATFORMS.MT5); - setJurisdictionSelectedShortcode('vanuatu'); + setJurisdictionSelectedShortcode(Jurisdiction.VANUATU); if ( poi_acknowledged_for_vanuatu_maltainvest && !poi_or_poa_not_submitted && @@ -349,7 +349,7 @@ const DMT5CompareModalContent = ({ break; case 'financial_labuan': setAppstorePlatform(CFD_PLATFORMS.MT5); - setJurisdictionSelectedShortcode('labuan'); + setJurisdictionSelectedShortcode(Jurisdiction.LABUAN); if (poi_acknowledged_for_bvi_labuan && poa_acknowledged && has_submitted_personal_details) { openPasswordModal(type_of_account); } else { @@ -358,7 +358,7 @@ const DMT5CompareModalContent = ({ break; case 'financial_maltainvest': setAppstorePlatform(CFD_PLATFORMS.MT5); - setJurisdictionSelectedShortcode('maltainvest'); + setJurisdictionSelectedShortcode(Jurisdiction.MALTA_INVEST); if ((poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged) || is_demo_tab) { openPasswordModal(type_of_account); } else { diff --git a/packages/cfd/src/Containers/props.types.ts b/packages/cfd/src/Containers/props.types.ts index 37856780cca8..6d359a67138d 100644 --- a/packages/cfd/src/Containers/props.types.ts +++ b/packages/cfd/src/Containers/props.types.ts @@ -1,3 +1,4 @@ +import React from 'react'; import { DetailsOfEachMT5Loginid, GetAccountStatus, @@ -8,7 +9,15 @@ import { } from '@deriv/api-types'; import { FormikHelpers as FormikActions } from 'formik'; import { TCFDPasswordFormValues } from './cfd-password-modal'; -import { TTradingPlatformAvailableAccount, TExistingData } from '../Components/props.types'; +import { + TTradingPlatformAvailableAccount, + TExistingData, + TJurisdictionCardSection, + TJurisdictionCardSectionTitleIndicators, + TClickableDescription, + TJurisdictionCardItems, + TJurisdictionCardItemVerification, +} from '../Components/props.types'; import RootStore from '../Stores/index'; export type TCFDPersonalDetailsContainerProps = { @@ -162,14 +171,48 @@ export type TCFDPasswordManagerModal = { }; export type TJurisdictionCardProps = { + account_status: GetAccountStatus; + account_type: string; + disabled: boolean; + is_onfido_design: boolean; jurisdiction_selected_shortcode: string; - context: RootStore; - synthetic_available_accounts: TTradingPlatformAvailableAccount[]; - financial_available_accounts: TTradingPlatformAvailableAccount[]; setJurisdictionSelectedShortcode: (card_type: string) => void; - account_type: string; - type_of_card: string; + type_of_card: TJurisdictionCardType; +}; + +export type TJurisdictionCardBackProps = { + card_classname: string; + is_card_selected: boolean; + toggleCardFlip: React.MouseEventHandler; + verification_docs: TJurisdictionCardItemVerification | undefined; +}; + +export type TJurisdictionCardFrontProps = TJurisdictionCardBackProps & { + account_status: GetAccountStatus; + card_data: TJurisdictionCardSection[]; + card_values: TJurisdictionCardItems; disabled: boolean; + type_of_card: TJurisdictionCardType; +}; + +export type TJurisdictionClickableDescriptionProps = { + clickable_description: Array; + toggleCardFlip: React.MouseEventHandler; +}; + +export type TJurisdictionTitleIndicatorProps = { + account_status: GetAccountStatus; + title_indicators: TJurisdictionCardSectionTitleIndicators; + type_of_card: TJurisdictionCardType; + verification_docs: TJurisdictionCardItemVerification | undefined; +}; + +export type TJurisdictionCardSectionProps = { + account_status: GetAccountStatus; + card_section_item: TJurisdictionCardSection; + toggleCardFlip: React.MouseEventHandler; + type_of_card: TJurisdictionCardType; + verification_docs: TJurisdictionCardItemVerification | undefined; }; export type TJurisdictionCardType = 'svg' | 'bvi' | 'vanuatu' | 'labuan' | 'maltainvest'; @@ -202,36 +245,45 @@ type TOpenAccountTransferMeta = { type?: string; }; -export type TJurisdictionModalProps = { +type TJurisdictionModalCommonProps = { account_type: { type: string; category: string; }; - account_status: GetAccountStatus; context: RootStore; - disableApp: () => void; - enableApp: () => void; is_jurisdiction_modal_visible: boolean; + openPasswordModal: (account_type: TOpenAccountTransferMeta) => void; + show_eu_related_content: boolean; + toggleJurisdictionModal: () => void; +}; + +export type TJurisdictionModalContentWrapperProps = TJurisdictionModalCommonProps & { + account_status: GetAccountStatus; + fetchAccountSettings: () => void; + has_submitted_cfd_personal_details: boolean; is_virtual: boolean; jurisdiction_selected_shortcode: string; - openPasswordModal: (account_type: TOpenAccountTransferMeta) => void; + real_financial_accounts_existing_data: TExistingData; + real_synthetic_accounts_existing_data: TExistingData; + residence: string; + residence_list: ResidenceList; setJurisdictionSelectedShortcode: (shortcode: string) => void; should_restrict_bvi_account_creation: boolean; should_restrict_vanuatu_account_creation: boolean; - show_eu_related_content: boolean; - trading_platform_available_accounts: TTradingPlatformAvailableAccount[]; - fetchAccountSettings: () => void; - toggleJurisdictionModal: () => void; toggleCFDVerificationModal: () => void; - real_synthetic_accounts_existing_data: TExistingData; - real_financial_accounts_existing_data: TExistingData; + trading_platform_available_accounts: TTradingPlatformAvailableAccount[]; updateMT5Status: () => void; - has_submitted_cfd_personal_details: boolean; +}; + +export type TJurisdictionModalProps = TJurisdictionModalCommonProps & { + disableApp: () => void; + enableApp: () => void; }; export type TJurisdictionModalContentProps = { - context: RootStore; + account_status: GetAccountStatus; account_type: string; + is_onfido_design: boolean; jurisdiction_selected_shortcode: string; setJurisdictionSelectedShortcode: (card_type: string) => void; synthetic_available_accounts: TTradingPlatformAvailableAccount[]; 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 0de741e45e0f..0785f3b59305 100644 --- a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts +++ b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts @@ -1,4 +1,5 @@ import { localize } from '@deriv/translations'; +import { Jurisdiction } from '@deriv/shared'; export type TDxCompanies = ReturnType; export type TMtCompanies = ReturnType; @@ -184,16 +185,16 @@ export const getFormattedJurisdictionCode = (jurisdiction_code: string) => { let formatted_label = ''; switch (jurisdiction_code) { - case 'svg': + case Jurisdiction.SVG: formatted_label = localize('SVG'); break; - case 'bvi': + case Jurisdiction.BVI: formatted_label = localize('BVI'); break; - case 'labuan': + case Jurisdiction.LABUAN: formatted_label = localize('Labuan'); break; - case 'vanuatu': + case Jurisdiction.VANUATU: formatted_label = localize('Vanuatu'); break; default: diff --git a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js index 3a7e6e007c41..8f9fea9bfd40 100644 --- a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js +++ b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js @@ -1,5 +1,5 @@ import { action, computed, observable, reaction, runInAction, makeObservable, override } from 'mobx'; -import { getAccountListKey, getAccountTypeFields, CFD_PLATFORMS, WS } from '@deriv/shared'; +import { getAccountListKey, getAccountTypeFields, CFD_PLATFORMS, WS, Jurisdiction } from '@deriv/shared'; import BaseStore from 'Stores/base-store'; import { getDxCompanies, getMtCompanies } from './Helpers/cfd-config'; @@ -233,8 +233,8 @@ export default class CFDStore extends BaseStore { this.toggleJurisdictionModal(); } else { if (this.root_store.traders_hub.show_eu_related_content) { - this.setJurisdictionSelectedShortcode('maltainvest'); - } else this.setJurisdictionSelectedShortcode('svg'); + this.setJurisdictionSelectedShortcode(Jurisdiction.MALTA_INVEST); + } else this.setJurisdictionSelectedShortcode(Jurisdiction.SVG); this.demoCFDSignup(); } } @@ -280,7 +280,7 @@ export default class CFDStore extends BaseStore { zipCode: address_postcode, ...(values.server ? { server: values.server } : {}), ...(this.jurisdiction_selected_shortcode ? { company: this.jurisdiction_selected_shortcode } : {}), - ...(this.jurisdiction_selected_shortcode !== 'labuan' + ...(this.jurisdiction_selected_shortcode !== Jurisdiction.LABUAN ? type_request : { account_type: 'financial', diff --git a/packages/cfd/src/sass/cfd-dashboard.scss b/packages/cfd/src/sass/cfd-dashboard.scss index 937250771fd5..478ce84b2613 100644 --- a/packages/cfd/src/sass/cfd-dashboard.scss +++ b/packages/cfd/src/sass/cfd-dashboard.scss @@ -489,20 +489,17 @@ .cfd-jurisdiction-card--synthetic, .cfd-jurisdiction-card--financial { - border: solid 1px var(--border-normal); - border-radius: 0.8rem; + border: solid 2px var(--border-normal); + border-radius: $BORDER_RADIUS * 4; display: flex; justify-content: space-between; flex-direction: column; - min-height: 36rem; - width: 27.6em; - position: relative; - padding: 1.6rem; - @include mobile { - margin-bottom: 2rem; - } + height: 100%; + width: 100%; + cursor: pointer; + transition: all 0.1s ease-in; - &:hover { + &:not(.selected-card):hover { box-shadow: 0 2px 8px 0 var(--shadow-menu); } @@ -510,111 +507,125 @@ border: solid 1px var(--border-disabled); } - @include desktop { - height: auto; - margin: 0 0.8rem; - } - &__wrapper { - padding: 0; - margin-top: 4.8rem; + margin: 4rem 6rem 2rem; display: flex; justify-content: center; - + gap: 2rem; @include mobile { + margin: 0; + padding: 4rem 4rem; + gap: 4rem; flex-direction: column; align-items: center; overflow-y: scroll; height: 60%; } } + &--selected { - border: solid 1px #377cfc; - border-radius: 4px; + border: solid 2px $color-green; + box-shadow: 0 1.2rem 1.8rem 0.8rem var(--shadow-menu); } - &__verification-status, - &__verification-status--pending, - &__verification-status--failed, - &__verification-status--account_added, - &__verification-status--poi_verified, - &__verification-status--not_submitted, - &__verification-status--hint { - width: 100%; - min-height: 2.4rem; - display: flex; - - * { - margin: auto; - } - - &--pending { - background-color: #ffad3a; - border-radius: 0.5rem; - } - - &--poi_verified { - background: var(--text-status-info-blue); - border-radius: 0.5rem; - padding: 0.1rem; - } - &--account_added { - background-color: #4bb4b3; - border-radius: 0.5rem; + &__card { + &-content { + &-container { + display: flex; + flex-direction: column; + height: 100%; + } + &-over-header { + background: var(--text-info-blue-background); + height: 4rem; + width: 100%; + padding: 0.5rem; + border-radius: 1.4rem 1.4rem 0 0; + &-blank { + height: 4rem; + border-radius: 1.4rem; + @include mobile { + height: 2rem; + } + } + } + &-footer { + width: 100%; + &-text { + background: var(--brand-secondary); + height: 4rem; + padding: 1rem; + border-radius: 0 0 1.4rem 1.4rem; + } + } } - - &--failed { - background-color: #ec3f3f; - border-radius: 0.5rem; + &-flipped-container { + gap: 2rem; + padding: 4rem 2rem; } - &--not_submitted { - background-color: var(--general-section-1); - padding: 0.3rem; - border-radius: 0.5rem; + &-section-container { + display: flex; + flex-direction: column; + gap: 1.2rem; + height: 100%; + margin: 0 2rem; } } + &__h2-header { - margin: 1.4rem 0 2.4rem; + min-height: 5rem; + margin: 1rem 2rem; + @include mobile { + margin-bottom: 2rem; + min-height: auto; + } } + &__footer-wrapper { + display: flex; + flex-direction: column; + justify-content: space-between; @include mobile { + min-height: auto; background-color: var(--general-main-1); width: 100%; height: 100%; position: sticky; bottom: 0; - max-height: 20rem; z-index: 12; } - .dc-modal-footer { - @include desktop { - position: fixed; - bottom: 0; - width: 100%; - } + } + + &__footnotes-container { + display: flex; + flex-direction: column; + gap: 1rem; + margin: 1rem; + @include desktop { + min-height: 6rem; + } + @include mobile { + gap: 0; + margin: 0; } } + &__footnote { display: flex; - flex-direction: column; justify-content: center; - margin: 1.6rem 2.4rem; - padding: 0.8rem; @include mobile { margin: unset; padding: 1.6rem 0.8rem; box-shadow: 0px -4px 4px rgba(0, 0, 0, 0.08); } - &--pending { - color: #ffad3a; + color: $color-yellow; } } &__jurisdiction-checkbox { display: flex; justify-content: center; - margin-bottom: 2.4rem; @include mobile { padding: 0.8rem; } @@ -622,33 +633,157 @@ &__over-header { background-color: #dfeaff; - top: -1rem; + top: -2rem; left: 1.4rem; z-index: 10; width: 90%; height: 4rem; position: absolute; - border-radius: 4px; + border-radius: $BORDER_RADIUS * 2; margin-bottom: 1rem; - + border: 1px solid var(--text-info-blue); & > p { font-size: 16px; text-align: center; } } +} - &__bullet-wrapper { +.cfd-card { + &-perspective { + -webkit-perspective: 100rem; + perspective: 100rem; + @include mobile { + width: 100%; + } + } + &-container { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + -webkit-transition: all 0.25s ease-in; + transition: all 0.25s ease-in; + width: 29rem; + &.synthetic { + min-height: 48rem; + } + &.financial { + min-height: 54rem; + } + @include mobile { + height: 48rem; + width: 100%; + } + } + &-flipped { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + } + &-front, + &-back { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; + position: absolute; + top: 0; + left: 0; + } + &-front { + z-index: 2; + -webkit-transform: rotateY(0deg); + transform: rotateY(0deg); + } + &-back { + -webkit-transform: rotateY(-180deg); + transform: rotateY(-180deg); + } + &-section { + width: 100%; display: flex; - margin-bottom: 1rem; - - &--checkmark { - margin-right: 1rem; + flex-direction: column; + gap: 0.8rem; + &-divider { + width: 100%; + border-bottom: 2px solid var(--border-divider); + } + &-title-indicator { + padding: 0.6rem 1.2rem; + border-radius: $BORDER_RADIUS; + &-icon-container { + display: flex; + gap: 0.5rem; + } + &__red-darker { + background: $color-red-8; + } + &__red-dark { + background: $color-red-9; + } + &__red-light { + background: $color-red-10; + } + &__yellow-dark { + background: $color-yellow-1; + } + &__yellow-light { + background: $color-yellow-2; + } + &__violet-dark { + background: $color-violet; + } + &__brown-dark { + background: $color-brown; + } + } + &-description-height { + @include desktop { + &-assets { + min-height: 3.4rem; + } + &-verifications, + &-regulator { + min-height: 5rem; + } + } + } + } + &-back-section { + &-items-container { + display: flex; + flex-direction: column; + gap: 1.2rem; + } + &-items-sub-container { + display: flex; + align-items: flex-start; + gap: 1rem; + } + &-back-button { + -webkit-transition: transform 0.25s linear; + transition: transform 0.25s linear; + } + &-text-icon-aligned { + margin-top: -0.3rem; + } + } + &-clickable-description-link { + color: var(--text-red); + &:hover { + text-decoration: underline; + } + } + &-title-container { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; + } + &-disabled { + pointer-events: none; + &-flat { + border: solid 1px var(--border-normal); } } -} - -.cfd-jurisdiction-card--synthetic { - padding: 2.4rem; } .cfd-modal--custom-exit { diff --git a/packages/cfd/src/sass/cfd.scss b/packages/cfd/src/sass/cfd.scss index ad444dec1b38..08c4e8b92ba0 100644 --- a/packages/cfd/src/sass/cfd.scss +++ b/packages/cfd/src/sass/cfd.scss @@ -400,7 +400,6 @@ } .dc-modal__container_jurisdiction-modal { - min-height: 664px; .dc-modal-header { border-bottom: 2px solid var(--general-section-1); } diff --git a/packages/components/src/components/icon/common/ic-back-button.svg b/packages/components/src/components/icon/common/ic-back-button.svg new file mode 100644 index 000000000000..dbc1ed6a3205 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-back-button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-document-number-verification-default.svg b/packages/components/src/components/icon/common/ic-document-number-verification-default.svg new file mode 100644 index 000000000000..8435374bc956 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-document-number-verification-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-document-number-verification-failed.svg b/packages/components/src/components/icon/common/ic-document-number-verification-failed.svg new file mode 100644 index 000000000000..334357727cc7 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-document-number-verification-failed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-document-number-verification-pending.svg b/packages/components/src/components/icon/common/ic-document-number-verification-pending.svg new file mode 100644 index 000000000000..27bd9da9a76d --- /dev/null +++ b/packages/components/src/components/icon/common/ic-document-number-verification-pending.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-document-number-verification-verified.svg b/packages/components/src/components/icon/common/ic-document-number-verification-verified.svg new file mode 100644 index 000000000000..56891aa32891 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-document-number-verification-verified.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-document-number-verification.svg b/packages/components/src/components/icon/common/ic-document-number-verification.svg new file mode 100644 index 000000000000..5a4e733557a0 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-document-number-verification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-identity-document-verification-default.svg b/packages/components/src/components/icon/common/ic-identity-document-verification-default.svg new file mode 100644 index 000000000000..d2ddae66cda2 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-identity-document-verification-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-identity-document-verification-failed.svg b/packages/components/src/components/icon/common/ic-identity-document-verification-failed.svg new file mode 100644 index 000000000000..985d919274dc --- /dev/null +++ b/packages/components/src/components/icon/common/ic-identity-document-verification-failed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-identity-document-verification-pending.svg b/packages/components/src/components/icon/common/ic-identity-document-verification-pending.svg new file mode 100644 index 000000000000..d1d4e762b3cb --- /dev/null +++ b/packages/components/src/components/icon/common/ic-identity-document-verification-pending.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-identity-document-verification-verified.svg b/packages/components/src/components/icon/common/ic-identity-document-verification-verified.svg new file mode 100644 index 000000000000..c2192579a966 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-identity-document-verification-verified.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-identity-document-verification.svg b/packages/components/src/components/icon/common/ic-identity-document-verification.svg new file mode 100644 index 000000000000..77e05efd57ad --- /dev/null +++ b/packages/components/src/components/icon/common/ic-identity-document-verification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-name-and-address-verification-default.svg b/packages/components/src/components/icon/common/ic-name-and-address-verification-default.svg new file mode 100644 index 000000000000..7d1131c11aa2 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-name-and-address-verification-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-name-and-address-verification-failed.svg b/packages/components/src/components/icon/common/ic-name-and-address-verification-failed.svg new file mode 100644 index 000000000000..a1b85a47dd89 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-name-and-address-verification-failed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-name-and-address-verification-pending.svg b/packages/components/src/components/icon/common/ic-name-and-address-verification-pending.svg new file mode 100644 index 000000000000..0f560f786135 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-name-and-address-verification-pending.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-name-and-address-verification-verified.svg b/packages/components/src/components/icon/common/ic-name-and-address-verification-verified.svg new file mode 100644 index 000000000000..cbaff2d6ed7a --- /dev/null +++ b/packages/components/src/components/icon/common/ic-name-and-address-verification-verified.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-name-and-address-verification.svg b/packages/components/src/components/icon/common/ic-name-and-address-verification.svg new file mode 100644 index 000000000000..2e17b0efa157 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-name-and-address-verification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-not-applicable-verification-default.svg b/packages/components/src/components/icon/common/ic-not-applicable-verification-default.svg new file mode 100644 index 000000000000..fd2f117edb9f --- /dev/null +++ b/packages/components/src/components/icon/common/ic-not-applicable-verification-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-selfie-verification-default.svg b/packages/components/src/components/icon/common/ic-selfie-verification-default.svg new file mode 100644 index 000000000000..15593bc780c5 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-selfie-verification-default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-selfie-verification-failed.svg b/packages/components/src/components/icon/common/ic-selfie-verification-failed.svg new file mode 100644 index 000000000000..d6fbd043ce9a --- /dev/null +++ b/packages/components/src/components/icon/common/ic-selfie-verification-failed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-selfie-verification-pending.svg b/packages/components/src/components/icon/common/ic-selfie-verification-pending.svg new file mode 100644 index 000000000000..339a3086a89c --- /dev/null +++ b/packages/components/src/components/icon/common/ic-selfie-verification-pending.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-selfie-verification-verified.svg b/packages/components/src/components/icon/common/ic-selfie-verification-verified.svg new file mode 100644 index 000000000000..8183216099a1 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-selfie-verification-verified.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-selfie-verification.svg b/packages/components/src/components/icon/common/ic-selfie-verification.svg new file mode 100644 index 000000000000..39d2bbe8c782 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-selfie-verification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-verification-status-green.svg b/packages/components/src/components/icon/common/ic-verification-status-green.svg new file mode 100644 index 000000000000..dc5a246bb465 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-verification-status-green.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-verification-status-red.svg b/packages/components/src/components/icon/common/ic-verification-status-red.svg new file mode 100644 index 000000000000..ea745e409fd3 --- /dev/null +++ b/packages/components/src/components/icon/common/ic-verification-status-red.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/common/ic-verification-status-yellow.svg b/packages/components/src/components/icon/common/ic-verification-status-yellow.svg new file mode 100644 index 000000000000..5cca88db6d2d --- /dev/null +++ b/packages/components/src/components/icon/common/ic-verification-status-yellow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/icons.js b/packages/components/src/components/icon/icons.js index c51f50ca4e17..d41741c7af82 100644 --- a/packages/components/src/components/icon/icons.js +++ b/packages/components/src/components/icon/icons.js @@ -274,6 +274,7 @@ import './common/ic-assessment.svg'; import './common/ic-astro-pay-dark.svg'; import './common/ic-astro-pay-light.svg'; import './common/ic-attachment.svg'; +import './common/ic-back-button.svg'; import './common/ic-bank-dashboard.svg'; import './common/ic-bank-transfer.svg'; import './common/ic-bank.svg'; @@ -340,6 +341,11 @@ import './common/ic-deriv.svg'; import './common/ic-desktop.svg'; import './common/ic-digits.svg'; import './common/ic-docs-submit.svg'; +import './common/ic-document-number-verification-default.svg'; +import './common/ic-document-number-verification-failed.svg'; +import './common/ic-document-number-verification-pending.svg'; +import './common/ic-document-number-verification-verified.svg'; +import './common/ic-document-number-verification.svg'; import './common/ic-dop.svg'; import './common/ic-download.svg'; import './common/ic-dp2p.svg'; @@ -385,6 +391,11 @@ import './common/ic-id-card-back.svg'; import './common/ic-id-card-front.svg'; import './common/ic-identity-card-dashboard.svg'; import './common/ic-identity-card.svg'; +import './common/ic-identity-document-verification-default.svg'; +import './common/ic-identity-document-verification-failed.svg'; +import './common/ic-identity-document-verification-pending.svg'; +import './common/ic-identity-document-verification-verified.svg'; +import './common/ic-identity-document-verification.svg'; import './common/ic-image.svg'; import './common/ic-info-blue.svg'; import './common/ic-info-outline.svg'; @@ -425,12 +436,18 @@ import './common/ic-minus.svg'; import './common/ic-mobile.svg'; import './common/ic-money-transfer.svg'; import './common/ic-multiplier.svg'; +import './common/ic-name-and-address-verification-default.svg'; +import './common/ic-name-and-address-verification-failed.svg'; +import './common/ic-name-and-address-verification-pending.svg'; +import './common/ic-name-and-address-verification-verified.svg'; +import './common/ic-name-and-address-verification.svg'; import './common/ic-neteller-dark.svg'; import './common/ic-neteller-light.svg'; import './common/ic-new-file.svg'; import './common/ic-no-ad.svg'; import './common/ic-no-data.svg'; import './common/ic-no-order.svg'; +import './common/ic-not-applicable-verification-default.svg'; import './common/ic-notification-clear.svg'; import './common/ic-notification.svg'; import './common/ic-online-naira.svg'; @@ -505,6 +522,11 @@ import './common/ic-save.svg'; import './common/ic-search.svg'; import './common/ic-security-and-privacy.svg'; import './common/ic-security.svg'; +import './common/ic-selfie-verification-default.svg'; +import './common/ic-selfie-verification-failed.svg'; +import './common/ic-selfie-verification-pending.svg'; +import './common/ic-selfie-verification-verified.svg'; +import './common/ic-selfie-verification.svg'; import './common/ic-selfie.svg'; import './common/ic-send-message.svg'; import './common/ic-skrill-dark.svg'; @@ -540,6 +562,9 @@ import './common/ic-user-blocked-outline.svg'; import './common/ic-user-outline.svg'; import './common/ic-user.svg'; import './common/ic-utility.svg'; +import './common/ic-verification-status-green.svg'; +import './common/ic-verification-status-red.svg'; +import './common/ic-verification-status-yellow.svg'; import './common/ic-verification-success.svg'; import './common/ic-verification.svg'; import './common/ic-visa-dark.svg'; diff --git a/packages/components/stories/icon/icons.js b/packages/components/stories/icon/icons.js index 0424319c40e1..13b5fe64bd58 100644 --- a/packages/components/stories/icon/icons.js +++ b/packages/components/stories/icon/icons.js @@ -282,6 +282,7 @@ export const icons = 'IcAstroPayDark', 'IcAstroPayLight', 'IcAttachment', + 'IcBackButton', 'IcBankDashboard', 'IcBankTransfer', 'IcBank', @@ -348,6 +349,11 @@ export const icons = 'IcDesktop', 'IcDigits', 'IcDocsSubmit', + 'IcDocumentNumberVerificationDefault', + 'IcDocumentNumberVerificationFailed', + 'IcDocumentNumberVerificationPending', + 'IcDocumentNumberVerificationVerified', + 'IcDocumentNumberVerification', 'IcDop', 'IcDownload', 'IcDp2p', @@ -393,6 +399,11 @@ export const icons = 'IcIdCardFront', 'IcIdentityCardDashboard', 'IcIdentityCard', + 'IcIdentityDocumentVerificationDefault', + 'IcIdentityDocumentVerificationFailed', + 'IcIdentityDocumentVerificationPending', + 'IcIdentityDocumentVerificationVerified', + 'IcIdentityDocumentVerification', 'IcImage', 'IcInfoBlue', 'IcInfoOutline', @@ -433,12 +444,18 @@ export const icons = 'IcMobile', 'IcMoneyTransfer', 'IcMultiplier', + 'IcNameAndAddressVerificationDefault', + 'IcNameAndAddressVerificationFailed', + 'IcNameAndAddressVerificationPending', + 'IcNameAndAddressVerificationVerified', + 'IcNameAndAddressVerification', 'IcNetellerDark', 'IcNetellerLight', 'IcNewFile', 'IcNoAd', 'IcNoData', 'IcNoOrder', + 'IcNotApplicableVerificationDefault', 'IcNotificationClear', 'IcNotification', 'IcOnlineNaira', @@ -513,6 +530,11 @@ export const icons = 'IcSearch', 'IcSecurityAndPrivacy', 'IcSecurity', + 'IcSelfieVerificationDefault', + 'IcSelfieVerificationFailed', + 'IcSelfieVerificationPending', + 'IcSelfieVerificationVerified', + 'IcSelfieVerification', 'IcSelfie', 'IcSendMessage', 'IcSkrillDark', @@ -548,6 +570,9 @@ export const icons = 'IcUserOutline', 'IcUser', 'IcUtility', + 'IcVerificationStatusGreen', + 'IcVerificationStatusRed', + 'IcVerificationStatusYellow', 'IcVerificationSuccess', 'IcVerification', 'IcVisaDark', diff --git a/packages/shared/src/styles/constants.scss b/packages/shared/src/styles/constants.scss index 2741931a769e..5aa78ff555b7 100644 --- a/packages/shared/src/styles/constants.scss +++ b/packages/shared/src/styles/constants.scss @@ -16,15 +16,21 @@ $color-black-6: #3e3e3e; $color-black-7: #000000; $color-black-8: #323738; $color-black-9: #5c5c5c; -$color-white: #ffffff; -$color-red: #ff444f; -$color-red-1: #ec3f3f; -$color-red-2: #cc2e3d; -$color-red-3: #a32430; -$color-red-4: #d33636; -$color-red-5: #eb3e48; -$color-red-6: #ec3f3f29; -$color-red-7: #ffe1e3; +$color-blue: #377cfc; +$color-blue-1: #0dc2e7; +$color-blue-2: #2a3052; +$color-blue-3: #0796e0; +$color-blue-4: #0677af; +$color-blue-5: #dfeaff; +$color-blue-6: #92b8ff; +$color-blue-7: #182130; +$color-brown: #664407; +$color-green: #85acb0; +$color-green-1: #4bb4b3; +$color-green-2: #3d9494; +$color-green-3: #00a79e; +$color-green-4: #008079; +$color-green-5: #4bb4b329; $color-grey: #c2c2c2; $color-grey-1: #999999; $color-grey-2: #f2f3f4; @@ -38,20 +44,25 @@ $color_grey-9: #868686; $color-grey-10: #919191; $color-grey-11: #fafafa; $color-grey-12: #f5f7fa; -$color-green: #85acb0; -$color-green-1: #4bb4b3; -$color-green-2: #3d9494; -$color-green-3: #00a79e; -$color-green-4: #008079; -$color-green-5: #4bb4b329; +$color-grey-13: #2e2e2e; $color-orange: #ff6444; -$color-yellow: #ffad3a; -$color-blue: #377cfc; -$color-blue-1: #0dc2e7; -$color-blue-2: #2a3052; -$color-blue-3: #0796e0; -$color-blue-4: #0677af; $color-purple: #722fe4; +$color-red: #ff444f; +$color-red-1: #ec3f3f; +$color-red-2: #cc2e3d; +$color-red-3: #a32430; +$color-red-4: #d33636; +$color-red-5: #eb3e48; +$color-red-6: #ec3f3f29; +$color-red-7: #ffe1e3; +$color-red-8: #661b20; +$color-red-9: #b33037; +$color-red-10: #ff444f; +$color-violet: #4a3871; +$color-white: #ffffff; +$color-yellow: #ffad3a; +$color-yellow-1: #b3760d; +$color-yellow-2: #ffa912; /* alpha colors */ $alpha-color-black-1: transparentize($color-black-7, 0.28); diff --git a/packages/shared/src/styles/themes.scss b/packages/shared/src/styles/themes.scss index 294262085f70..bb2fb2aa668d 100644 --- a/packages/shared/src/styles/themes.scss +++ b/packages/shared/src/styles/themes.scss @@ -34,6 +34,7 @@ --text-align-center: center; // Brand primary colors + --brand-white: #{$color-white}; --brand-dark-grey: #{$color-black}; --brand-red-coral: #{$color-red}; --brand-orange: #{$color-orange}; @@ -89,6 +90,7 @@ --text-red: #{$color-red}; --text-blue: #{$color-blue-3}; --text-info-blue: #{$color-blue}; + --text-info-blue-background: #{$color-blue-5}; --text-colored-background: #{$color-white}; --icon-light-background: #{$color-black-9}; --icon-dark-background: #{$color-white}; @@ -137,6 +139,7 @@ --border-hover-1: #{$color-black-9}; --border-active: var(--brand-secondary); --border-disabled: #{$color-grey-3}; + --border-divider: #{$color-grey-2}; // Fill --fill-normal: #{$color-white}; --fill-normal-1: #{$color-grey}; @@ -217,6 +220,8 @@ --text-loss-danger: #{$color-red-2}; --text-red: #{$color-red}; --text-colored-background: #{$color-white}; + --text-info-blue: #{$color-blue-6}; + --text-info-blue-background: #{$color-blue-7}; --text-status-info-blue: #{$color-blue}; --text-hint: #{$color-grey}; --icon-light-background: #{$color-black-9}; @@ -263,6 +268,7 @@ --border-hover-1: #{$color-black-9}; --border-active: var(--brand-secondary); --border-disabled: #{$color-black-4}; + --border-divider: #{$color-grey-13}; // Fill --fill-normal: #{$color-black}; --fill-normal-1: #{$color-black-1}; diff --git a/packages/shared/src/utils/constants/index.ts b/packages/shared/src/utils/constants/index.ts index 4477b7bd5fdf..8482abf7811c 100644 --- a/packages/shared/src/utils/constants/index.ts +++ b/packages/shared/src/utils/constants/index.ts @@ -1,5 +1,6 @@ export * from './barriers'; export * from './contract'; export * from './content_flags'; +export * from './jurisdictions-config'; export * from './signup_fields'; export * from './error'; diff --git a/packages/shared/src/utils/constants/jurisdictions-config.ts b/packages/shared/src/utils/constants/jurisdictions-config.ts new file mode 100644 index 000000000000..3030e044221d --- /dev/null +++ b/packages/shared/src/utils/constants/jurisdictions-config.ts @@ -0,0 +1,7 @@ +export const Jurisdiction = Object.freeze({ + SVG: 'svg', + BVI: 'bvi', + VANUATU: 'vanuatu', + LABUAN: 'labuan', + MALTA_INVEST: 'maltainvest', +});