Skip to content

Commit

Permalink
chore: poo ts init (#53)
Browse files Browse the repository at this point in the history
* chore: poo ts init

* chore: remove query

* chore: some types fix

* chore: revert observer for poo form

---------

Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”>
  • Loading branch information
yauheni-deriv and “yauheni-kryzhyk-deriv” committed Oct 19, 2023
1 parent 0c6cf2b commit 0f0884e
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 99 deletions.
13 changes: 9 additions & 4 deletions packages/account/src/Containers/proof-of-ownership/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ExpandedCard from './expanded-card';
import { TPaymentMethodInfo } from '../../Types';

type TCardProps = {
details: TPaymentMethodInfo;
details?: TPaymentMethodInfo;
index: number;
updateErrors: (index: number, item_index: number, sub_index: number) => void;
};
Expand Down Expand Up @@ -44,13 +44,18 @@ const Card = ({ details, index, updateErrors }: TCardProps) => {
return (
<div
className={classNames('proof-of-ownership__card', { 'proof-of-ownership__card-open': is_open })}
data-testid={details.payment_method}
data-testid={details?.payment_method}
role='card-item'
>
<div className='proof-of-ownership__card-item' onClick={onClickHandler}>
<Icon icon={details?.icon} className='proof-of-ownership__card-item-logo' width={68} height={58} />
<Icon
icon={details?.icon || ''}
className='proof-of-ownership__card-item-logo'
width={68}
height={58}
/>
<Text className='proof-of-ownership__card-item-text' as='p' color='general' size='s' weight='bold'>
{details.payment_method}
{details?.payment_method}
</Text>
<Button
id='proof-of-ownership'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { useFormikContext } from 'formik';
import { Input, Text } from '@deriv/components';
import { IDENTIFIER_TYPES, VALIDATIONS } from '../../Constants/poo-identifier';
import FileUploader from '../../Sections/Verification/ProofOfOwnership/file-uploader';
import { TPaymentMethodInfo } from '../../Types';
import { TPaymentMethodInfo, TPaymentMethodUploadData } from '../../Types';
import ExampleLink from './example-link';

type TExpandedCardProps = {
card_details: TPaymentMethodInfo;
card_details?: TPaymentMethodInfo;
index: number;
updateErrors: (index: number, item_index: number, sub_index: number) => void;
};
Expand All @@ -21,7 +21,7 @@ type TExpandedCardProps = {
* @returns React Component
*/
const ExpandedCard = ({ card_details, index, updateErrors }: TExpandedCardProps) => {
const { values, setFieldValue, errors } = useFormikContext();
const { values, setFieldValue, errors } = useFormikContext<{ data: Partial<TPaymentMethodUploadData>[] }>();

const handleUploadedFile = async (name: string, file: Blob) => {
await setFieldValue(name, file);
Expand Down Expand Up @@ -54,8 +54,8 @@ const ExpandedCard = ({ card_details, index, updateErrors }: TExpandedCardProps)
documents_required,
id: item_id,
payment_method_identifier,
is_generic_pm: card_details.is_generic_pm,
identifier_type: card_details.identifier_type,
is_generic_pm: card_details?.is_generic_pm,
identifier_type: card_details?.identifier_type,
});
};

Expand Down Expand Up @@ -86,7 +86,7 @@ const ExpandedCard = ({ card_details, index, updateErrors }: TExpandedCardProps)
as='p'
color='general'
size='xs'
key={instruction?.key ?? instruction}
key={typeof instruction !== 'string' ? instruction.key : instruction}
>
{instruction}{' '}
{card_details?.identifier_type === IDENTIFIER_TYPES.CARD_NUMBER && <ExampleLink />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ProofOfOwnership } from '../proof-of-ownership.jsx';
import test_data from './test-data';
import { GetAccountStatus } from '@deriv/api-types';
import { StoreProvider, mockStore } from '@deriv/stores';
import { ProofOfOwnership } from '../proof-of-ownership';
import test_data from './test-data';

type TRequests = DeepRequired<GetAccountStatus>['authentication']['ownership']['requests'];
type TStatus = DeepRequired<GetAccountStatus>['authentication']['ownership']['status'];

describe('proof-of-ownership.jsx', () => {
let ownership_temp;
let ownership_temp: typeof test_data;

beforeAll(() => {
ownership_temp = test_data;
});
Expand All @@ -16,7 +21,7 @@ describe('proof-of-ownership.jsx', () => {
</StoreProvider>
);
};
let store = mockStore();
let store = mockStore({});
it('should render no poo required status page', () => {
store = mockStore({
client: {
Expand Down Expand Up @@ -94,7 +99,10 @@ describe('proof-of-ownership.jsx', () => {
client: {
account_status: {
authentication: {
ownership: { requests: ownership_temp.requests, status: ownership_temp.status },
ownership: {
requests: ownership_temp.requests as TRequests,
status: ownership_temp.status as TStatus,
},
needs_verification: ['ownership'],
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export default {
requests: [
{
id: '1',
creation_time: '123',
id: 1,
payment_method: 'beyonic',
documents_required: 1,
},
{
id: '2',
creation_time: '234',
id: 2,
payment_method: 'boleto (d24 voucher)',
documents_required: 1,
},
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import POO from './proof-of-ownership';

export default POO;
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import { Formik } from 'formik';
import classNames from 'classnames';
import { Formik, FormikErrors, FormikProps } from 'formik';
import DocumentUploader from '@binary-com/binary-document-uploader';
import { Button, useStateCallback } from '@deriv/components';
import { Button } from '@deriv/components';
import { readFiles, WS, DOCUMENT_TYPE } from '@deriv/shared';
import { localize } from '@deriv/translations';
import FormFooter from '../../../Components/form-footer';
import FormBody from '../../../Components/form-body';
import FormSubHeader from '../../../Components/form-sub-header';
import FormBodySection from '../../../Components/form-body-section';
import { isMobile, readFiles, WS, DOCUMENT_TYPE } from '@deriv/shared';
import Card from '../../../Containers/proof-of-ownership/card';
import { IDENTIFIER_TYPES, VALIDATIONS } from '../../../Constants/poo-identifier';
import { TPaymentMethod, TPaymentMethodInfo, TPaymentMethodUploadData } from 'Types';
import { TCoreStores } from '@deriv/stores/types';

const getScrollOffset = (items_count = 0) => {
if (isMobile()) return '200px';
if (items_count <= 2) return '0px';
return '80px';
type TProofOfOwnershipForm = {
client_email: TCoreStores['client']['email'];
grouped_payment_method_data: Partial<Record<TPaymentMethod, TPaymentMethodInfo>>;
is_mobile: TCoreStores['ui']['is_mobile'];
refreshNotifications: TCoreStores['notifications']['refreshNotifications'];
updateAccountStatus: TCoreStores['client']['updateAccountStatus'];
};

//need to check types
// type TInitialValues = { data?: DeepPartial<TPaymentMethodUploadData>[][] };
// type TErrors = { data?: { payment_method_identifier?: string; files?: File[] }[] };

const ProofOfOwnershipForm = ({
client_email,
grouped_payment_method_data,
is_mobile,
refreshNotifications,
updateAccountStatus,
}) => {
}: TProofOfOwnershipForm) => {
const grouped_payment_method_data_keys = Object.keys(grouped_payment_method_data);
const initial_values = {};
const [form_state, setFormState] = useStateCallback({ should_show_form: true });
const form_ref = React.useRef();
const fileReadErrorMessage = filename => {
const [form_state, setFormState] = React.useState({ is_btn_loading: false });
const form_ref = React.useRef(null);

const getScrollOffset = React.useCallback(
(items_count = 0) => {
if (is_mobile) return '200px';
if (items_count <= 2) return '0px';
return '80px';
},
[is_mobile]
);

const fileReadErrorMessage = (filename: string) => {
return localize('Unable to read file {{name}}', { name: filename });
};
const validateFields = values => {
Expand Down Expand Up @@ -137,25 +156,25 @@ const ProofOfOwnershipForm = ({
return errors;
};

const updateErrors = async (index, item_index, sub_index) => {
const updateErrors = async (index: number, item_index: number, sub_index: number) => {
let error_count = 0;
const errors = {};
const errors: FormikErrors<TInitialValues> = {};
errors.data = [...(form_ref?.current?.errors?.data || [])];
if (typeof errors.data[index] === 'object') {
if (typeof errors?.data[index] === 'object') {
delete errors?.data?.[index]?.[item_index]?.files?.[sub_index];
const has_other_errors = errors?.data[index]?.[item_index]?.files?.some(error => error !== null);
if (!has_other_errors) {
delete errors?.data[index]?.[item_index];
}
errors.data.forEach(e => {
errors?.data?.forEach(e => {
error_count += Object.keys(e || {}).length;
});
if (error_count === 0) {
errors.data = [];
}
}
await form_ref.current.setErrors(errors);
await form_ref.current.validateForm();
await form_ref?.current?.setErrors(errors);
await form_ref?.current?.validateForm();
};
const handleFormSubmit = ({ data: form_values }) => {
try {
Expand Down Expand Up @@ -251,7 +270,11 @@ const ProofOfOwnershipForm = ({
)}
<Card
index={index}
details={grouped_payment_method_data[grouped_payment_method_data_key]}
details={
grouped_payment_method_data[
grouped_payment_method_data_key as TPaymentMethod
]
}
updateErrors={updateErrors}
/>
</div>
Expand All @@ -278,12 +301,4 @@ const ProofOfOwnershipForm = ({
);
};

ProofOfOwnershipForm.propTypes = {
client_email: PropTypes.string,
grouped_payment_method_data: PropTypes.object,
refreshNotifications: PropTypes.func,
updateAccountStatus: PropTypes.func,
citizen: PropTypes.string,
};

export default ProofOfOwnershipForm;
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
import React, { useEffect, useState } from 'react';
import { withRouter } from 'react-router-dom';
import { GetAccountStatus } from '@deriv/api-types';
import { Loading } from '@deriv/components';
import { observer, useStore } from '@deriv/stores';
import ProofOfOwnershipForm from './proof-of-ownership-form.jsx';
import ProofOfOwnershipForm from './proof-of-ownership-form';
import { POONotRequired, POOVerified, POORejetced, POOSubmitted } from 'Components/poo/statuses';
import { POO_STATUSES } from '../../../Constants/poo-identifier.ts';
import { POO_STATUSES } from 'Constants/poo-identifier';
import getPaymentMethodsConfig from '../../../Configs/payment-method-config';
import { TPaymentMethod, TPaymentMethodIdentifier, TPaymentMethodInfo } from 'Types';

export const ProofOfOwnership = observer(() => {
const { client, notifications, ui } = useStore();
const { account_status, email: client_email, updateAccountStatus } = client;
const { is_dark_mode_on: is_dark_mode, is_mobile } = ui;
const { refreshNotifications } = notifications;
const { is_dark_mode_on: is_dark_mode } = ui;
const cards = account_status?.authentication?.ownership?.requests;
const cards = account_status?.authentication?.ownership
?.requests as DeepRequired<GetAccountStatus>['authentication']['ownership']['requests'];
const [status, setStatus] = useState(POO_STATUSES.NONE);
const citizen = client?.account_settings?.citizen || client?.account_settings?.country_code;

const grouped_payment_method_data = React.useMemo(() => {
const groups = {};
const groups: Partial<Record<TPaymentMethod, TPaymentMethodInfo>> = {};
const payment_methods_config = getPaymentMethodsConfig();
cards?.forEach(card => {
const card_payment_method = card?.payment_method?.toLowerCase() || '';
const card_details =
payment_methods_config[card.payment_method.toLowerCase()] || payment_methods_config.other;
if (groups[card?.payment_method?.toLowerCase()]) {
groups[card?.payment_method?.toLowerCase()].items.push(card);
payment_methods_config[card_payment_method as TPaymentMethod] || payment_methods_config.other;

if (groups[card_payment_method as TPaymentMethod]) {
groups[card_payment_method as TPaymentMethod]?.items?.push(card);
} else {
groups[card?.payment_method?.toLowerCase()] = {
groups[card_payment_method as TPaymentMethod] = {
documents_required: card?.documents_required,
icon: is_dark_mode ? card_details?.icon_dark : card_details?.icon_light,
payment_method: card?.payment_method,
items: [card],
instructions: card_details.instructions,
input_label: card_details?.input_label,
identifier_type: card_details.identifier_type,
identifier_type: card_details.identifier_type as TPaymentMethodIdentifier,
is_generic_pm: !card_details?.input_label,
};
}
});
return { groups };
}, [cards, is_dark_mode]);
useEffect(() => {
setStatus(account_status?.authentication?.ownership?.status?.toLowerCase());
setStatus(account_status?.authentication?.ownership?.status?.toLowerCase() || '');
}, [account_status]);
const onTryAgain = () => {
setStatus(POO_STATUSES.NONE);
};
if (cards?.length > 0 && status !== POO_STATUSES.REJECTED) {
if (cards?.length && status !== POO_STATUSES.REJECTED) {
return (
<ProofOfOwnershipForm
client_email={client_email}
grouped_payment_method_data={grouped_payment_method_data.groups}
updateAccountStatus={updateAccountStatus}
is_mobile={is_mobile}
refreshNotifications={refreshNotifications}
client_email={client_email}
citizen={citizen}
updateAccountStatus={updateAccountStatus}
/>
); // Proof of ownership is required.
}
Expand Down
17 changes: 13 additions & 4 deletions packages/account/src/Types/common.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import React from 'react';
import { FormikHandlers, FormikProps, FormikValues } from 'formik';
import { Redirect } from 'react-router-dom';
import { Authorize, GetAccountStatus, IdentityVerificationAddDocumentResponse, ResidenceList } from '@deriv/api-types';
import { IDENTIFIER_TYPES } from '../Constants/poo-identifier';
import { Platforms } from '@deriv/shared';
import { IDENTIFIER_TYPES } from '../Constants/poo-identifier';
import getPaymentMethodsConfig from '../Configs/payment-method-config';

export type TToken = {
display_name: string;
Expand Down Expand Up @@ -192,9 +193,17 @@ export type TPaymentMethodInfo = {
documents_required: number;
icon: string;
payment_method: string;
items: NonNullable<NonNullable<GetAccountStatus['authentication']>['ownership']>['requests'];
instructions: Array<string>;
input_label: string;
items: DeepRequired<GetAccountStatus>['authentication']['ownership']['requests'];
instructions: string[] | JSX.Element[];
input_label: string | null;
identifier_type: TPaymentMethodIdentifier;
is_generic_pm: boolean;
};

export type TPaymentMethod = keyof ReturnType<typeof getPaymentMethodsConfig>;

export type TPaymentMethodUploadData = {
files: Blob[];
id: number;
payment_method_identifier: string;
} & Pick<TPaymentMethodInfo, 'documents_required' | 'identifier_type' | 'is_generic_pm'>;
Loading

0 comments on commit 0f0884e

Please sign in to comment.