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/trah-4188/incorporate POA enhancement for wallet #75

Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const POAMobileLayout = observer(
!!errors.address_state &&
!!errors.address_postcode
);
}, [values]);
}, [values, errors, step.id]);

return (
<div className='poa-mobile-layout'>
Expand Down
4 changes: 4 additions & 0 deletions packages/api-v2/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ type KycAuthStatus = {
* Current POA status.
*/
status?: 'none' | 'pending' | 'rejected' | 'verified' | 'expired';
/**
* Supported documents per document_type.
*/
supported_documents?: string[];
};
/**
* POI authentication status details.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
@include mobile-or-tablet-screen {
width: 100%;
height: 100%;
padding: 1.6rem;
padding: unset;
}
}
88 changes: 78 additions & 10 deletions packages/wallets/src/features/accounts/modules/Poa/Poa.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
import React, { useEffect, useState } from 'react';
import { Formik, FormikValues } from 'formik';
import React, { Fragment, useEffect, useMemo, useRef, useState } from 'react';
import { Formik, FormikProps, FormikValues } from 'formik';
import { useTranslations } from '@deriv-com/translations';
import { InlineMessage, Loader, Text } from '@deriv-com/ui';
import { InlineMessage, Loader, Text, useDevice } from '@deriv-com/ui';
import { ModalStepWrapper } from '../../../../components';
import { THooks } from '../../../../types';
import { Footer } from '../components';
import POAMobile from './components/POAMobile/POAMobile';
import { AddressSection, DocumentSubmission, PoaUploadErrorMessage } from './components';
import { usePoa } from './hooks';
import { TPoaValues } from './types';
import { getPoaValidationSchema } from './utils';
import './Poa.scss';

type TMobileFooterProps = {
handleClick: VoidFunction;
isDisabled: boolean;
nextText?: string;
};

const MobileFooter = ({ handleClick, isDisabled, nextText }: TMobileFooterProps) => (
<Footer disableNext={isDisabled} nextText={nextText} onClickNext={handleClick} />
);

type TPoaProps = {
onCompletion?: VoidFunction;
};

const Poa: React.FC<TPoaProps> = ({ onCompletion }) => {
const { localize } = useTranslations();
const { isDesktop } = useDevice();
const {
countryCode,
errorSettings,
initialStatus,
initialValues,
Expand All @@ -27,6 +41,28 @@ const Poa: React.FC<TPoaProps> = ({ onCompletion }) => {
} = usePoa();
const [errorDocumentUpload, setErrorDocumentUpload] = useState<THooks.DocumentUpload['error']>();
const [showLoader, setShowLoader] = useState(true);
const [step, setStep] = useState<{ id: number; text: string }>({ id: 1, text: localize('Enter your address') });

likhith-deriv marked this conversation as resolved.
Show resolved Hide resolved
const formikRef = useRef<FormikProps<TPoaValues>>(null);

const shouldAllowDocumentUpload = useMemo(() => {
if (!formikRef.current) return false;

const { errors, values } = formikRef.current;

if (step.id === 2) {
return false;
}
return (
!values.firstLine &&
!!errors.firstLine &&
!!errors.secondLine &&
!values.townCityLine &&
!!errors.townCityLine &&
!!errors.stateProvinceLine &&
!!errors.zipCodeLine
);
}, [formikRef, step.id]);

useEffect(() => {
if (isSubmissionSuccess && onCompletion) {
Expand All @@ -46,10 +82,13 @@ const Poa: React.FC<TPoaProps> = ({ onCompletion }) => {

if (showLoader) return <Loader />;

const handelClickNext = () => setStep({ id: 2, text: localize('Upload proof of address') });

likhith-deriv marked this conversation as resolved.
Show resolved Hide resolved
return (
<Formik
initialStatus={initialStatus}
initialValues={initialValues}
innerRef={formikRef}
onSubmit={upload}
validationSchema={getPoaValidationSchema(localize)}
>
Expand All @@ -63,19 +102,48 @@ const Poa: React.FC<TPoaProps> = ({ onCompletion }) => {
return <PoaUploadErrorMessage errorCode={errorDocumentUpload.code} onRetry={onErrorRetry} />;
}

let buttonConfig: TMobileFooterProps;

if (step.id === 1) {
buttonConfig = {
handleClick: handelClickNext,
isDisabled: shouldAllowDocumentUpload,
};
} else {
buttonConfig = {
handleClick: handleSubmit,
isDisabled: !isValid,
nextText: localize('Submit'),
};
}

return (
<ModalStepWrapper
renderFooter={() => <Footer disableNext={!isValid} onClickNext={handleSubmit} />}
renderFooter={() =>
isDesktop ? (
<Footer disableNext={!isValid} onClickNext={handleSubmit} />
) : (
<MobileFooter {...buttonConfig} />
)
likhith-deriv marked this conversation as resolved.
Show resolved Hide resolved
}
title={localize('Add a real MT5 account')}
>
<div className='wallets-poa'>
{errorSettings?.message && (
<InlineMessage variant='error'>
<Text>{localize(errorSettings.message)}</Text>
</InlineMessage>
{isDesktop ? (
<Fragment>
{errorSettings?.message && (
<InlineMessage variant='error'>
<Text>{localize(errorSettings.message)}</Text>
</InlineMessage>
)}
<AddressSection hasError={Boolean(errorSettings?.message)} />
<DocumentSubmission countryCode={countryCode as string} />
</Fragment>
) : (
<Fragment>
<POAMobile countryCode={countryCode as string} step={step} />
</Fragment>
)}
<AddressSection />
<DocumentSubmission />
</div>
</ModalStepWrapper>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
align-items: flex-start;
gap: 0.8rem;
margin-bottom: 1rem;
line-height: 14px;

&-message {
width: 80rem;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,35 @@
import React from 'react';
import { useFormikContext } from 'formik';
import { Localize, useTranslations } from '@deriv-com/translations';
import { InlineMessage, Text } from '@deriv-com/ui';
import { InlineMessage, Text, useDevice } from '@deriv-com/ui';
import { FormDropdown, FormField } from '../../../../../../components';
import { TAddressDetails } from '../../types';
import { TAddressDetails, TAddressSectionProps } from '../../types';
import './AddressSection.scss';

const AddressSection: React.FC = () => {
const AddressSection: React.FC<TAddressSectionProps> = ({ hasError }) => {
const { localize } = useTranslations();
const { status } = useFormikContext<TAddressDetails>();
const { isDesktop } = useDevice();

return (
<div className='wallets-address-section'>
<div className='wallets-address-section__title'>
<Text weight='bold'>
<Localize i18n_default_text='Address' />
</Text>
<div className='wallets-address-section__title__divider' />
</div>
<div className='wallets-address-section__inline'>
<InlineMessage variant='warning'>
<div className='wallets-address-section__inline-message'>
<Localize i18n_default_text='For faster verification, input the same address here as in your proof of address document (see section below)' />
</div>
</InlineMessage>
</div>
{isDesktop && (
<div className='wallets-address-section__title'>
<Text weight='bold'>
<Localize i18n_default_text='Address' />
</Text>
<div className='wallets-address-section__title__divider' />
</div>
)}
{!hasError && (
<div className='wallets-address-section__inline'>
<InlineMessage variant='warning'>
<div className='wallets-address-section__inline-message'>
<Localize i18n_default_text='Use the same address that appears on your proof of address (utility bill, bank statement, etc.).' />
</div>
</InlineMessage>
</div>
)}
<div className='wallets-address-section__input'>
<FormField label={localize('First line of address*')} name='firstLine' />
<FormField label={localize('Second line of address (optional)')} name='secondLine' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,11 @@
width: 100%;
}
}

&__type-selection {
display: flex;
flex-direction: column;
gap: 1.6rem;
align-self: stretch;
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,62 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { useFormikContext } from 'formik';
import { useIsEuRegion } from '@deriv/api-v2';
import { useIsEuRegion, useKycAuthStatus } from '@deriv/api-v2';
import { LabelPairedArrowUpFromBracketXlFillIcon } from '@deriv/quill-icons';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Text, useDevice } from '@deriv-com/ui';
import { Dropzone } from '../../../../../../components';
import { TDocumentSubmission } from '../../types';
import { getExampleImagesConfig } from '../../utils';
import { Dropzone, FormDropdown } from '../../../../../../components';
import { TDocumentSubmission, TDocumentSubmissionProps, TListItem } from '../../types';
import { getExampleImagesConfig, getSupportedProofOfAddressDocuments } from '../../utils';
import { CommonMistakesExamples } from '../CommonMistakesExamples';
import './DocumentSubmission.scss';

const DocumentSubmission: React.FC = () => {
const DocumentSubmission: React.FC<TDocumentSubmissionProps> = ({ countryCode }) => {
const { localize } = useTranslations();
const { isDesktop } = useDevice();
const { data: isEuRegion } = useIsEuRegion();
const { isLoading, kyc_auth_status: kycAuthStatus } = useKycAuthStatus({ country: countryCode });
const [documentList, setDocumentList] = useState<Required<TListItem>[]>([]);
const { setFieldValue, values } = useFormikContext<TDocumentSubmission>();

useEffect(() => {
if (!isLoading && kycAuthStatus) {
const { address } = kycAuthStatus;
const { supported_documents: supportedDocuments } = address;
const docList = getSupportedProofOfAddressDocuments().filter(doc =>
supportedDocuments?.includes(doc.value)
);
setDocumentList(docList);
}
}, [isLoading, kycAuthStatus]);

const listItems = [
localize('Utility bill: electricity, water, gas, or landline phone bill.'),
localize(
'Financial, legal, or government document: recent bank statement, affidavit, or government-issued letter.'
),
localize('Home rental agreement: valid and current agreement.'),
{
id: 'utility_bill',
value: (
<Localize
components={[<strong key={0} />]}
i18n_default_text='<0>Utility bill:</0> Electricity, water, gas, or landline phone bill.'
/>
),
},
{
id: 'financial_legal_government_document',
value: (
<Localize
components={[<strong key={0} />]}
i18n_default_text='<0>Financial, legal, or government document:</0> Recent bank statement, affidavit, or government-issued letter.'
/>
),
},
{
id: 'tenancy_agreement',
value: (
<Localize
components={[<strong key={0} />]}
i18n_default_text='<0>Tenancy agreement:</0> Valid and current agreement.'
/>
),
},
];

useEffect(() => {
Expand All @@ -34,23 +69,23 @@ const DocumentSubmission: React.FC = () => {
<div className='wallets-poa__document'>
<div className='wallets-poa__document__title'>
<Text weight='bold'>
<Localize i18n_default_text='Document submission' />
<Localize i18n_default_text='Submit your document' />
</Text>
<div className='wallets-poa__document__title__divider' />
</div>
<div className='wallets-poa__document__container'>
<div className='wallets-poa__document__container__disclaimer'>
<Text size='sm' weight='bold'>
{localize(
'We accept only these types of documents as proof of address. The document must be recent (issued within last {{timePeriod}} months) and include your name and address:',
'We accept only the following documents as proof of address. The document must be issued within last {{timePeriod}} months and include your name and address:',
{ timePeriod: isEuRegion ? '6' : '12' }
)}
</Text>

<ul className='wallets-poa__document__container__disclaimer__list'>
{listItems.map(item => (
<li key={`list-item-${item}`}>
<Text size='sm'>{item}</Text>
<li key={`list-item-${item.id}`}>
<Text size='sm'>{item.value}</Text>
</li>
))}
</ul>
Expand All @@ -70,6 +105,20 @@ const DocumentSubmission: React.FC = () => {
))}
</div>
</div>

<div className='wallets-poa__document__type-selection'>
<Text size='sm' weight='bold'>
<Localize i18n_default_text='Select the type of document:' />
</Text>
<FormDropdown
isFullWidth
label={localize('Type of document')}
list={documentList}
listHeight='sm'
name='documentType'
/>
</div>

<div className='wallets-poa__document__container__upload'>
<Text size='sm' weight='bold'>
<Localize i18n_default_text='Upload file' />
Expand Down
Loading
Loading