-
+
{localize('ID verification failed')}
@@ -30,4 +30,4 @@ const IdvNoSubmissions = ({ handleRequireSubmission }: TIdvNoSubmission) => {
);
};
-export default IdvNoSubmissions;
+export default IdvLimited;
diff --git a/packages/account/src/Components/poi/idv-status/idv-limited/index.js b/packages/account/src/Components/poi/idv-status/idv-limited/index.js
deleted file mode 100644
index 1223bdf639cb..000000000000
--- a/packages/account/src/Components/poi/idv-status/idv-limited/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import IdvNoSubmissions from './idv-limited';
-
-export default IdvNoSubmissions;
diff --git a/packages/account/src/Components/poi/idv-status/idv-limited/index.ts b/packages/account/src/Components/poi/idv-status/idv-limited/index.ts
new file mode 100644
index 000000000000..649a4a5158a4
--- /dev/null
+++ b/packages/account/src/Components/poi/idv-status/idv-limited/index.ts
@@ -0,0 +1,3 @@
+import IdvLimited from './idv-limited';
+
+export default IdvLimited;
diff --git a/packages/account/src/Components/poi/idv-status/idv-rejected/__tests__/idv-rejected.spec.tsx b/packages/account/src/Components/poi/idv-status/idv-rejected/__tests__/idv-rejected.spec.tsx
deleted file mode 100644
index 52c58bef0094..000000000000
--- a/packages/account/src/Components/poi/idv-status/idv-rejected/__tests__/idv-rejected.spec.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import { fireEvent, render, screen } from '@testing-library/react';
-import IdvRejected from '../idv-rejected';
-
-jest.mock('Assets/ic-idv-document-rejected.svg', () => jest.fn(() => 'IdvDocumentRejected'));
-
-describe('
', () => {
- const mockHandleRequireSubmission = jest.fn();
-
- it('should render IdvRejected component and trigger click', () => {
- render(
);
-
- expect(screen.getByText('IdvDocumentRejected')).toBeInTheDocument();
- expect(screen.getByText(/ID verification failed/i)).toBeInTheDocument();
- expect(screen.getByText(/we were unable to verify your ID with the details you provided/i)).toBeInTheDocument();
-
- const btn = screen.getByRole('button');
- expect(btn).toHaveTextContent(/try again/i);
- fireEvent.click(btn);
- expect(mockHandleRequireSubmission).toHaveBeenCalledTimes(1);
- });
-});
diff --git a/packages/account/src/Components/poi/idv-status/idv-rejected/idv-rejected.tsx b/packages/account/src/Components/poi/idv-status/idv-rejected/idv-rejected.tsx
deleted file mode 100644
index 81a4bbc6f83d..000000000000
--- a/packages/account/src/Components/poi/idv-status/idv-rejected/idv-rejected.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import { Button, Text } from '@deriv/components';
-import { localize } from '@deriv/translations';
-import IdvDocumentRejected from 'Assets/ic-idv-document-rejected.svg';
-
-type TIdvRejected = {
- handleRequireSubmission: () => void;
-};
-
-const IdvRejected = ({ handleRequireSubmission }: TIdvRejected) => {
- return (
-
-
-
- {localize('ID verification failed')}
-
-
- {localize('We were unable to verify your ID with the details you provided.')}
-
-
-
- );
-};
-
-export default IdvRejected;
diff --git a/packages/account/src/Components/poi/idv-status/idv-rejected/index.js b/packages/account/src/Components/poi/idv-status/idv-rejected/index.js
deleted file mode 100644
index f35e095598df..000000000000
--- a/packages/account/src/Components/poi/idv-status/idv-rejected/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import IdvRejected from './idv-rejected';
-
-export default IdvRejected;
diff --git a/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx b/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
index 86212d2144de..aa923548204f 100644
--- a/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
+++ b/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
@@ -1,55 +1,154 @@
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { render, screen } from '@testing-library/react';
+import { idv_error_statuses } from '@deriv/shared';
import IdvSubmitComplete from '../idv-submit-complete';
+import { StoreProvider, mockStore } from '@deriv/stores';
jest.mock('../../../../../Assets/ic-idv-document-pending.svg', () => jest.fn(() => 'IdvDocumentPending'));
+type TIdvSubmitCompleteProps = React.ComponentProps
;
+
describe('', () => {
- const mock_props = {
+ const mock_props: TIdvSubmitCompleteProps = {
needs_poa: false,
is_from_external: false,
+ redirect_button: '',
};
- const commonRenderCheck = () => {
+ const store = mockStore({
+ client: {
+ account_status: {
+ authentication: {
+ attempts: {
+ count: 0,
+ history: [],
+ },
+ },
+ },
+ },
+ });
+
+ const renderComponent = ({ props = mock_props, store_config = store }) =>
+ render(
+
+
+
+
+
+ );
+
+ it('should render IdvSubmitComplete component external, no needs_poa, without mismatch_status', () => {
+ const new_props: TIdvSubmitCompleteProps = {
+ ...mock_props,
+ redirect_button: 'Mock Redirect Button',
+ };
+ renderComponent({ props: new_props });
+
expect(screen.getByText('IdvDocumentPending')).toBeInTheDocument();
+ expect(screen.getByText('Mock Redirect Button')).toBeInTheDocument();
expect(screen.getByText('Your documents were submitted successfully')).toBeInTheDocument();
expect(
screen.getByText('We’ll review your documents and notify you of its status within 5 minutes.')
).toBeInTheDocument();
- };
- it('should render IdvSubmitComplete component not external, no needs_poa', () => {
- render();
-
- commonRenderCheck();
+ expect(screen.queryByText('Your profile is updated')).not.toBeInTheDocument();
+ expect(screen.queryByText('Your document has been submitted')).not.toBeInTheDocument();
+ expect(
+ screen.queryByText(
+ "We'll review your proof of identity again and will give you an update as soon as possible."
+ )
+ ).not.toBeInTheDocument();
expect(screen.queryByText("Next, we'll need your proof of address.")).not.toBeInTheDocument();
- expect(screen.queryByText('Submit proof of address')).not.toBeInTheDocument();
});
- it('should render IdvSubmitComplete component not external, needs_poa', () => {
- mock_props.needs_poa = true;
- render(
-
-
-
- );
+ it('should render IdvSubmitComplete component needs_poa not external, without mismatch_status and redirect_button', () => {
+ const new_props: TIdvSubmitCompleteProps = {
+ ...mock_props,
+ needs_poa: true,
+ };
- commonRenderCheck();
- expect(screen.getByText("Next, we'll need your proof of address.")).toBeInTheDocument();
+ renderComponent({ props: new_props });
+
+ expect(screen.getByText('IdvDocumentPending')).toBeInTheDocument();
+ expect(screen.getByText('Your documents were submitted successfully')).toBeInTheDocument();
expect(screen.getByText('Submit proof of address')).toBeInTheDocument();
+ expect(screen.getByText("Next, we'll need your proof of address.")).toBeInTheDocument();
+ expect(screen.queryByText('Your profile is updated')).not.toBeInTheDocument();
+ expect(screen.queryByText('Your document has been submitted')).not.toBeInTheDocument();
+ expect(
+ screen.queryByText(
+ "We'll review your proof of identity again and will give you an update as soon as possible."
+ )
+ ).not.toBeInTheDocument();
});
- it('should render IdvSubmitComplete component external, needs_poa', () => {
- mock_props.needs_poa = true;
- mock_props.is_from_external = true;
- render(
-
-
-
- );
+ it('should render IdvSubmitComplete component with mismatch_status ', () => {
+ const new_store = mockStore({
+ client: {
+ account_status: {
+ authentication: {
+ attempts: {
+ count: 2,
+ history: [{ status: 'pending' }],
+ },
+ },
+ },
+ },
+ });
- commonRenderCheck();
- expect(screen.getByText("Next, we'll need your proof of address.")).toBeInTheDocument();
- expect(screen.queryByText('Submit proof of address')).not.toBeInTheDocument();
+ const new_props: TIdvSubmitCompleteProps = {
+ ...mock_props,
+ mismatch_status: idv_error_statuses.poi_name_dob_mismatch,
+ };
+ renderComponent({ props: new_props, store_config: new_store });
+
+ expect(screen.getByText('IdvDocumentPending')).toBeInTheDocument();
+ expect(screen.getByText('Your profile is updated')).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ "We'll review your proof of identity again and will give you an update as soon as possible."
+ )
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByText('We’ll review your documents and notify you of its status within 5 minutes.')
+ ).not.toBeInTheDocument();
+ expect(screen.queryByText('Your documents were submitted successfully')).not.toBeInTheDocument();
+ expect(screen.queryByText('Your document has been submitted')).not.toBeInTheDocument();
+ expect(screen.queryByText("Next, we'll need your proof of address.")).not.toBeInTheDocument();
+ });
+
+ it('should render IdvSubmitComplete component with mismatch_status', () => {
+ const new_store = mockStore({
+ client: {
+ account_status: {
+ authentication: {
+ attempts: {
+ count: 2,
+ history: [{ status: 'pending' }],
+ },
+ },
+ },
+ },
+ });
+
+ const new_props: TIdvSubmitCompleteProps = {
+ ...mock_props,
+ mismatch_status: idv_error_statuses.poi_expired,
+ };
+ renderComponent({ props: new_props, store_config: new_store });
+
+ expect(screen.getByText('IdvDocumentPending')).toBeInTheDocument();
+ expect(screen.getByText('Your document has been submitted')).toBeInTheDocument();
+ expect(
+ screen.getByText(
+ "We'll review your proof of identity again and will give you an update as soon as possible."
+ )
+ ).toBeInTheDocument();
+ expect(
+ screen.queryByText('We’ll review your documents and notify you of its status within 5 minutes.')
+ ).not.toBeInTheDocument();
+ expect(screen.queryByText('Your profile is updated')).not.toBeInTheDocument();
+ expect(screen.queryByText('Your documents were submitted successfully')).not.toBeInTheDocument();
+ expect(screen.queryByText("Next, we'll need your proof of address.")).not.toBeInTheDocument();
});
});
diff --git a/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx b/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
index bd0f526e110d..7b66f7720ee1 100644
--- a/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
+++ b/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
@@ -1,39 +1,81 @@
-import IdvDocumentPending from '../../../../Assets/ic-idv-document-pending.svg';
-import PoaButton from '../../../poa/poa-button/poa-button';
import React from 'react';
import { Text } from '@deriv/components';
-import { localize } from '@deriv/translations';
+import { idv_error_statuses, TIDVErrorStatus } from '@deriv/shared';
+import { observer, useStore } from '@deriv/stores';
+import { Localize } from '@deriv/translations';
+import IdvDocumentPending from 'Assets/ic-idv-document-pending.svg';
+import PoaButton from 'Components/poa/poa-button';
type TIdvSubmitComplete = {
- needs_poa: boolean;
is_from_external: boolean;
- redirect_button: React.ReactElement;
+ mismatch_status: TIDVErrorStatus;
+ needs_poa: boolean;
+ redirect_button: React.ReactNode;
};
-const IdvSubmitComplete = ({ needs_poa, is_from_external, redirect_button }: TIdvSubmitComplete) => {
- const poa_button = !is_from_external && ;
-
- return (
-
-
-
- {localize('Your documents were submitted successfully')}
-
-
- {localize('We’ll review your documents and notify you of its status within 5 minutes.')}
-
- {needs_poa ? (
-
-
- {localize("Next, we'll need your proof of address.")}
-
- {poa_button}
-
- ) : (
-
{redirect_button}
- )}
-
- );
-};
+const IdvSubmitComplete = observer(
+ ({ is_from_external, mismatch_status, needs_poa, redirect_button }: Partial) => {
+ const { client } = useStore();
+ const { account_status } = client;
+
+ const attempt_count = account_status?.authentication?.attempts?.count ?? 0;
+ const attempt_history = account_status?.authentication?.attempts?.history ?? [];
+
+ const is_already_attempted = attempt_count > 1 || attempt_history.length > 1;
+
+ const is_mismatch_error =
+ mismatch_status === idv_error_statuses.poi_name_dob_mismatch ||
+ mismatch_status === idv_error_statuses.poi_dob_mismatch ||
+ mismatch_status === idv_error_statuses.poi_name_mismatch;
+
+ const is_expired_or_failed_error =
+ mismatch_status === idv_error_statuses.poi_expired || mismatch_status === idv_error_statuses.poi_failed;
+
+ const getHeaderText = () => {
+ if (is_already_attempted) {
+ if (is_mismatch_error) return ;
+ if (is_expired_or_failed_error)
+ return ;
+ }
+ return ;
+ };
+
+ const getDescriptionText = () => {
+ if (is_already_attempted && (is_mismatch_error || is_expired_or_failed_error))
+ return (
+
+ );
+ return (
+
+ );
+ };
+
+ const poa_button = !is_from_external && (
+ } />
+ );
+
+ return (
+
+
+
+ {getHeaderText()}
+
+
+ {getDescriptionText()}
+
+ {needs_poa ? (
+
+
+
+
+ {poa_button}
+
+ ) : (
+
{redirect_button}
+ )}
+
+ );
+ }
+);
-export default IdvSubmitComplete;
+export default React.memo(IdvSubmitComplete);
diff --git a/packages/account/src/Components/poi/idv-status/idv-verified/idv-verified.tsx b/packages/account/src/Components/poi/idv-status/idv-verified/idv-verified.tsx
index 387c0ca346d7..59254b8b0bda 100644
--- a/packages/account/src/Components/poi/idv-status/idv-verified/idv-verified.tsx
+++ b/packages/account/src/Components/poi/idv-status/idv-verified/idv-verified.tsx
@@ -1,9 +1,10 @@
-import IdvDocumentVerified from '../../../../Assets/ic-idv-verified.svg';
-import PoaButton from '../../../poa/poa-button/poa-button';
import React from 'react';
import { Text } from '@deriv/components';
import { isMobile } from '@deriv/shared';
-import { localize } from '@deriv/translations';
+import { Localize } from '@deriv/translations';
+import { ContinueTradingButton } from 'Components/poa/continue-trading-button/continue-trading-button';
+import IdvDocumentVerified from '../../../../Assets/ic-idv-verified.svg';
+import PoaButton from '../../../poa/poa-button/poa-button';
type TIdvVerified = {
needs_poa: boolean;
@@ -12,9 +13,11 @@ type TIdvVerified = {
};
const IdvVerified = ({ needs_poa, is_from_external, redirect_button }: Partial) => {
- const header_Text = needs_poa
- ? localize('Your ID is verified. You will also need to submit proof of your address.')
- : localize('ID verification passed');
+ const header_Text = needs_poa ? (
+
+ ) : (
+
+ );
return (
@@ -26,13 +29,15 @@ const IdvVerified = ({ needs_poa, is_from_external, redirect_button }: Partial
{!isMobile() && (
- {localize("Next, we'll need your proof of address.")}
+
)}
- {!is_from_external && }
+ {!is_from_external && (
+ } />
+ )}
) : (
- redirect_button
+ redirect_button ||
)}
);
diff --git a/packages/account/src/Components/poi/poi-confirm-with-example-form-container/poi-confirm-with-example-form-container.tsx b/packages/account/src/Components/poi/poi-confirm-with-example-form-container/poi-confirm-with-example-form-container.tsx
index 7a586c04c24c..e904807694e4 100644
--- a/packages/account/src/Components/poi/poi-confirm-with-example-form-container/poi-confirm-with-example-form-container.tsx
+++ b/packages/account/src/Components/poi/poi-confirm-with-example-form-container/poi-confirm-with-example-form-container.tsx
@@ -12,11 +12,14 @@ import {
toMoment,
WS,
} from '@deriv/shared';
+import PoiNameDobExample from '../../../Assets/ic-poi-name-dob-example.svg';
import FormBody from '../../form-body';
import LoadErrorMessage from '../../load-error-message';
import PersonalDetailsForm from '../../forms/personal-details-form.jsx';
+import { GENERIC_ERROR_MESSAGE, DUPLICATE_ACCOUNT_ERROR_MESSAGE } from '../../../Configs/poi-error-config';
+import { API_ERROR_CODES } from '../../../Constants/api-error-codes';
import { makeSettingsRequest, validate, validateName } from '../../../Helpers/utils';
-import { TInputFieldValues } from 'Types';
+import { TInputFieldValues } from '../../../Types';
type TRestState = {
api_error: string;
@@ -46,6 +49,8 @@ const PoiConfirmWithExampleFormContainer = ({
api_error: '',
});
+ const side_note_image = ;
+
React.useEffect(() => {
const initializeFormValues = () => {
WS.wait('get_settings').then(() => {
@@ -81,12 +86,16 @@ const PoiConfirmWithExampleFormContainer = ({
);
const data = await WS.setSettings(request);
- if (data.error) {
- setStatus({ error_msg: data.error.message });
+ if (data?.error) {
+ const response_error =
+ data.error?.code === API_ERROR_CODES.DUPLICATE_ACCOUNT
+ ? DUPLICATE_ACCOUNT_ERROR_MESSAGE
+ : GENERIC_ERROR_MESSAGE;
+ setStatus({ error_msg: response_error });
setSubmitting(false);
} else {
const response = await WS.authorized.storage.getSettings();
- if (response.error) {
+ if (response?.error) {
setRestState({ ...rest_state, api_error: response.error.message });
return;
}
@@ -140,7 +149,17 @@ const PoiConfirmWithExampleFormContainer = ({
{({ errors, handleSubmit, isSubmitting, status }) => (
)}
diff --git a/packages/account/src/Components/poi/poi-country-selector/__tests__/poi-country-selector.spec.tsx b/packages/account/src/Components/poi/poi-country-selector/__tests__/poi-country-selector.spec.tsx
index daef89e70eb5..79e8de7583b4 100644
--- a/packages/account/src/Components/poi/poi-country-selector/__tests__/poi-country-selector.spec.tsx
+++ b/packages/account/src/Components/poi/poi-country-selector/__tests__/poi-country-selector.spec.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { isDesktop, isMobile } from '@deriv/shared';
-import PoiCountrySelector from '../poi-country-selector';
+import CountrySelector from '../poi-country-selector';
jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
@@ -9,7 +9,7 @@ jest.mock('@deriv/shared', () => ({
isMobile: jest.fn(() => false),
}));
-describe('