Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

likhith/feat: ✨ incorporated IDV in Personal details for Real account signup #2

Merged
1 change: 1 addition & 0 deletions packages/account/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'^Constants/(.*)$': '<rootDir>/src/Constants/$1',
'^Configs/(.*)$': '<rootDir>/src/Configs/$1',
'^Duplicated/(.*)$': '<rootDir>/src/Duplicated/$1',
'^Helpers/(.*)$': '<rootDir>/src/Helpers/$1',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Containers folder is also missing from the list

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add the entry

'^Services/(.*)$': '<rootDir>/src/Services/$1',
'^Stores/(.*)$': '<rootDir>/src/Stores/$1',
'^Sections/(.*)$': '<rootDir>/src/Sections/$1',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ describe('<PersonalDetails/>', () => {
getCurrentStep: jest.fn(() => 1),
onSave: jest.fn(),
onCancel: jest.fn(),
account_settings: {},
};

beforeAll(() => (ReactDOM.createPortal = jest.fn(component => component)));
Expand All @@ -253,6 +254,7 @@ describe('<PersonalDetails/>', () => {

expect(screen.getByText(fake_alert_messaget)).toBeInTheDocument();
});

it('should not show fake_alert_message when is_appstore is false ', () => {
renderwithRouter(
<PlatformContext.Provider value={{ is_appstore: false }}>
Expand Down Expand Up @@ -298,6 +300,7 @@ describe('<PersonalDetails/>', () => {
})
).toBeInTheDocument();
});

it('should show Name label when salutation is not passed', () => {
const newprops = { ...props, value: {} };
renderwithRouter(<PersonalDetails {...newprops} />);
Expand Down
883 changes: 882 additions & 1 deletion packages/account/src/Components/personal-details/personal-details.jsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { Autocomplete, Button, DesktopWrapper, Input, MobileWrapper, Text, Selec
import { Formik, Field } from 'formik';
import { localize, Localize } from '@deriv/translations';
import { formatInput, WS } from '@deriv/shared';
import { documentAdditionalError, getDocumentData, getRegex, preventEmptyClipboardPaste } from './utils';
import { documentAdditionalError, getRegex, preventEmptyClipboardPaste } from './utils';
import FormFooter from 'Components/form-footer';
import BackButtonIcon from 'Assets/ic-poi-back-btn.svg';
import DocumentSubmitLogo from 'Assets/ic-document-submit-icon.svg';
import { getDocumentData } from 'Helpers/utils';

const IdvDocumentSubmit = ({ handleBack, handleViewComplete, selected_country, is_from_external }) => {
const [document_list, setDocumentList] = React.useState([]);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// [TODO]: Remove duplicated functions from this file and use the ones in Helpers/utils.js

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to add a TODO? is this a draft PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this is not a draft PR. Currently some functions from this file are moved to Helper/utils, so they can be used across components rather than having them specific to idv-document-submit component. Once the new flow for CR is fully implemented this will be removed.


import { getUrlBase } from '@deriv/shared';

export const documentAdditionalError = (document_additional, document_additional_format) => {
Expand Down
5 changes: 4 additions & 1 deletion packages/account/src/Configs/personal-details-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const personal_details_config = ({ residence_list, account_settings, is_appstore
};

const personalDetailsConfig = (
{ upgrade_info, real_account_signup_target, residence_list, account_settings },
{ upgrade_info, real_account_signup_target, residence_list, account_settings, account_status, residence },
PersonalDetails,
is_appstore = false
) => {
Expand Down Expand Up @@ -212,6 +212,9 @@ const personalDetailsConfig = (
},
],
disabled_items,
account_status,
residence,
account_settings,
},
passthrough: ['residence_list', 'is_fully_authenticated', 'has_real_account'],
icon: 'IcDashboardPersonalDetails',
Expand Down
157 changes: 157 additions & 0 deletions packages/account/src/Helpers/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { getUrlBase } from '@deriv/shared';

const getImageLocation = image_name => getUrlBase(`/public/images/common/${image_name}`);

// Note: Ensure that the object keys matches BE API's keys. This is simply a mapping for FE templates
const idv_document_data = {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job on this file, please help to write tests cases for it as well 🙏🏼

ke: {
alien_card: {
new_display_name: '',
example_format: '123456',
sample_image: getImageLocation('ke_alien_card.png'),
},
national_id: {
new_display_name: '',
example_format: '12345678',
sample_image: getImageLocation('ke_national_identity_card.png'),
},
passport: {
new_display_name: '',
example_format: 'A12345678',
sample_image: getImageLocation('ke_passport.png'),
},
},
za: {
national_id: {
new_display_name: 'National ID',
example_format: '1234567890123',
sample_image: getImageLocation('za_national_identity_card.png'),
},
national_id_no_photo: {
new_display_name: 'National ID (No Photo)',
example_format: '1234567890123',
sample_image: '',
},
},
ng: {
bvn: {
new_display_name: 'Bank Verification Number',
example_format: '12345678901',
sample_image: '',
},
cac: {
new_display_name: 'Corporate Affairs Commission',
example_format: '12345678',
sample_image: '',
},
drivers_license: {
new_display_name: '',
example_format: 'ABC123456789',
sample_image: getImageLocation('ng_drivers_license.png'),
},
nin: {
new_display_name: 'National Identity Number',
example_format: '12345678901',
sample_image: '',
},
nin_slip: {
new_display_name: 'National Identity Number Slip',
example_format: '12345678901',
sample_image: getImageLocation('ng_nin_slip.png'),
},
tin: {
new_display_name: 'Taxpayer identification number',
example_format: '12345678-1234',
sample_image: '',
},
voter_id: {
new_display_name: 'Voter ID',
example_format: '1234567890123456789',
sample_image: getImageLocation('ng_voter_id.png'),
},
},
gh: {
drivers_license: {
new_display_name: '',
example_format: 'B1234567',
sample_image: '',
},
national_id: {
new_display_name: 'National ID',
example_format: 'GHA-123456789-1',
sample_image: '',
},
passport: {
new_display_name: 'Passport',
example_format: 'G1234567',
sample_image: '',
},
ssnit: {
new_display_name: 'Social Security and National Insurance Trust',
example_format: 'C123456789012',
sample_image: '',
},
voter_id: {
new_display_name: 'Voter ID',
example_format: '01234567890',
sample_image: '',
},
},
br: {
cpf: {
new_display_name: 'CPF',
example_format: '123.456.789-12',
sample_image: '',
},
},
ug: {
national_id: {
new_display_name: 'National ID',
example_format: 'CM12345678PE1D',
sample_image: getImageLocation('ug_national_identity_card.png'),
},
national_id_no_photo: {
new_display_name: 'National ID (No Photo)',
example_format: 'CM12345678PE1D',
sample_image: '',
},
},
zw: {
national_id: {
new_display_name: 'National ID',
example_format: '081234567F53',
sample_image: getImageLocation('zw_national_identity_card.png'),
},
},
};

export const shouldShowIdentityInformation = ({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also make this into a hook!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here hook is not needed as the function just accepts inputs and computes a boolean. It is not maintaining a state nor makes use of any other hooks

account_status,
account_settings,
residence,
residence_list,
real_account_signup_target,
}) => {
const citizen = account_settings.citizen || residence;
const country = residence_list.find(item => item.value === citizen);
const maltainvest = real_account_signup_target === 'maltainvest';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const maltainvest = real_account_signup_target === 'maltainvest';
const is_maltainvest = real_account_signup_target === 'maltainvest';

const should_skip_idv = account_status?.status?.some(status => status === 'skip_idv'); //status added by BE when idv should be skipped for the user
return !maltainvest && citizen && country?.identity?.services?.idv?.is_country_supported && !should_skip_idv;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return !maltainvest && citizen && country?.identity?.services?.idv?.is_country_supported && !should_skip_idv;
return !is_maltainvest && citizen && country?.identity?.services?.idv?.is_country_supported && !should_skip_idv;

};

export const getDocumentData = (country_code, document_type) => {
return (
(Object.keys(idv_document_data).includes(country_code) && idv_document_data[country_code][document_type]) || {
new_display_name: '',
example_format: '',
sample_image: '',
}
);
};

export const preventEmptyClipboardPaste = e => {
const clipboardData = (e.clipboardData || window.clipboardData).getData('text');
if (clipboardData.length === 0) {
e.preventDefault();
}
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import {
PersonalDetails,
ProofOfIdentityFormOnSignup,
TermsOfUse,
TradingAssessmentNewUser,
addressDetailsConfig,
currencySelectorConfig,
financialDetailsConfig,
personalDetailsConfig,
proofOfIdentityConfig,
termsOfUseConfig,
tradingAssessmentConfig,
} from '@deriv/account';
Expand All @@ -20,26 +18,11 @@ const isMaltaAccount = ({ real_account_signup_target }) => real_account_signup_t
const shouldShowPersonalAndAddressDetailsAndCurrency = ({ real_account_signup_target }) =>
real_account_signup_target !== 'samoa';

const shouldShowIdentityInformation = ({
account_status,
account_settings,
residence,
residence_list,
real_account_signup_target,
}) => {
const citizen = account_settings.citizen || residence;
const country = residence_list.find(item => item.value === citizen);
const maltainvest = real_account_signup_target === 'maltainvest';
const should_skip_idv = account_status?.status?.some(status => status === 'skip_idv'); //status added by BE when idv should be skipped for the user
return !maltainvest && citizen && country?.identity?.services?.idv?.is_country_supported && !should_skip_idv;
};

export const getItems = props => [
...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [currencySelectorConfig(props, CurrencySelector)] : []),
...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [personalDetailsConfig(props, PersonalDetails)] : []),
...(shouldShowPersonalAndAddressDetailsAndCurrency(props) ? [addressDetailsConfig(props, AddressDetails)] : []),
...(isMaltaAccount(props) ? [tradingAssessmentConfig(props, TradingAssessmentNewUser)] : []),
...(isMaltaAccount(props) ? [financialDetailsConfig(props, FinancialDetails)] : []),
...(shouldShowIdentityInformation(props) ? [proofOfIdentityConfig(props, ProofOfIdentityFormOnSignup)] : []),
termsOfUseConfig(props, TermsOfUse),
];
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ const AccountWizard = props => {
props.onFinishSuccess(response.new_account_real.currency.toLowerCase());
}
const { document_type, document_number, document_additional } = { ...form_values() };
if (document_type && document_number) {
if (document_type && document_type.id !== '#NA' && document_number) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#NA this hardcoded value is being used in multiple places, let's define a constant for it.

const country_code = props.account_settings.citizen || props.residence;
submitIDVData(document_type, document_number, document_additional, country_code);
}
Expand Down