diff --git a/scripts/config/pages.js b/scripts/config/pages.js index bc9a59a550e5d..6b52db002ef51 100644 --- a/scripts/config/pages.js +++ b/scripts/config/pages.js @@ -21,11 +21,13 @@ module.exports = [ ['trading', 'app/trade/trading', 'default', 'SmartTrader'], + // TODO: Remove 'maltainvestws' and 'realws' after completely change the signup flow for all countries as these only being used for exceptional countries. ['new_account/maltainvestws', 'app/new_account/financial', 'default', 'Financial Account Opening'], ['new_account/realws', 'app/new_account/real', 'default', 'Real Money Account Opening'], + ['new_account/real_account', 'app/new_account/real_account', 'default', 'Real Account Opening'], ['new_account/virtualws', 'app/new_account/virtual', 'default', 'Create New Demo Account'], ['new_account/welcome', 'app/new_account/welcome_page', 'default', 'Welcome to Binary.com'], - ['new_account/welcome_onboarding', 'app/new_account/welcome_onboarding', 'default', 'Welcome to Binary.com'], + ['new_account/welcome_onboarding', 'app/new_account/welcome_onboarding', 'default', 'Welcome to Binary.com'], ['resources', 'app/resources/index', 'default', 'Resources'], ['resources/asset_indexws', 'app/resources/asset_index', 'full_width', 'Asset Index'], diff --git a/src/javascript/_common/check_password.js b/src/javascript/_common/check_password.js index 3357b6e538dcd..7759296143f42 100644 --- a/src/javascript/_common/check_password.js +++ b/src/javascript/_common/check_password.js @@ -86,7 +86,7 @@ const checkPassword = (password_selector, should_show_error) => { const removeCheck = (password_selector, should_reset_meter) => { const el_password = document.querySelector(password_selector); const el_meter_bar = el_password.parentNode.querySelector('.password--meter-fill'); - const password_value = el_password.value.trim(); + const password_value = (el_password.value || '').trim(); const el_feedback_message = el_password.parentNode.querySelector('.password--message'); if (el_meter_bar && password_value.length < 1 || should_reset_meter) { el_meter_bar.style.transform = 'scale(0, 1)'; diff --git a/src/javascript/app/base/binary_pages.js b/src/javascript/app/base/binary_pages.js index f029d92ccae28..1e1f5c895ef93 100644 --- a/src/javascript/app/base/binary_pages.js +++ b/src/javascript/app/base/binary_pages.js @@ -40,8 +40,10 @@ const Accounts = require('../pages/user/accounts'); const LostPassword = require('../pages/user/lost_password'); const MetaTrader = require('../pages/user/metatrader/metatrader'); const TypesOfAccounts = require('../pages/user/metatrader/types_of_accounts'); +// TODO: Remove 'FinancialAccOpening' and 'RealAccOpening' after completely change the signup flow for all countries const FinancialAccOpening = require('../pages/user/new_account/financial_acc_opening'); const RealAccOpening = require('../pages/user/new_account/real_acc_opening'); +const RealAccountOpening = require('../pages/user/new_account/real_account_opening'); const VirtualAccOpening = require('../pages/user/new_account/virtual_acc_opening'); const WelcomePage = require('../pages/user/new_account/welcome_page'); const WelcomePageOnboarding = require('../pages/user/new_account/welcome_onboarding'); @@ -109,6 +111,7 @@ const pages_config = { logged_inws : { module: LoggedInHandler }, lost_passwordws : { module: LostPassword, not_authenticated: true }, malta : { module: StaticPages.Locations }, + // TODO: Remove 'maltainvestws' after completely change the signup flow for all countries maltainvestws : { module: FinancialAccOpening, is_authenticated: true }, market_timesws : { module: TradingTimesUI, no_mf: true, no_blocked_country: true }, metals : { module: GetStarted.Metals }, @@ -120,7 +123,9 @@ const pages_config = { portfoliows : { module: Portfolio, is_authenticated: true, needs_currency: true }, professional : { module: professionalClient, is_authenticated: true, only_real: true }, profit_tablews : { module: ProfitTable, is_authenticated: true, needs_currency: true }, + // TODO: Remove 'realws' after completely change the signup flow for all countries realws : { module: RealAccOpening, is_authenticated: true }, + real_account : { module: RealAccountOpening, is_authenticated: true }, redirect : { module: Redirect }, regulation : { module: Regulation }, reset_passwordws : { module: ResetPassword }, diff --git a/src/javascript/app/base/header.js b/src/javascript/app/base/header.js index 907ad173dfd6a..4d5b5a853fc35 100644 --- a/src/javascript/app/base/header.js +++ b/src/javascript/app/base/header.js @@ -1,7 +1,6 @@ const BinaryPjax = require('./binary_pjax'); const Client = require('./client'); const BinarySocket = require('./socket'); -const showHidePulser = require('../common/account_opening').showHidePulser; const getCurrencyDisplayCode = require('../common/currency').getCurrencyDisplayCode; const getLandingCompanyValue = require('../../_common/base/client_base').getLandingCompanyValue; const isAuthenticationAllowed = require('../../_common/base/client_base').isAuthenticationAllowed; @@ -136,20 +135,20 @@ const Header = (() => { return; } - const showUpgrade = (url, localized_text) => { + const showUpgrade = (url, params, localized_text) => { applyToAllElements(upgrade_msg, (el) => { el.setVisibility(1); applyToAllElements('a', (ele) => { - ele.html(createElement('span', { text: localized_text })).setVisibility(1).setAttribute('href', Url.urlFor(url)); + ele.html(createElement('span', { text: localized_text })).setVisibility(1).setAttribute('href', Url.urlFor(url, params)); }, '', el); }); }; - const showUpgradeBtn = (url, localized_text) => { + const showUpgradeBtn = (url, params, localized_text) => { applyToAllElements(upgrade_msg, (el) => { el.setVisibility(1); applyToAllElements('a.button', (ele) => { - ele.html(createElement('span', { text: localized_text })).setVisibility(1).setAttribute('href', Url.urlFor(url)); + ele.html(createElement('span', { text: localized_text })).setVisibility(1).setAttribute('href', Url.urlFor(url, params)); }, '', el); }); }; @@ -186,9 +185,9 @@ const Header = (() => { if (show_upgrade_msg) { const upgrade_url = upgrade_info.can_upgrade_to.length > 1 ? 'user/accounts' - : Object.values(upgrade_info.upgrade_links)[0]; - showUpgrade(upgrade_url, upgrade_link_txt); - showUpgradeBtn(upgrade_url, upgrade_btn_txt); + : 'new_account/real_account'; + showUpgrade(upgrade_url, `account_type=${upgrade_info.can_upgrade_to[0]}`, upgrade_link_txt); + showUpgradeBtn(upgrade_url, `account_type=${upgrade_info.can_upgrade_to[0]}`, upgrade_btn_txt); } else { applyToAllElements(upgrade_msg, (el) => { applyToAllElements('a', (ele) => { @@ -203,9 +202,9 @@ const Header = (() => { getElementById('virtual-wrapper').setVisibility(0); const upgrade_url = upgrade_info.can_upgrade_to.length > 1 ? 'user/accounts' - : Object.values(upgrade_info.upgrade_links)[0]; - showUpgrade(upgrade_url, upgrade_link_txt); - showUpgradeBtn(upgrade_url, upgrade_btn_txt); + : 'new_account/real_account'; + showUpgrade(upgrade_url, `account_type=${upgrade_info.can_upgrade_to[0]}`, upgrade_link_txt); + showUpgradeBtn(upgrade_url, `account_type=${upgrade_info.can_upgrade_to[0]}`, upgrade_btn_txt); if (/new_account/.test(window.location.href)) { showHidePulser(0); @@ -217,6 +216,8 @@ const Header = (() => { }); }; + const showHidePulser = (should_show) => { $('.upgrademessage').children('a').setVisibility(should_show); }; + const showHideNewAccount = (upgrade_info) => { if (upgrade_info.can_upgrade || upgrade_info.can_open_multi) { changeAccountsText(1, localize('Create Account')); diff --git a/src/javascript/app/common/__tests__/account_opening.js b/src/javascript/app/common/__tests__/account_opening.js index cfe4cf506b738..7261ced45f144 100644 --- a/src/javascript/app/common/__tests__/account_opening.js +++ b/src/javascript/app/common/__tests__/account_opening.js @@ -12,7 +12,7 @@ describe('AccountOpening', () => { expect(AccountOpening.redirectAccount()).to.eq(1); }); it('will not redirect client who is already on maltainvest account opening page again', () => { - setURL(`${Url.websiteUrl()}en/maltainvestws.html`); + setURL(`${Url.websiteUrl()}en/new_account/real_account.html?account_type=maltainvest`); expect(AccountOpening.redirectAccount()).to.eq(0); }); it('will redirect client who cannot upgrade their account to the previous page', () => { diff --git a/src/javascript/app/common/account_opening.js b/src/javascript/app/common/account_opening.js index 839b5d4cbae92..dc3b642245029 100644 --- a/src/javascript/app/common/account_opening.js +++ b/src/javascript/app/common/account_opening.js @@ -4,10 +4,14 @@ const moment = require('moment'); const generateBirthDate = require('./attach_dom/birth_date_picker'); const FormManager = require('./form_manager'); const BinaryPjax = require('../base/binary_pjax'); -const Client = require('../base/client'); +const Header = require('../base/header'); const BinarySocket = require('../base/socket'); +const Client = require('../base/client'); const professionalClient = require('../pages/user/account/settings/professional_client'); +const param = require('../../_common/url').param; +const ClientBase = require('../../_common/base/client_base'); const CommonFunctions = require('../../_common/common_functions'); +const getElementById = require('../../_common/common_functions').getElementById; const localize = require('../../_common/localize').localize; const State = require('../../_common/storage').State; const toISOFormat = require('../../_common/string_util').toISOFormat; @@ -16,14 +20,47 @@ const urlFor = require('../../_common/url').urlFor; const getPropertyValue = require('../../_common/utility').getPropertyValue; const AccountOpening = (() => { + + const excluded_countries = ['im', 'au', 'sg', 'no']; + + const getSinupPageLink = (upgrade_info, account_type) => { + const get_settings = State.getResponse('get_settings'); + const country_code = get_settings.country_code; + if (excluded_countries.includes(country_code)) { // old flow + return urlFor(upgrade_info.upgrade_links[account_type]); + } // new flow + return urlFor('/new_account/real_account', `account_type=${account_type}`); + + }; + const redirectAccount = () => { const upgrade_info = Client.getUpgradeInfo(); - if (!upgrade_info.can_upgrade) { BinaryPjax.loadPreviousUrl(); return -1; } + const country_code = State.getResponse('get_settings').country_code; + if (window.location.pathname.includes('/real_account')) { // new signup flow + if (excluded_countries.includes(country_code)) { + BinaryPjax.load('user/accounts'); + } + const real_account_signup_target = param('account_type'); + const is_in_correct_path = upgrade_info.can_upgrade_to.some(lc => lc === real_account_signup_target); + if (!is_in_correct_path) { + const upgradable_accounts_count = upgrade_info.can_upgrade_to.length; + if (upgradable_accounts_count > 1) { + BinaryPjax.load('user/accounts'); + } else if (upgradable_accounts_count === 1) { + window.location.replace(urlFor('/new_account/real_account', `account_type=${upgrade_info.can_upgrade_to[0]}`)); + } + return 1; + } + return 0; + } // old signup flow (only for excluded countries) + if (!excluded_countries.includes(country_code)) { + BinaryPjax.load('user/accounts'); + } if (!upgrade_info.is_current_path) { const upgradable_accounts_count = Object.keys(upgrade_info.upgrade_links).length; if (upgradable_accounts_count > 1) { @@ -34,6 +71,17 @@ const AccountOpening = (() => { return 1; } return 0; + + }; + + const showResponseError = (response) => { + getElementById('loading').setVisibility(0); + getElementById('real_account_wrapper').setVisibility(1); + const $notice_box = $('#client_message').find('.notice-msg'); + $('#submit-message').empty(); + $notice_box.text(response.msg_type === 'sanity_check' ? localize('There was some invalid character in an input field.') : response.error.message).end() + .setVisibility(1); + $.scrollTo($notice_box, 500, { offset: -150 }); }; const populateForm = (form_id, getValidations, is_financial) => { @@ -205,21 +253,6 @@ const AccountOpening = (() => { } }; - const handleTaxIdentificationNumber = () => { - BinarySocket.wait('get_settings').then((response) => { - const tax_identification_number = response.get_settings.tax_identification_number; - if (tax_identification_number) { - $('#lbl_tax_identification_number').text(tax_identification_number); - CommonFunctions.getElementById('row_lbl_tax_identification_number').setVisibility(1); - $('#tax_identification_number') - .val(tax_identification_number) // Set value for validation - .attr({ 'data-force': true, 'data-value': tax_identification_number }); - } else { - CommonFunctions.getElementById('row_tax_identification_number').setVisibility(1); - } - }); - }; - const handleState = (states_list, form_id, getValidations) => { const address_state_id = '#address_state'; BinarySocket.wait('get_settings').then((response) => { @@ -256,6 +289,7 @@ const AccountOpening = (() => { } }); }; + const handleNewAccount = (response, message_type) => { if (response.error) { const error_message = response.error.message; @@ -275,6 +309,21 @@ const AccountOpening = (() => { } }; + const handleTaxIdentificationNumber = () => { + BinarySocket.wait('get_settings').then((response) => { + const tax_identification_number = response.get_settings.tax_identification_number; + if (tax_identification_number) { + $('#lbl_tax_identification_number').text(tax_identification_number); + CommonFunctions.getElementById('row_lbl_tax_identification_number').setVisibility(1); + $('#tax_identification_number') + .val(tax_identification_number) // Set value for validation + .attr({ 'data-force': true, 'data-value': tax_identification_number }); + } else { + CommonFunctions.getElementById('row_tax_identification_number').setVisibility(1); + } + }); + }; + const commonValidations = () => { const residence = Client.get('residence'); const req = [ @@ -313,7 +362,7 @@ const AccountOpening = (() => { id = $(this).attr('id'); if (!/^(tnc|address_state|chk_professional|chk_tax_id|citizen)$/.test(id)) { validation = { selector: `#${id}`, validations: ['req'] }; - if (id === 'not_pep') { + if (id === 'pep_declaration') { validation.exclude_request = 1; validation.validations = [['req', { message: localize('Please confirm that you are not a politically exposed person.') }]]; } @@ -323,6 +372,54 @@ const AccountOpening = (() => { return validations; }; + const setCurrencyForFinancialAccount = async (currency_to_set) => { + sessionStorage.removeItem('new_financial_account_set_currency'); + await BinarySocket.wait('authorize'); + const response = await BinarySocket.send({ set_account_currency: currency_to_set }); + if (response.error) { + showResponseError(response); + } else { + Client.set('currency', currency_to_set); + BinarySocket.send({ balance: 1 }); + BinarySocket.send({ payout_currencies: 1 }, { forced: true }); + Header.displayAccountStatus(); + setTimeout(() => { window.location.replace(urlFor('user/set-currency') || urlFor('trading')); }, 500); // need to redirect not using pjax + } + }; + + const createNewAccount = async (account_details, submit_button) => { + FormManager.disableButton(submit_button); + const is_maltainvest_account = !!account_details.new_account_maltainvest; + account_details.client_type = $('#chk_professional').is(':checked') ? 'professional' : 'retail'; + delete account_details.tax_identification_confirm; + delete account_details.tnc; + delete account_details.pep_declaration; + delete account_details.fs_professional; + + // Set currency after account is created for Maltainvest only + if (is_maltainvest_account && account_details.currency) { + const currency = account_details.currency; + delete account_details.currency; + sessionStorage.setItem('new_financial_account_set_currency', currency); + } + + const response = await BinarySocket.send(account_details); + if (response.error) { + if (response.error.code === 'show risk disclaimer') return true; + showResponseError(response); + } else { + localStorage.setItem('is_new_account', 1); + const email = Client.get('email'); + const loginid = response[is_maltainvest_account ? 'new_account_maltainvest' : 'new_account_real'].client_id; + const token = response[is_maltainvest_account ? 'new_account_maltainvest' : 'new_account_real'].oauth_token; + ClientBase.setNewAccount({ email, loginid, token }); + if (is_maltainvest_account) window.location.reload(); + else window.location.replace(urlFor('user/set-currency')); + } + FormManager.enableButton(submit_button); + return false; + }; + const showHidePulser = (should_show) => { $('.upgrademessage').children('a').setVisibility(should_show); }; const registerPepToggle = () => { @@ -334,13 +431,17 @@ const AccountOpening = (() => { }; return { - redirectAccount, - populateForm, - handleNewAccount, commonValidations, + createNewAccount, + excluded_countries, + getSinupPageLink, + handleNewAccount, + populateForm, + redirectAccount, + registerPepToggle, selectCheckboxValidation, + setCurrencyForFinancialAccount, showHidePulser, - registerPepToggle, }; })(); diff --git a/src/javascript/app/common/form_manager.js b/src/javascript/app/common/form_manager.js index 6f8698afe17c2..5f8379e08de7c 100644 --- a/src/javascript/app/common/form_manager.js +++ b/src/javascript/app/common/form_manager.js @@ -68,6 +68,10 @@ const FormManager = (() => { value = field.$.attr('data-value'); } else if (/lbl_/.test(key)) { value = field.value || field.$.text(); + } else if (key === '#currency') { + value = $('.currency_wrapper.selected').attr('id') || ''; + } else if (field.$.attr('class') === 'hide-product-checkbox') { + value = field.$.attr('class') === 'hide-product-checkbox' ? 1 : 0; } else if (field.$.attr('class') === 'hidden-consent-checkbox') { value = field.$.attr('class') === 'hidden-consent-checkbox' ? 1 : 0; } else if (field.$.is(':checkbox')) { @@ -146,7 +150,9 @@ const FormManager = (() => { if (!can_submit) return; if (Validation.validate(options.form_selector)) { const req = $.extend({}, options.obj_request, getFormData(options.form_selector)); - if (typeof options.fnc_additional_check === 'function') { + if (typeof options.get_submitted_data === 'function') { + options.get_submitted_data(getFormData(options.form_selector)); + } else if (typeof options.fnc_additional_check === 'function') { Promise.resolve(options.fnc_additional_check(req)).then((result) => { if (result) submit(req); }); @@ -167,6 +173,8 @@ const FormManager = (() => { return { handleSubmit, init: initForm, + disableButton, + enableButton, }; })(); diff --git a/src/javascript/app/common/form_progress.js b/src/javascript/app/common/form_progress.js new file mode 100644 index 0000000000000..5d27c356304a0 --- /dev/null +++ b/src/javascript/app/common/form_progress.js @@ -0,0 +1,58 @@ +const getElementById = require('../../_common/common_functions').getElementById; +const isMobile = require('../../_common/os_detect').isMobile; +const localize = require('../../_common/localize').localize; + +const FormProgress = (() => { + const render = (identifire, steps, current_step) => { + const el_header = document.createElement('div'); + el_header.className = 'form-progress__header'; + + if (isMobile()) { + const el_title = document.createElement('p'); + el_title.className = 'form-progress__step-title'; + el_title.innerHTML = localize('Step [_1]: [_2] ([_1] of [_3])', + [current_step + 1, steps[current_step].title, steps.length]); + el_header.appendChild(el_title); + } else { + const el_steps = document.createElement('div'); + el_steps.className = 'form-progress__steps'; + + const el_steps_before = document.createElement('div'); + el_steps_before.className = 'form-progress__steps--before'; + el_steps_before.style.width = `calc(100% * ${steps.length - 1} / ${steps.length})`; + el_steps.appendChild(el_steps_before); + + steps.forEach((step, index) => { + const el_step = document.createElement('div'); + el_step.key = index + 1; + el_step.className = 'form-progress__step'; + el_step.style = `--step_width: ${steps.length > 4 ? '160px' : '230px'}`; + + const el_identifier = document.createElement('div'); + el_identifier.className = `identifier${index <= current_step ? ' identifier--active' : ''}`; + el_identifier.innerHTML = index + 1; + el_step.appendChild(el_identifier); + + const el_title = document.createElement('p'); + el_title.className = 'form-progress__step-title'; + el_title.innerHTML = step.title; + el_step.appendChild(el_title); + el_steps.appendChild(el_step); + }); + const el_steps_after = document.createElement('div'); + el_steps_after.className = 'form-progress__steps--after'; + el_steps_after.style.width = `calc(${current_step / steps.length} * 100%)`; + el_steps.appendChild(el_steps_after); + el_header.appendChild(el_steps); + } + getElementById(identifire).childNodes.forEach(node => node.parentNode.removeChild(node)); + getElementById(identifire).appendChild(el_header); + }; + + return { + render, + }; +})(); + +module.exports = FormProgress; + diff --git a/src/javascript/app/common/form_validation.js b/src/javascript/app/common/form_validation.js index e8940849547de..2a8fc02d7025f 100644 --- a/src/javascript/app/common/form_validation.js +++ b/src/javascript/app/common/form_validation.js @@ -41,6 +41,8 @@ const Validation = (() => { value = isChecked(field); } else if (field.type === 'radio') { value = field.$.find(`input[name=${field.selector.slice(1)}]:checked`).val(); + } else if (field.type === 'span') { + value = field.$.data().value; } else { value = field.$.val(); } @@ -75,7 +77,9 @@ const Validation = (() => { field.$error = $form.find(field.msg_element); } else { // for password type fields we need to go up one parent due to the password field wrapper - const $parent = field.$.attr('type') === 'password' ? field.$.parent().parent() : field.$.parent(); + let $parent = field.$.attr('type') === 'password' ? field.$.parent().parent() : field.$.parent(); + // correct $parent for select fields (which not using select2) + if ($parent.hasClass('select')) $parent = $parent.parent(); // Add indicator to required fields if (field.validations.find(v => /^req$/.test(v) && (isEmptyObject(v[1]) || !v[1].hide_asterisk))) { let $label = $parent.parent().find('label'); @@ -267,7 +271,7 @@ const Validation = (() => { }; const getTaxRegex = (residence_list, tax_residence) => { - const tin_format = (residence_list.find(residence => residence.value === tax_residence) || {}).tin_format; + const tin_format = (residence_list.find(residence => residence.value === tax_residence) || {}).tin_format; return (tin_format || []).map((format) => new RegExp(format)); }; diff --git a/src/javascript/app/pages/user/accounts.js b/src/javascript/app/pages/user/accounts.js index 476186f9f832c..d89fe1533825a 100644 --- a/src/javascript/app/pages/user/accounts.js +++ b/src/javascript/app/pages/user/accounts.js @@ -1,13 +1,14 @@ -const moment = require('moment'); -const SetCurrency = require('./set_currency'); -const BinaryPjax = require('../../base/binary_pjax'); -const Client = require('../../base/client'); -const BinarySocket = require('../../base/socket'); -const showPopup = require('../../common/attach_dom/popup'); -const Currency = require('../../common/currency'); -const localize = require('../../../_common/localize').localize; -const State = require('../../../_common/storage').State; -const urlFor = require('../../../_common/url').urlFor; +const moment = require('moment'); +const SetCurrency = require('./set_currency'); +const BinaryPjax = require('../../base/binary_pjax'); +const Client = require('../../base/client'); +const BinarySocket = require('../../base/socket'); +const AccountOpening = require('../../common/account_opening'); +const showPopup = require('../../common/attach_dom/popup'); +const Currency = require('../../common/currency'); +const localize = require('../../../_common/localize').localize; +const State = require('../../../_common/storage').State; +const urlFor = require('../../../_common/url').urlFor; const Accounts = (() => { let landing_company; @@ -121,7 +122,10 @@ const Accounts = (() => { '', { class: 'button', - href : urlFor(upgrade_info.upgrade_links[upgrade_info.can_upgrade_to[index]]), + href : AccountOpening.getSinupPageLink( + upgrade_info, + upgrade_info.can_upgrade_to[index] + ), }, ) .html($('', { text: localize('Create account') }))))); @@ -275,7 +279,7 @@ const Accounts = (() => { const populateMultiAccount = () => { const table_headers = TableHeaders.get(); - const account = { real: 1 }; + const account = { real: 1 }; const handleClick = () => showCurrencyPopUp('create'); $(form_id).find('tbody') .append($('', { id: 'new_account_opening' }) diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/address-details-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/address-details-config.js new file mode 100644 index 0000000000000..6f459799f44c1 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/address-details-config.js @@ -0,0 +1,68 @@ +const AddressDetailForm = require('../new_account_modules/address_detail_form'); +const localize = require('../../../../../_common/localize').localize; + +const getAddressDetailsConfig = ({ account_settings, is_svg }) => [ + { + id : 'address_line_1', + section : 'address_section', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.address_line_1 || '', + rules : ['req', 'address', ['length', { min: 1, max: 700 }]], + }, + { + id : 'address_line_2', + section : 'address_section', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.address_line_2 || '', + rules : [['length', { min: 0, max: 70 }]], + }, + { + id : 'address_city', + section : 'address_section', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.address_city || '', + rules : [ + 'req', + ['regular', { regex: /^[a-zA-Z\s\W'.-]{1,35}$/ }], + ], + }, + { + id : 'address_state', + section : 'address_section', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.address_state || '', + rules : [ + ['regular', { regex: /^[\w\s\W'.-;,]{0,60}$/ }], + // Isle of Man and SVG Clients do not need to fill out state. + ...(account_settings.country_code === 'im' || is_svg ? [] : ['req']), + ], + }, + { + id : 'address_postcode', + section : 'address_section', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.address_postcode || '', + rules : [ + ['length', { min: 0, max: 20 }], + 'postcode', + // GB and IM residence are required to fill in the post code. + ...(/^(im|gb)$/.test(account_settings.country_code) ? ['req'] : []), + ], + }, +]; + +const getRequiredFields = (landing_company, all_fields) => + all_fields.filter(field => field.supported_in.includes(landing_company)); + +const addressDetailsConfig = ({ real_account_signup_target, account_settings }) => { + const is_svg = real_account_signup_target === 'svg'; + const config = getAddressDetailsConfig({ account_settings, is_svg }); + return { + title : localize('Address'), + body_module : AddressDetailForm, + body_module_step: 'address_detail_step', + fields : getRequiredFields(real_account_signup_target, config), + }; +}; + +module.exports = addressDetailsConfig; diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/currency-selector-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/currency-selector-config.js new file mode 100644 index 0000000000000..b08a3b105ea2e --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/currency-selector-config.js @@ -0,0 +1,27 @@ +const CurrencyForm = require('../new_account_modules/currency_form'); +const localize = require('../../../../../_common/localize').localize; + +const currency_selector_fields = [ + { + id : 'currency', + supported_in : ['maltainvest', 'malta', 'svg', 'iom'], + default_value: '', + rules : [['custom', { + value : () => $('.currency_wrapper.selected').attr('id') || '', + func : (value) => value !== '', + message: 'Please select the currency for this account.', + }]], + }, +]; + +const getRequiredFields = (landing_company, all_fields) => + all_fields.filter(field => field.supported_in.includes(landing_company)); + +const currencySelectorConfig = ({ real_account_signup_target }) => ({ + title : localize('Account currency'), + body_module : CurrencyForm, + body_module_step: 'currency_step', + fields : getRequiredFields(real_account_signup_target, currency_selector_fields), +}); + +module.exports = currencySelectorConfig; diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/financial-details-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/financial-details-config.js new file mode 100644 index 0000000000000..f18ecc61dc8de --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/financial-details-config.js @@ -0,0 +1,138 @@ +const FinancialDetailForm = require('../new_account_modules/financial_detail_form'); +const localize = require('../../../../../_common/localize').localize; + +const getFinancialDetailsConfig = ({ financial_assessment }) => [ + { + id : 'income_source', + section : 'financial_information', + default_value: financial_assessment.income_source || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'employment_status', + section : 'financial_information', + default_value: financial_assessment.employment_status || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'employment_industry', + section : 'financial_information', + default_value: financial_assessment.employment_industry || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'occupation', + section : 'financial_information', + default_value: financial_assessment.occupation || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'source_of_wealth', + section : 'financial_information', + default_value: financial_assessment.source_of_wealth || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'education_level', + section : 'financial_information', + supported_in : ['maltainvest'], + default_value: financial_assessment.education_level || '', + rules : ['req'], + }, + { + id : 'net_income', + section : 'financial_information', + default_value: financial_assessment.net_income || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'estimated_worth', + section : 'financial_information', + default_value: financial_assessment.estimated_worth || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'account_turnover', + section : 'financial_information', + supported_in : ['maltainvest'], + default_value: financial_assessment.account_turnover || '', + rules : ['req'], + }, + { + id : 'forex_trading_experience', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.forex_trading_experience || '', + rules : ['req'], + }, + { + id : 'forex_trading_frequency', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.forex_trading_frequency || '', + rules : ['req'], + }, + { + id : 'binary_options_trading_experience', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.binary_options_trading_experience || '', + rules : ['req'], + }, + { + id : 'binary_options_trading_frequency', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.binary_options_trading_frequency || '', + rules : ['req'], + }, + { + id : 'cfd_trading_experience', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.cfd_trading_experience || '', + rules : ['req'], + }, + { + id : 'cfd_trading_frequency', + section : 'trading_experience', + supported_in : ['maltainvest'], + default_value: financial_assessment.cfd_trading_frequency || '', + rules : ['req'], + }, + { + id : 'other_instruments_trading_experience', + section : 'trading_experience', + default_value: financial_assessment.other_instruments_trading_experience || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, + { + id : 'other_instruments_trading_frequency', + section : 'trading_experience', + default_value: financial_assessment.other_instruments_trading_frequency || '', + supported_in : ['maltainvest'], + rules : ['req'], + }, +]; + +const getRequiredFields = (landing_company, all_fields) => + all_fields.filter(field => field.supported_in.includes(landing_company)); + +const financialDetailsConfig = ({ real_account_signup_target, financial_assessment }) => { + const config = getFinancialDetailsConfig({ financial_assessment }); + return { + title : localize('Financial assessment'), + body_module : FinancialDetailForm, + body_module_step: 'financial_info_step', + fields : getRequiredFields(real_account_signup_target, config), + }; +}; +module.exports = financialDetailsConfig; diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/personal-details-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/personal-details-config.js new file mode 100644 index 0000000000000..1c107763546e6 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/personal-details-config.js @@ -0,0 +1,114 @@ +const localize = require('../../../../../_common/localize').localize; +const PersonalDetailForm = require('../new_account_modules/personal_detail_form'); + +const getPersonalDetailsConfig = ({ account_settings, residence_list }) => { + const config = [ + { + id : 'salutation', + section : 'name', + supported_in : ['iom', 'malta', 'maltainvest'], + default_value: account_settings.salutation || '', + is_immutable : true, + rules : ['req'], + }, + { + id : 'first_name', + section : 'name', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.first_name || '', + is_immutable : true, + rules : ['req', 'letter_symbol', ['length', { min: 2, max: 50 }]], + }, + { + id : 'last_name', + section : 'name', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.last_name || '', + is_immutable : true, + rules : ['req', 'letter_symbol', ['length', { min: 2, max: 50 }]], + }, + { + id : 'date_of_birth', + section : 'detail', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.date_of_birth + ? account_settings.date_of_birth + : '', + is_immutable: true, + rules : ['req'], + }, + { + id : 'place_of_birth', + section : 'detail', + supported_in : ['maltainvest', 'iom', 'malta'], + default_value: account_settings.place_of_birth || '', + is_immutable : true, + rules : ['req'], + }, + { + id : 'citizen', + section : 'detail', + supported_in : ['iom', 'malta', 'maltainvest'], + default_value: account_settings.citizen || '', + is_immutable : true, + rules : ['req'], + }, + { + id : 'phone', + section : 'detail', + supported_in : ['svg', 'iom', 'malta', 'maltainvest'], + default_value: account_settings.phone || '', + rules : ['req', 'phone', ['length', + { min: 9, max: 35, value: () => $('#phone').val().replace(/\D/g, '') }, + ]], + }, + { + id : 'tax_residence', + section : 'tax', + supported_in : ['maltainvest'], + default_value: account_settings.tax_residence || '', + rules : ['req', ['length', { min: 1, max: 20 }]], + }, + { + id : 'tax_identification_number', + section : 'tax', + supported_in : ['maltainvest'], + default_value: account_settings.tax_identification_number || '', + rules : [ + 'req', + ['tax_id', { residence_list, $warning: $('#tax_id_warning'), $tax_residence: $('#tax_residence') }], + ['length', { min: 1, max: 20 }], + ], + }, + { + id : 'tax_identification_confirm', + section : 'tax', + supported_in : ['maltainvest'], + default_value: false, + rules : ['req'], + }, + { + id : 'account_opening_reason', + section : 'account_opening_reason', + supported_in : ['iom', 'malta', 'maltainvest'], + default_value: account_settings.account_opening_reason || '', + rules : ['req'], + }, + ]; + return config; +}; + +const getRequiredFields = (landing_company, all_fields) => + all_fields.filter(field => field.supported_in.includes(landing_company)); + +const personalDetailsConfig = ({ real_account_signup_target, account_settings, residence_list }) => { + const config = getPersonalDetailsConfig({ account_settings, residence_list }); + return { + title : localize('Personal details'), + body_module : PersonalDetailForm, + body_module_step: 'personal_detail_step', + fields : getRequiredFields(real_account_signup_target, config), + }; +}; + +module.exports = personalDetailsConfig; diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/terms-of-use-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/terms-of-use-config.js new file mode 100644 index 0000000000000..1c9784b6749af --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/terms-of-use-config.js @@ -0,0 +1,49 @@ +const localize = require('../../../../../_common/localize').localize; +const TermsOfUseForm = require('../new_account_modules/terms_of_use_form'); + +const getTermsOfUseConfig = [ + { + id : 'jurisdiction', + section : 'terms_of_use_section', + supported_in: ['maltainvest', 'svg', 'iom', 'malta'], + rules : [], + }, + { + id : 'fs_professional', + section : 'terms_of_use_section', + supported_in: ['maltainvest'], + rules : [], + }, + { + id : 'risk_disclaimer', + section : 'terms_of_use_section', + supported_in: ['maltainvest', 'svg'], + rules : [], + }, + { + id : 'pep_declaration', + section : 'terms_of_use_section', + supported_in : ['maltainvest', 'iom', 'malta', 'svg'], + default_value: false, + rules : ['req'], + }, + { + id : 'tnc', + section : 'terms_of_use_section', + supported_in : ['maltainvest', 'svg', 'iom', 'malta'], + default_value: false, + rules : ['req'], + }, +]; + +const getRequiredFields = (landing_company, all_fields) => + all_fields.filter(field => field.supported_in.includes(landing_company)); + +const termsOfUseConfig = ({ real_account_signup_target }) => ({ + title : localize('Terms of use'), + body_module : TermsOfUseForm, + body_module_step: 'terms_of_use_step', + fields : getRequiredFields(real_account_signup_target, getTermsOfUseConfig), +}); + +module.exports = termsOfUseConfig; diff --git a/src/javascript/app/pages/user/new_account/new_account_form_config/wizard-step-config.js b/src/javascript/app/pages/user/new_account/new_account_form_config/wizard-step-config.js new file mode 100644 index 0000000000000..9896a7610f330 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_form_config/wizard-step-config.js @@ -0,0 +1,18 @@ +const addressDetailsConfig = require('./address-details-config'); +const currencySelectorConfig = require('./currency-selector-config'); +const financialDetailsConfig = require('./financial-details-config'); +const personalDetailsConfig = require('./personal-details-config'); +const termsOfUseConfig = require('./terms-of-use-config'); + +const shouldShowFinancialDetails = ({ real_account_signup_target }) => real_account_signup_target === 'maltainvest'; +const shouldShowPersonalAndAddressDetailsAndCurrency = ({ real_account_signup_target }) => real_account_signup_target !== 'samoa'; + +const getSteps = props => [ + ...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [currencySelectorConfig(props)] : []), + ...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [personalDetailsConfig(props)] : []), + ...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [addressDetailsConfig(props)] : []), + ...(shouldShowFinancialDetails(props) ? [financialDetailsConfig(props)] : []), + termsOfUseConfig(props), +]; + +module.exports = getSteps; diff --git a/src/javascript/app/pages/user/new_account/new_account_modules/address_detail_form.js b/src/javascript/app/pages/user/new_account/new_account_modules/address_detail_form.js new file mode 100644 index 0000000000000..85d45d7c08b11 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_modules/address_detail_form.js @@ -0,0 +1,56 @@ +const SelectMatcher = require('@binary-com/binary-style').select2Matcher; +const Client = require('../../../../base/client'); +const BinarySocket = require('../../../../base/socket'); +const getElementById = require('../../../../../_common/common_functions').getElementById; +const makeOption = require('../../../../../_common/common_functions').makeOption; +const localize = require('../../../../../_common/localize').localize; + +const AddressDetailForm = (() => { + + const init = async (fields) => { + const text_fields = ['address_line_1', 'address_line_2', 'address_city', 'address_postcode']; + fields.forEach(async field => { + if (text_fields.includes(field.id)) { + $(`#${field.id}`).text(field.default_value); + $(`#${field.id}`) + .val(field.default_value) // Set value for validation + .attr({ 'data-force': true, 'data-value': field.default_value }); + } + if (field.id === 'address_state') await initializeState(field); + + getElementById(`${field.section}_section`).setVisibility(1); + getElementById(`${field.id}_row`).setVisibility(1); + }); + }; + + const initializeState = async (field) => { + let $address_state = $('#address_state'); + const state_list = (await BinarySocket.send({ states_list: Client.get('residence') })).states_list; + if (state_list && state_list.length > 0) { + [{ text: localize('Please select'), value: '' }].concat(state_list).forEach((state) => { + $address_state.append(makeOption({ text: state.text, value: state.value })); + }); + if (field.default_value !== '') $address_state.val(field.default_value); + $address_state.select2({ + matcher(params, data) { + return SelectMatcher(params, data); + }, + }); + } else { + $address_state.replaceWith($('', + { id: 'address_state', name: 'address_state', type: 'text', maxlength: '35', 'data-lpignore': true })); + $address_state = $('#address_state'); + if (field.default_value !== '') { + const state_name = state_list.find(obj => obj.value === field.default_value).text; + $address_state.text(state_name); + } + } + }; + + return { + init, + }; + +})(); + +module.exports = AddressDetailForm; diff --git a/src/javascript/app/pages/user/new_account/new_account_modules/currency_form.js b/src/javascript/app/pages/user/new_account/new_account_modules/currency_form.js new file mode 100644 index 0000000000000..d4b2cdf7abfd0 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_modules/currency_form.js @@ -0,0 +1,123 @@ +const BinarySocket = require('../../../../base/socket'); +const Currency = require('../../../../common/currency'); +const localize = require('../../../../../_common/localize').localize; +const Url = require('../../../../../_common/url'); + +const SetCurrency = (() => { + let $error, + $currency_list; + + const currencies_display_order = [ + 'USD', + 'EUR', + 'GBP', + 'AUD', + 'BTC', + 'ETH', + 'LTC', + 'UST', + 'eUSDT', + 'BUSD', + 'DAI', + 'EURS', + 'IDK', + 'PAX', + 'TUSD', + 'USDC', + 'USDK', + ]; + + const init = async (_, real_account_signup_target) => { + $currency_list = $('.currency_list'); + $error = $('#set_currency').find('.error-msg'); + const landing_company = (await BinarySocket.wait('landing_company')).landing_company; + + populateCurrencies(getAvailableCurrencies(landing_company, real_account_signup_target)); + onSelection(true); + }; + + const getAvailableCurrencies = (landing_company, real_account_signup_target) => { + const target = getTargetCompany(landing_company, real_account_signup_target); + if (landing_company[`${target}_company`]) { + return getSortedCurrencies(landing_company[`${target}_company`].legal_allowed_currencies); + } + return []; + }; + + const getTargetCompany = (landing_company, real_account_signup_target) => { + if (real_account_signup_target === 'maltainvest') return 'financial'; + return landing_company.gaming_company ? 'gaming' : 'financial'; + }; + + const getSortedCurrencies = (currency_list) => currency_list.sort((a, b) => { + if (currencies_display_order.indexOf(a) < currencies_display_order.indexOf(b)) { + return -1; + } + if (currencies_display_order.indexOf(a) > currencies_display_order.indexOf(b)) { + return 1; + } + return 0; + }); + + const populateCurrencies = (currencies) => { + const $fiat_currencies = $('
'); + const $cryptocurrencies = $('
'); + currencies.forEach((c) => { + const $wrapper = $('
', { class: 'gr-2 gr-6-m currency_wrapper', id: c }); + const $image = $('
').append($('', { src: Url.urlForStatic(`images/pages/set_currency/${c.toLowerCase()}.svg`) })); + const $name = $('
', { class: 'currency-name' }); + + if (Currency.isCryptocurrency(c)) { + const $display_name = $('', { + text: Currency.getCurrencyName(c) || c, + ...(/^UST$/.test(c) && { + 'data-balloon' : localize('Tether Omni (USDT) is a version of Tether that\'s pegged to USD and is built on the Bitcoin blockchain.'), + 'data-balloon-length': 'medium', + 'data-balloon-pos' : 'top', + 'class' : 'show-mobile', + }), + ...(/^eUSDT/.test(c) && { + 'data-balloon' : localize('Tether ERC20 (eUSDT) is a version of Tether that\'s pegged to USD and is hosted on the Ethereum platform.'), + 'data-balloon-length': 'medium', + 'data-balloon-pos' : 'top', + 'class' : 'show-mobile', + }), + }); + + $name.append($display_name).append($('
')).append(`(${Currency.getCurrencyDisplayCode(c)})`); + } else { + $name.text(c); + } + + $wrapper.append($image).append($name); + (Currency.isCryptocurrency(c) ? $cryptocurrencies : $fiat_currencies).append($wrapper); + }); + const fiat_currencies = $fiat_currencies.html(); + if (fiat_currencies) { + $('#fiat_currencies').setVisibility(1); + $('#fiat_currency_list').html(fiat_currencies).parent().setVisibility(1); + } + const crypto_currencies = $cryptocurrencies.html(); + if (crypto_currencies) { + $('#crypto_currencies').setVisibility(1); + $('#crypto_currency_list').html(crypto_currencies).parent().setVisibility(1); + } + + $('#set_currency, .select_currency').setVisibility(1); + }; + + const onSelection = () => { + $('.currency_wrapper').off('click dblclick').on('click dblclick', function () { + if ($error) $error.setVisibility(0); + const $clicked_currency = $(this); + $currency_list.find('> div').removeClass('selected'); + $clicked_currency.addClass('selected'); + }); + }; + + return { + init, + }; +})(); + +module.exports = SetCurrency; diff --git a/src/javascript/app/pages/user/new_account/new_account_modules/financial_detail_form.js b/src/javascript/app/pages/user/new_account/new_account_modules/financial_detail_form.js new file mode 100644 index 0000000000000..a2ead1c9da8b1 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_modules/financial_detail_form.js @@ -0,0 +1,18 @@ +const getElementById = require('../../../../../_common/common_functions').getElementById; + +const FinancialDetailForm = (() => { + + const init = async (fields) => { + fields.forEach(field => { + getElementById(`${field.id}`).value = field.default_value; + getElementById(`${field.section}_section`).setVisibility(1); + getElementById(`${field.id}_row`).setVisibility(1); + }); + }; + + return { + init, + }; +})(); + +module.exports = FinancialDetailForm; diff --git a/src/javascript/app/pages/user/new_account/new_account_modules/personal_detail_form.js b/src/javascript/app/pages/user/new_account/new_account_modules/personal_detail_form.js new file mode 100644 index 0000000000000..9a9c082991c90 --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_modules/personal_detail_form.js @@ -0,0 +1,79 @@ +const SelectMatcher = require('@binary-com/binary-style').select2Matcher; +const moment = require('moment'); +const Client = require('../../../../base/client'); +const generateBirthDate = require('../../../../../app/common/attach_dom/birth_date_picker'); +const BinarySocket = require('../../../../base/socket'); +const localize = require('../../../../../_common/localize').localize; +const getElementById = require('../../../../../_common/common_functions').getElementById; +const makeOption = require('../../../../../_common/common_functions').makeOption; +const State = require('../../../../../_common/storage').State; +const toISOFormat = require('../../../../../_common/string_util').toISOFormat; +const toReadableFormat = require('../../../../../_common/string_util').toReadableFormat; + +const PersonalDetailForm = (() => { + + const init = async (fields) => { + const residence_list = (await BinarySocket.wait('residence_list')).residence_list; + const client_residence = Client.get('residence') || ''; + const landing_company = State.getResponse('landing_company'); + + const $options = $('
'); + residence_list.forEach((residence) => { + $options.append(makeOption({ text: residence.text, value: residence.value })); + }); + + if (fields.some(field => field.id === 'salutation')) getElementById('name_section_legend').innerHTML = localize('Title and name'); + + const residence_select_fields = ['place_of_birth', 'citizen', 'tax_residence']; + const simple_select_fields = ['salutation', 'account_opening_reason']; + const text_fields = ['first_name', 'last_name', 'tax_identification_number']; + + fields.forEach(field => { + if (residence_select_fields.includes(field.id)) { + if (field.is_immutable && field.default_value !== '') { + const country_name = residence_list.find(obj => obj.value === field.default_value).text; + $(`#${field.id}`).replaceWith($('', { id: field.id, text: country_name, 'data-value': field.default_value })); + } else { + $(`#${field.id}`).html($options.html()).val(field.default_value); + $(`#${field.id}`).select2({ + matcher(params, data) { + return SelectMatcher(params, data); + }, + }); + } + } + if (simple_select_fields.includes(field.id)) { + $(`#${field.id}`).addClass('center-select-m').val(field.default_value); + } + if (text_fields.includes(field.id)) { + $(`#${field.id}`).text(field.default_value); + $(`#${field.id}`) + .val(field.default_value) // Set value for validation + .attr({ 'data-force': true, 'data-value': field.default_value }); + } + if (field.id === 'date_of_birth') { + generateBirthDate(landing_company.minimum_age); + if (field.default_value !== '') { + const dob_moment_object = moment.unix(field.default_value); + $(`#${field.id}`) + .attr('data-value', toISOFormat(dob_moment_object)) + .val(toReadableFormat(dob_moment_object)); + } + } + if (field.id === 'phone') { + const residence_phone_idd = + residence_list.find(residence => residence.value === client_residence).phone_idd; + $(`#${field.id}`).val(field.default_value !== '' ? field.default_value : `+${residence_phone_idd}`); + } + getElementById(`${field.section}_section`).setVisibility(1); + getElementById(`${field.id}_row`).setVisibility(1); + if (field.is_immutable && field.default_value !== '') $(`#${field.id}`).attr('disabled', 'disabled'); + }); + }; + + return { + init, + }; +})(); + +module.exports = PersonalDetailForm; diff --git a/src/javascript/app/pages/user/new_account/new_account_modules/terms_of_use_form.js b/src/javascript/app/pages/user/new_account/new_account_modules/terms_of_use_form.js new file mode 100644 index 0000000000000..58ab171c09abb --- /dev/null +++ b/src/javascript/app/pages/user/new_account/new_account_modules/terms_of_use_form.js @@ -0,0 +1,51 @@ +const professionalClient = require('../../../../pages/user/account/settings/professional_client'); +const getElementById = require('../../../../../_common/common_functions').getElementById; +const localize = require('../../../../../_common/localize').localize; +const State = require('../../../../../_common/storage').State; + +const TermsOfUseForm = (() => { + const init = async (fields, real_account_signup_target) => { + const landing_company = State.getResponse('landing_company'); + const lc_to_upgrade_to = + landing_company[real_account_signup_target === 'maltainvest' + ? 'financial_company' + : 'gaming_company' + ] || landing_company.financial_company; + getElementById('lc-name').innerHTML = lc_to_upgrade_to.name; + getElementById('lc-country').innerHTML = lc_to_upgrade_to.shortcode === 'iom' ? `the ${lc_to_upgrade_to.country}` : lc_to_upgrade_to.country; + getElementById('lc-regulator').innerHTML = getRegulatorText(lc_to_upgrade_to.shortcode); + + $('#pep_declaration_note_toggle').off('click').on('click', (e) => { + e.stopPropagation(); + $('#pep_declaration_note_toggle').toggleClass('open'); + $('#pep_declaration_note').slideToggle(); + }); + + if (lc_to_upgrade_to.shortcode === 'maltainvest') { + professionalClient.init(real_account_signup_target === 'maltainvest', false); + } + fields.forEach(field => { + getElementById(`${field.section}_section`).setVisibility(1); + getElementById(`${field.id}_row`).setVisibility(1); + }); + }; + + const getRegulatorText = (shortcode) => { + switch (shortcode) { + case 'iom': + return localize('regulated by the UK Gaming Commission (UKGC),'); + case 'malta': + return localize('regulated by the Malta Gaming Authority,'); + case 'maltainvest': + return localize('regulated by the Malta Financial Services Authority (MFSA),'); + default: + return ''; + } + }; + + return { + init, + }; +})(); + +module.exports = TermsOfUseForm; diff --git a/src/javascript/app/pages/user/new_account/real_acc_opening.js b/src/javascript/app/pages/user/new_account/real_acc_opening.js index 346a9b36d91d6..b936b0b0bb1cd 100644 --- a/src/javascript/app/pages/user/new_account/real_acc_opening.js +++ b/src/javascript/app/pages/user/new_account/real_acc_opening.js @@ -39,12 +39,16 @@ const RealAccOpening = (() => { $('#tax_information_note_toggle').toggleClass('open'); $('#tax_information_note').slideToggle(); }); + + getElementById('real_loading').setVisibility(0); + getElementById('frm_real').setVisibility(1); + + AccountOpening.showHidePulser(0); + AccountOpening.registerPepToggle(); }); } else { BinaryPjax.loadPreviousUrl(); } - AccountOpening.showHidePulser(0); - AccountOpening.registerPepToggle(); }; const getValidations = () => { diff --git a/src/javascript/app/pages/user/new_account/real_account_opening.js b/src/javascript/app/pages/user/new_account/real_account_opening.js new file mode 100644 index 0000000000000..e84470d203c8a --- /dev/null +++ b/src/javascript/app/pages/user/new_account/real_account_opening.js @@ -0,0 +1,119 @@ +const getSteps = require('./new_account_form_config/wizard-step-config'); +const Client = require('../../../base/client'); +const BinarySocket = require('../../../base/socket'); +const AccountOpening = require('../../../common/account_opening'); +const FormManager = require('../../../common/form_manager'); +const FormProgress = require('../../../common/form_progress'); +const getElementById = require('../../../../_common/common_functions').getElementById; +const param = require('../../../../_common/url').param; +const { localize } = require('../../../../_common/localize'); + +const RealAccountOpening = (() => { + let real_account_signup_target, + steps, + current_step, + account_details, + action_previous_buttons; + + const onLoad = async () => { + real_account_signup_target = param('account_type'); + const currency_to_set = sessionStorage.getItem('new_financial_account_set_currency'); + if (currency_to_set) AccountOpening.setCurrencyForFinancialAccount(currency_to_set); + else { + const residence_list_promise = BinarySocket.send({ residence_list: 1 }); + const account_settings_promise = BinarySocket.send({ get_settings: 1 }); + const financial_assessment_promise = BinarySocket.send({ get_financial_assessment: 1 }); + const [residence_list_response, account_settings_response, financial_assessment_response] = + await Promise.all([residence_list_promise, account_settings_promise, financial_assessment_promise]); + const account_settings = account_settings_response.get_settings; + const residence_list = residence_list_response.residence_list; + const financial_assessment = financial_assessment_response.get_financial_assessment || {}; + if (AccountOpening.redirectAccount()) return; + const upgrade_info = Client.getUpgradeInfo(); + + account_details = { residence: account_settings.country_code }; + Object.assign(account_details, + real_account_signup_target === 'maltainvest' + ? { new_account_maltainvest: 1, accept_risk: 0 } + : { new_account_real: 1 } + ); + + action_previous_buttons = document.getElementsByClassName('action_previous'); + Array.from(action_previous_buttons).forEach(item => { item.addEventListener('click', onClickPrevious); }); + getElementById('financial_risk_warning').addEventListener('submit', onRiskAccept); + + steps = getSteps({ + real_account_signup_target, + residence_list, + account_settings, + upgrade_info, + financial_assessment, + }); + current_step = 0; + steps.forEach(step => { step.body_module.init(step.fields, real_account_signup_target); }); + + setPageTitle(); + getElementById('loading').setVisibility(0); + getElementById('real_account_wrapper').setVisibility(1); + getElementById('account_opening_steps').setVisibility(1); + renderStep(); + } + }; + + const renderStep = (previous_step = 0) => { + FormProgress.render('form_progress', steps, current_step); + + if (previous_step >= 0) getElementById(steps[previous_step].body_module_step).setVisibility(0); + getElementById(steps[current_step].body_module_step).setVisibility(1); + + FormManager.init(`#${steps[current_step].body_module_step}_form`, getValidationRules(steps[current_step])); + FormManager.handleSubmit({ + form_selector : `#${steps[current_step].body_module_step}_form`, + get_submitted_data: onStepSubmitted, + }); + $.scrollTo(0, 500); + }; + + const onRiskAccept = (e) => { + e.preventDefault(); + Object.assign(account_details, { accept_risk: 1 }); + AccountOpening.createNewAccount(account_details, $('#financial_risk_accept')); + }; + + const onStepSubmitted = async (req) => { + Object.assign(account_details, req); + if (current_step === steps.length - 1) { + const should_show_financial_risk_warning = await AccountOpening.createNewAccount(account_details, $('#new_account_submit')); + if (should_show_financial_risk_warning) showFinancialRiskWarning(); + } else renderStep(current_step++); + }; + + const showFinancialRiskWarning = () => { + getElementById('account_opening_steps').setVisibility(0); + getElementById('financial_risk_warning').setVisibility(1); + $.scrollTo(0, 500); + }; + + const onClickPrevious = () => renderStep(current_step--); + + const getValidationRules = (step) => step.fields.map(field => ({ + selector : `#${field.id}`, + validations: field.rules, + })); + + const setPageTitle = () => { + getElementById('page_title').innerHTML = + real_account_signup_target === 'maltainvest' + ? localize('Financial Account Opening') + : localize('Real money account opening'); + }; + + const onUnload = () => { AccountOpening.showHidePulser(1); }; + + return { + onLoad, + onUnload, + }; +})(); + +module.exports = RealAccountOpening; diff --git a/src/javascript/app/pages/user/new_account/welcome_page.js b/src/javascript/app/pages/user/new_account/welcome_page.js index 47fe8950ca075..d3849b61e930b 100644 --- a/src/javascript/app/pages/user/new_account/welcome_page.js +++ b/src/javascript/app/pages/user/new_account/welcome_page.js @@ -1,10 +1,12 @@ -const BinarySocket = require('../../../base/socket'); -const Client = require('../../../base/client'); -const getElementById = require('../../../../_common/common_functions').getElementById; -const localize = require('../../../../_common/localize').localize; -const Url = require('../../../../_common/url'); -const createElement = require('../../../../_common/utility').createElement; -const showLoadingImage = require('../../../../_common/utility').showLoadingImage; +const BinarySocket = require('../../../base/socket'); +const Client = require('../../../base/client'); +const excluded_countries = require('../../../common/account_opening').excluded_countries; +const getElementById = require('../../../../_common/common_functions').getElementById; +const localize = require('../../../../_common/localize').localize; +const State = require('../../../../_common/storage').State; +const Url = require('../../../../_common/url'); +const createElement = require('../../../../_common/utility').createElement; +const showLoadingImage = require('../../../../_common/utility').showLoadingImage; const WelcomePage = (() => { const onLoad = () => { @@ -28,21 +30,30 @@ const WelcomePage = (() => { } el_upgrade_title.html(upgrade_btn_txt); el_welcome_container.setVisibility(1); - + const upgrade_url = upgrade_info.can_upgrade_to.length > 1 - ? 'user/accounts' - : Object.values(upgrade_info.upgrade_links)[0]; + ? Url.urlFor('user/accounts') + : getUpgradeAccountLink(upgrade_info); if (upgrade_info.can_upgrade) { const upgrade_btn = getElementById('upgrade_btn'); if (upgrade_btn) { - upgrade_btn.html(createElement('span', { text: localize('Upgrade now') })).setAttribute('href', Url.urlFor(upgrade_url)); + upgrade_btn.html(createElement('span', { text: localize('Upgrade now') })).setAttribute('href', upgrade_url); upgrade_btn.classList.remove('button-disabled'); } } }); }; + const getUpgradeAccountLink = (upgrade_info) => { + const country_code = State.getResponse('get_settings').country_code; + if (!excluded_countries.includes(country_code)) { // old flow + return Url.urlFor(Object.values(upgrade_info.upgrade_links)[0]); + } + return Url.urlFor('/new_account/real_account', `account_type=${upgrade_info.can_upgrade_to[0]}`); + + }; + return { onLoad, }; diff --git a/src/javascript/app/pages/user/set_currency.js b/src/javascript/app/pages/user/set_currency.js index f7a4b9174beed..722ec2f5b822a 100644 --- a/src/javascript/app/pages/user/set_currency.js +++ b/src/javascript/app/pages/user/set_currency.js @@ -31,19 +31,37 @@ const SetCurrency = (() => { const payout_currencies = (await BinarySocket.wait('payout_currencies')).payout_currencies; const $currency_list = $('.currency_list'); - const $error = $('#set_currency').find('.error-msg'); + const $error = $('#set_currency').find('.error-msg'); + + $('#deposit_btn').off('click dblclick').on('click dblclick', () => { + if (popup_action) { + cleanupPopup(); + } + BinaryPjax.load(`${Url.urlFor('cashier/forwardws')}?action=deposit`); + }); + $('#maybe_later_btn').off('click dblclick').on('click dblclick', () => { + const url = Client.isAccountOfType('financial') ? Url.urlFor('user/metatrader') : Client.defaultRedirectUrl(); + BinaryPjax.load(url); + }); + + $('#deposit_btn').off('click dblclick').on('click dblclick', () => { + if (popup_action) { + cleanupPopup(); + } + BinaryPjax.load(`${Url.urlFor('cashier/forwardws')}?action=deposit`); + }); + $('#maybe_later_btn').off('click dblclick').on('click dblclick', () => { + const url = Client.isAccountOfType('financial') ? Url.urlFor('user/metatrader') : Client.defaultRedirectUrl(); + BinaryPjax.load(url); + }); popup_action = localStorage.getItem('popup_action'); if (Client.get('currency') || popup_action) { if (is_new_account) { $('#set_currency_loading').remove(); $('#set_currency').setVisibility(1); - $('#deposit_btn') - .off('click dblclick') - .on('click dblclick', () => { - BinaryPjax.load(`${Url.urlFor('cashier/forwardws')}?action=deposit`); - }) - .setVisibility(1); + $('#deposit_row').setVisibility(1); + $('#congratulations_message').html(localize('You have added a [_1] account.', [Client.get('currency')])); } else if (popup_action) { const currencies = /multi_account|set_currency/.test(popup_action) ? getAvailableCurrencies(landing_company, payout_currencies) : @@ -99,7 +117,7 @@ const SetCurrency = (() => { const $fiat_currencies = $('
'); const $cryptocurrencies = $('
'); currencies.forEach((c) => { - const $wrapper = $('
', { class: 'gr-2 gr-4-m currency_wrapper', id: c }); + const $wrapper = $('
', { class: 'gr-2 gr-6-m currency_wrapper', id: c }); const $image = $('
').append($('', { src: Url.urlForStatic(`images/pages/set_currency/${c.toLowerCase()}.svg`) })); const $name = $('
', { class: 'currency-name' }); if (Currency.isCryptocurrency(c)) { @@ -244,7 +262,7 @@ const SetCurrency = (() => { $('#congratulations_message').html( popup_action === 'set_currency' ? localize('You have successfully set your account currency to [_1].', [`${selected_currency_display}`]) : - localize('You have successfully changed your account currency from [_1] to [_2].', [ `${previous_currency_display}`, `${selected_currency_display}` ]) + localize('You have successfully changed your account currency from [_1] to [_2].', [`${previous_currency_display}`, `${selected_currency_display}`]) ); $('.btn_cancel, #deposit_btn, #set_currency, #show_new_account').setVisibility(1); $(`#${Client.get('loginid')}`).find('td[datath="Currency"]').text(selected_currency_display); @@ -269,15 +287,7 @@ const SetCurrency = (() => { } else { Header.populateAccountsList(); // update account title $('.select_currency').setVisibility(0); - $('#deposit_btn') - .off('click dblclick') - .on('click dblclick', () => { - if (popup_action) { - cleanupPopup(); - } - BinaryPjax.load(`${Url.urlFor('cashier/forwardws')}?action=deposit`); - }) - .setVisibility(1); + $('#deposit_row').setVisibility(1); } } }); @@ -295,7 +305,7 @@ const SetCurrency = (() => { * @param {boolean} is_btn_enabled // Enable button */ const removeError = ($error, is_btn_enabled) => { - if ($error){ + if ($error) { $error.setVisibility(0); } if ($submit && is_btn_enabled) { @@ -306,7 +316,7 @@ const SetCurrency = (() => { const populateReqMultiAccount = (selected_currency) => { const get_settings = State.getResponse('get_settings'); - return ({ + const request = { new_account_real : 1, currency : selected_currency, date_of_birth : moment.utc(+get_settings.date_of_birth * 1000).format('YYYY-MM-DD'), @@ -329,7 +339,11 @@ const SetCurrency = (() => { ...(get_settings.tax_residence && { tax_residence: get_settings.tax_residence, }), + }; + Object.keys(request).forEach(key => { + if (!request[key] || request[key] === '') delete request[key]; }); + return request; }; const cleanupPopup = () => { diff --git a/src/sass/_common/common.scss b/src/sass/_common/common.scss index de466e3b3e26c..ee257f8e5956f 100755 --- a/src/sass/_common/common.scss +++ b/src/sass/_common/common.scss @@ -194,6 +194,10 @@ label { line-height: 25px; } +.fieldset_margin_top { + margin-top: 2rem; +} + /* used for form label in grid structure */ .form_label { @include BIDIR_VALUE(text-align, right, left); @@ -232,6 +236,10 @@ label { margin: 0 !important; } +.auto-margin { + margin: auto !important; +} + .full-height { height: 100%; } @@ -930,6 +938,14 @@ label + input { } } +#real_account_wrapper input { + width: 100%; + max-width: 340px; + @media screen and (max-width: 768px) { + box-sizing: border-box; + } +} + /* TODO: remove when UX research is finished */ #interview_popup_container { height: 100vh; diff --git a/src/sass/_common/form_progress.scss b/src/sass/_common/form_progress.scss new file mode 100644 index 0000000000000..b22e305205ab9 --- /dev/null +++ b/src/sass/_common/form_progress.scss @@ -0,0 +1,81 @@ +.form-progress { + width: 100%; + + &__header { + display: flex; + flex-direction: column; + justify-content: center; + margin-bottom: 1rem; + + @media (min-width: 768px) { + align-items: center; + margin-bottom: 1.5rem; + } + } + &__step { + align-items: center; + display: flex; + flex-direction: column; + height: 6rem; + justify-content: space-around; + width: var(--step_width); + + & .identifier { + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + width: 40px; + height: 40px; + background-color: $COLOR_LIGHT_GRAY; + border: 1px solid $COLOR_LIGHT_GRAY; + color: $COLOR_BLACK; + line-height: 40px; + z-index: 2; + + &--active { + background-color: $COLOR_ORANGE !important; + color: $COLOR_WHITE; + border: 1px solid $COLOR_ORANGE !important; + transition: all 0.3s ease; + } + } + &-title { + font-size: $FONT_SIZE_S; + @media (max-width: 480px) { + margin: 0.5rem 0; + } + } + } + &__steps { + align-items: center; + display: flex; + justify-content: center; + margin-top: 20px; + position: relative; + + &--before { + bottom: 0; + content: ''; + left: 0; + margin: 0 auto; /* this centers the line to the full width specified */ + position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */ + right: 0; + top: 1.4rem; + border-top: 2px solid $COLOR_LIGHT_GRAY; + z-index: 0; + } + &--after { + border-top: 2px solid $COLOR_ORANGE; + bottom: 0; + content: ''; + left: 0; + margin: 0 auto; /* this centers the line to the full width specified */ + position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */ + top: 1.4rem; + transition: width 0.3s ease; + transform: translateX(100px); + z-index: 1; + } + } +} diff --git a/src/sass/common.scss b/src/sass/common.scss index 7fd1f4cbe14cf..7ea5a4079020c 100755 --- a/src/sass/common.scss +++ b/src/sass/common.scss @@ -11,6 +11,7 @@ @import '_common/jquery_elements'; @import '_common/table'; @import '_common/img_lightbox'; +@import '_common/form_progress.scss'; /* language based rules */ @import '_common/base/language_base'; diff --git a/src/sass/static/pages.scss b/src/sass/static/pages.scss index 2fbb13e5a40a7..52903060835c7 100644 --- a/src/sass/static/pages.scss +++ b/src/sass/static/pages.scss @@ -805,9 +805,14 @@ body #not_authenticated_financial ul.checked > li { } #set_currency { - #frm_set_currency { + #currency_step_form { .section-divider { - max-width: 500px; + max-width: 600px; + } + } + .set_currency_hint { + @media screen and (max-width: 480px) { + text-align: left; } } .currency_list > div { @@ -859,6 +864,78 @@ body #not_authenticated_financial ul.checked > li { } } +#submit_section { + margin-top: 30px; + padding-top: 20px; + border-top: 1px solid $COLOR_LIGHT_GRAY; +} + +#page_title { + @media screen and (max-width: 480px) { + font-size: $FONT_SIZE_XL; + margin-bottom: 0; + } +} + +.add-account-tnc { + margin-left: 10px; +} + +.margin-zero { + margin: 0; +} + +.margin-v-10 { + margin: 10px 0; +} + +.inline-block-button { + display: inline-block; +} + +.select-center-mobile { + text-align-last: center; + -moz-text-align-last: center; +} + +#account_opening_steps { + .select2-container { + width: 100% !important; + @media screen and (min-width: 768px) { + width: 360px !important; + } + } +} + +#content.real_account-content { + margin-top: 20px; +} + +#ui-datepicker-div { + z-index: 3 !important; +} + +.center-select-m { + text-align-last: center; +} + +.currency_list { + @media screen and (min-width: 768px) { + justify-content: center; + } +} + +.padding-h35 { + @media screen and (min-width: 768px) { + padding-left: 35px; + padding-right: 35px; + } + @media screen and (max-width: 480px) { + padding-left: 0; + padding-right: 0; + } +} + .platforms-content { h2 { line-height: 36px; diff --git a/src/templates/_common/components/forms.jsx b/src/templates/_common/components/forms.jsx index 91220212a5ad1..6732e95e0bee2 100644 --- a/src/templates/_common/components/forms.jsx +++ b/src/templates/_common/components/forms.jsx @@ -1,9 +1,9 @@ import React from 'react'; -export const Fieldset = ({ children, legend, id, className }) => ( +export const Fieldset = ({ children, legend, legend_id, id, className }) => (
{legend && - {legend} + {legend} } {children}
diff --git a/src/templates/_common/components/forms_common_rows.jsx b/src/templates/_common/components/forms_common_rows.jsx index fc082ffc0c4c0..6067901e73c8e 100644 --- a/src/templates/_common/components/forms_common_rows.jsx +++ b/src/templates/_common/components/forms_common_rows.jsx @@ -1,10 +1,10 @@ -import React from 'react'; +import React from 'react'; import { Fieldset, FormRow } from './forms.jsx'; export const Salutation = ({ className, row_class, row_id }) => ( ( ( label={it.L('Date of birth')} row_class={row_class} row_id={row_id} - attributes={{ size: '12', readOnly: true, className: `center-text-m ${className || ''}`, 'data-lpignore': true, required: true }} + attributes={{ size: '12', readOnly: true, className: `center-text-m ${className || ''}`, 'data-lpignore': true }} /> ); -export const Citizenship = ({ className, row_class }) => ( +export const PlaceOfBirth = ({ className, row_class, row_id }) => ( + +); + +export const Citizenship = ({ className, row_class, row_id }) => ( ); @@ -78,11 +90,10 @@ export const Residence = ({ className, row_class, row_id }) => ( ); -export const AccountOpeningReason = ({ row_id, row_class }) => ( +export const AccountOpeningReason = ({ row_id, row_class }) => ( ( ); -export const AddressLine1 = ({ hint }) => ( +export const TaxResidence = ({ className, row_class, row_id }) => ( + +); + +export const TaxIdentificationNumber = ({ className, hint, row_class, row_id }) => ( + +); + +export const TaxIdentificationConfirm = ({ row_class, row_id }) => ( +
+
+ + +
+
+); + +export const AddressLine1 = ({ hint, row_class, row_id }) => ( ); -export const AddressLine2 = ({ hint }) => ( +export const AddressLine2 = ({ hint, row_class, row_id }) => ( ); -export const AddressCity = ({ hint }) => ( +export const AddressCity = ({ hint, row_class, row_id }) => ( ); -export const AddressState = () => ( - +export const AddressState = (row_class, row_id) => ( + ); -export const AddressPostcode = ({ children, hint }) => ( +export const AddressPostcode = ({ children, hint, row_class, row_id, is_full_width }) => ( ( label={it.L('Postal/ZIP code')} attributes={{ maxLength: '20', 'data-lpignore': true }} hint={hint} - has_geovalidator - row_class='postcode-form-row' + row_class={`postcode-form-row ${row_class || ''}`} + has_geovalidator={!is_full_width} + row_id={row_id} > {children} @@ -151,7 +211,7 @@ export const Phone = ({ hint, row_class, row_id }) => ( type='text' id='phone' className='center-text-m' - label={it.L('Mobile number')} + label={it.L('Phone number')} attributes={{ 'data-lpignore': true }} hint={hint} row_class={row_class} @@ -181,7 +241,22 @@ export const SecretAnswer = () => ( /> ); -export const Tnc = () => ( +export const Tnc = ({ className, row_id }) => ( +
+
+ + +
+
+); + +export const TncWithSubmitButton = () => (
@@ -201,20 +276,20 @@ export const Tnc = () => (
); -export const Jurisdiction = () => ( -
+export const Jurisdiction = ({ row_id, className }) => ( +

{it.L('Your account will be opened with [_1], [_2] and will be subject to the laws of [_3].', '', '', '')}

); -export const RiskDisclaimer = () => ( -
+export const RiskDisclaimer = ({ className, row_id }) => ( +
-

{it.L('The financial trading services contained within this site are only suitable for customers who accept the possibility of losing all the money they invest and who understand and have experience of the risk involved in the acquisition of financial contracts. Transactions in financial contracts carry a high degree of risk. If purchased contracts expire worthless, you will suffer a total loss of your investment, which consists of the contract premium.')}

+

{it.L('The financial trading services offered on this site are only suitable for customers who accept the possibility of losing all the money they invest and who understand and have experience of the risk involved in the purchase of financial contracts. Transactions in financial contracts carry a high degree of risk. If the contracts you purchased expire as worthless, you will lose all your investment, which includes the contract premium.')}

-
+
); export const ClientMessage = () => ( diff --git a/src/templates/app/_includes/new_account_steps/address_detail_form.jsx b/src/templates/app/_includes/new_account_steps/address_detail_form.jsx new file mode 100644 index 0000000000000..cf038e6e7eab1 --- /dev/null +++ b/src/templates/app/_includes/new_account_steps/address_detail_form.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { + AddressLine1, + AddressLine2, + AddressCity, + AddressState, + AddressPostcode, +} from '../../../_common/components/forms_common_rows.jsx'; + +const AddressDetailForm = () => ( +
+
+

{it.L('Only use an address for which you have proof of residence')}

+
+
+ + + + + +
+
+ {it.L('Previous')} + +
+ +); + +export default AddressDetailForm; diff --git a/src/templates/app/_includes/new_account_steps/currency_form.jsx b/src/templates/app/_includes/new_account_steps/currency_form.jsx new file mode 100644 index 0000000000000..49c79f8c24002 --- /dev/null +++ b/src/templates/app/_includes/new_account_steps/currency_form.jsx @@ -0,0 +1,35 @@ +import React from 'react'; + +const Currencies = ({ text, id }) => ( + +
+
+
{text}
+
+
+
+
+
+ +); + +const CurrencyForm = () => ( +
+
+
+
+ +

{it.L('You will not be able to change currency once you have made a deposit.')}

+ +
+ +

+

+ +
+
+
+
+); + +export default CurrencyForm; diff --git a/src/templates/app/_includes/new_account_steps/financial_info_form.jsx b/src/templates/app/_includes/new_account_steps/financial_info_form.jsx new file mode 100644 index 0000000000000..d29a3046e2e64 --- /dev/null +++ b/src/templates/app/_includes/new_account_steps/financial_info_form.jsx @@ -0,0 +1,161 @@ +import React from 'react'; +import { Fieldset, FormRow } from '../../../_common/components/forms.jsx'; + +const Experience = () => ( + + + + + + +); + +const Frequency = () => ( + + + + + + + +); + +const SelectRow = ({ id, label, con }) => ( + {con()} +); + +const Values = () => ( + + + + + + + + +); + +const TradingExperienceForm = () => ( +
+ + + + + + + + + + + +
+); + +const FinancialInformationForm = () => ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+); + +const FinancialInfoForm = () => ( + +
+ + +
+ {it.L('Previous')} + +
+
+ +); + +export default FinancialInfoForm; diff --git a/src/templates/app/_includes/new_account_steps/personal_detail_form.jsx b/src/templates/app/_includes/new_account_steps/personal_detail_form.jsx new file mode 100644 index 0000000000000..e28157faacf12 --- /dev/null +++ b/src/templates/app/_includes/new_account_steps/personal_detail_form.jsx @@ -0,0 +1,52 @@ +import React from 'react'; +import { + Salutation, + FirstName, + LastName, + DateOfBirth, + Citizenship, + PlaceOfBirth, + AccountOpeningReason, + Phone, + TaxResidence, + TaxIdentificationNumber, + TaxIdentificationConfirm, +} from '../../../_common/components/forms_common_rows.jsx'; +import { Fieldset } from '../../../_common/components/forms.jsx'; + +const PersonalDetailForm = () => ( + +
+
+
+ + + +
+
+ + + + +
+
+ + +

+ {it.L('This Tax Identification Number (TIN) is invalid. You may continue, but to facilitate future payment processes, valid tax information will be required.')} +

+ +
+
+ +
+
+
+ {it.L('Previous')} + +
+
+
+); + +export default PersonalDetailForm; diff --git a/src/templates/app/_includes/new_account_steps/terms_of_use_form.jsx b/src/templates/app/_includes/new_account_steps/terms_of_use_form.jsx new file mode 100644 index 0000000000000..a1452971915c3 --- /dev/null +++ b/src/templates/app/_includes/new_account_steps/terms_of_use_form.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import PepDeclaration from '../pep_declaration.jsx'; +import { + Jurisdiction, + RiskDisclaimer, + Tnc, +} from '../../../_common/components/forms_common_rows.jsx'; +import ProfessionalClient from '../professional_client.jsx'; + +const TermsOfUseForm = () => ( +
+
+ +
+ +
+ + + +
+
+ {it.L('Previous')} + +
+
+); + +export default TermsOfUseForm; diff --git a/src/templates/app/_includes/pep_declaration.jsx b/src/templates/app/_includes/pep_declaration.jsx index 7cf39908913b1..63b69ea78f204 100644 --- a/src/templates/app/_includes/pep_declaration.jsx +++ b/src/templates/app/_includes/pep_declaration.jsx @@ -1,22 +1,36 @@ +/* eslint-disable */ import React from 'react'; import { Fieldset } from '../../_common/components/forms.jsx'; -const PepDeclaration = () => ( -
+const PepDeclaration = ({ is_new_flow, className, row_id }) => ( +
- -
+

{is_new_flow + ? it.L('A politically exposed person (PEP) is someone appointed with a prominent public position. Close associates and family members of a PEP are also considered to be PEPs.') + : it.L('A PEP is an individual who is or has been entrusted with a prominent public function. This status extends to a PEP\'s relatives and close associates.') + } + {!is_new_flow && {it.L('Learn more')}} +

+ {!is_new_flow &&

{it.L('A politically exposed person (PEP) is an individual who is or has been entrusted with a prominent public function. Family members and close associates of such individuals are also considered as PEPs. A PEP who has ceased to be entrusted with a prominent public function for at least 12 months no longer qualifies as a PEP.')}

-
+
}
- -
); diff --git a/src/templates/app/_includes/professional_client.jsx b/src/templates/app/_includes/professional_client.jsx index a064e8d894c1d..e7f8822f935f8 100644 --- a/src/templates/app/_includes/professional_client.jsx +++ b/src/templates/app/_includes/professional_client.jsx @@ -1,8 +1,8 @@ import React from 'react'; import { Fieldset } from '../../_common/components/forms.jsx'; -const ProfessionalClient = () => ( -
+const ProfessionalClient = ({ row_id, className }) => ( +

{it.L('By default, all [_1] clients are retail clients but anyone can request to be treated as a professional client.', it.website_name)}

diff --git a/src/templates/app/new_account/financial.jsx b/src/templates/app/new_account/financial.jsx index 666d31d9dc50c..66290a0e5ec13 100644 --- a/src/templates/app/new_account/financial.jsx +++ b/src/templates/app/new_account/financial.jsx @@ -23,7 +23,7 @@ import { SecretQuestion, SecretAnswer, ClientMessage, - Tnc, + TncWithSubmitButton, TaxInformationForm, } from '../../_common/components/forms_common_rows.jsx'; @@ -70,13 +70,13 @@ const Financial = () => (
- + - +
diff --git a/src/templates/app/new_account/real.jsx b/src/templates/app/new_account/real.jsx index bc105fe7dda2d..019223d87bb86 100644 --- a/src/templates/app/new_account/real.jsx +++ b/src/templates/app/new_account/real.jsx @@ -1,6 +1,7 @@ import React from 'react'; import PepDeclaration from '../_includes/pep_declaration.jsx'; import ProfessionalClient from '../_includes/professional_client.jsx'; +import Loading from '../../_common/components/loading.jsx'; import { Fieldset, FormRow } from '../../_common/components/forms.jsx'; import { Salutation, @@ -21,16 +22,19 @@ import { SecretQuestion, SecretAnswer, ClientMessage, - Tnc, + TncWithSubmitButton, } from '../../_common/components/forms_common_rows.jsx'; const Real = () => (

{it.L('Real Money Account Opening')}

+
+ +

{it.L('Please complete the Real Account form to verify your age as required by the [_1]UK Gambling[_2] Commission (UKGC).', '', '')}

- +
@@ -61,13 +65,13 @@ const Real = () => (
- +
- + diff --git a/src/templates/app/new_account/real_account.jsx b/src/templates/app/new_account/real_account.jsx new file mode 100644 index 0000000000000..569fe55bcbb3e --- /dev/null +++ b/src/templates/app/new_account/real_account.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import FinancialInfoForm from '../_includes/new_account_steps/financial_info_form.jsx'; +import CurrencyForm from '../_includes/new_account_steps/currency_form.jsx'; +import PersonalDetailForm from '../_includes/new_account_steps/personal_detail_form.jsx'; +import AddressDetailForm from '../_includes/new_account_steps/address_detail_form.jsx'; +import TermsOfUseForm from '../_includes/new_account_steps/terms_of_use_form.jsx'; +import Loading from '../../_common/components/loading.jsx'; +import { ClientMessage } from '../../_common/components/forms_common_rows.jsx'; + +const RealAccount = () => ( + +
+ +
+ +
+

+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+

{it.L('Appropriateness Test: WARNING:')}

+

{it.L('In providing our services to you, we are required to obtain information from you in order to assess whether a given product or service is appropriate for you (that is, whether you possess the experience and knowledge to understand the risks involved).')}

+

{it.L('On the basis of the information provided in relation to your knowledge and experience, we consider that the investments available via this website are not appropriate for you.')}

+

{it.L('By clicking Accept below and proceeding with the Account Opening you should note that you may be exposing yourself to risks (which may be significant, including the risk of loss of the entire sum invested) that you may not have the knowledge and experience to properly assess or mitigate.')}

+
+ {it.L('Decline')} + +
+
+ +
+ +); + +export default RealAccount; diff --git a/src/templates/app/user/set_currency.jsx b/src/templates/app/user/set_currency.jsx index ceaa1f7ac3377..00c6259bc91c1 100644 --- a/src/templates/app/user/set_currency.jsx +++ b/src/templates/app/user/set_currency.jsx @@ -1,5 +1,5 @@ -import React from 'react'; -import Loading from '../../_common/components/loading.jsx'; +import React from 'react'; +import Loading from '../../_common/components/loading.jsx'; import { SeparatorLine } from '../../_common/components/separator_line.jsx'; const Currencies = ({ text, id }) => ( @@ -9,8 +9,8 @@ const Currencies = ({ text, id }) => (
{text}
-
-
+
+
); @@ -31,16 +31,17 @@ const SetCurrency = () => (
-

{it.L('Congratulations!')}

-

{it.L('You have successfully created your real money [_1]account.', `${it.L('gaming')} `)}

+

{it.L('Success!')}

+

+

{it.L('Make a deposit now to start trading.')}

-