From 71c6056cb476806fb7d3597980bc63d7a0a2a3f2 Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:38:45 +0400 Subject: [PATCH] [account-v2]/likhith/coj-706/created accordion and modal component (#14676) * feat: created accordion and modal component * fix: incorporated code review comments * feat: incoprorated config for POO * feat: incoprorated config for POO * feat: incoprorated config for POO * fix: CI issues * Merge branch 'master' into likhith/COJ-709/POO-components * Merge branch 'master' into likhith/COJ-709/POO-components * Merge branch 'master' into likhith/COJ-709/POO-components * chore: update import for useOnClickOutside hook from deriv-com/ui to usehooks-ts (#74) * feat: added hook to generate POO data * Merge branch 'master' into likhith/COJ-709/POO-components * fix: incorporated review comments * feat: added util functions * fix: types issue * fix: removed unused import * fix: upgraded quill icons version * chore: refactored config * chore: added testcases * fix: incorporated review comment * fix: updated package version * fix: incorporated Snoar cloud suggestions * fix: element ref missing issue * fix: incorporate review comment * fix: modified config --------- Co-authored-by: Aum Bhatt <125039206+aum-deriv@users.noreply.github.com> --- package-lock.json | 16 +- packages/account-v2/package.json | 4 +- packages/account-v2/src/App.tsx | 6 +- ...onstants.tsx => connectedAppsConstants.ts} | 0 .../account-v2/src/constants/constants.ts | 6 + .../{errorMessages.tsx => errorMessages.ts} | 0 packages/account-v2/src/constants/index.ts | 1 + .../src/constants/paymentMethodsConfig.ts | 167 ++++++++++++++++++ .../MaskCardModal/MaskCardModal.tsx | 26 +++ .../__tests__/MaskCardModal.spec.tsx | 47 +++++ .../PaymentMethodInstructions.tsx | 153 ++++++++++++++++ .../PaymentMethodInstructions.spec.tsx | 128 ++++++++++++++ packages/account-v2/src/containers/index.ts | 2 + .../__tests__/usePaymentMethodDetails.spec.ts | 153 ++++++++++++++++ packages/account-v2/src/hooks/index.ts | 1 + .../src/hooks/usePaymentMethodDetails.ts | 40 +++++ packages/account-v2/src/modules/package.json | 140 +++++++-------- .../ProofOfOwnership/ProofOfOwnership.tsx | 69 ++++++++ packages/account-v2/src/pages/index.ts | 1 + .../account-v2/src/router/routesConfig.tsx | 4 +- packages/account-v2/src/types.ts | 45 ++++- packages/account-v2/src/utils/index.ts | 1 + packages/account-v2/src/utils/pooUtils.ts | 32 ++++ packages/cashier-v2/package.json | 4 +- .../TransferDropdown/TransferDropdown.tsx | 3 +- packages/p2p-v2/package.json | 4 +- packages/tradershub/package.json | 4 +- packages/wallets/package.json | 2 +- 28 files changed, 967 insertions(+), 92 deletions(-) rename packages/account-v2/src/constants/{connectedAppsConstants.tsx => connectedAppsConstants.ts} (100%) rename packages/account-v2/src/constants/{errorMessages.tsx => errorMessages.ts} (100%) create mode 100644 packages/account-v2/src/constants/paymentMethodsConfig.ts create mode 100644 packages/account-v2/src/containers/MaskCardModal/MaskCardModal.tsx create mode 100644 packages/account-v2/src/containers/MaskCardModal/__tests__/MaskCardModal.spec.tsx create mode 100644 packages/account-v2/src/containers/PaymentMethods/PaymentMethodInstructions.tsx create mode 100644 packages/account-v2/src/containers/PaymentMethods/__tests__/PaymentMethodInstructions.spec.tsx create mode 100644 packages/account-v2/src/hooks/__tests__/usePaymentMethodDetails.spec.ts create mode 100644 packages/account-v2/src/hooks/usePaymentMethodDetails.ts create mode 100644 packages/account-v2/src/pages/ProofOfOwnership/ProofOfOwnership.tsx create mode 100644 packages/account-v2/src/utils/pooUtils.ts diff --git a/package-lock.json b/package-lock.json index fc075c3e5132..19d8386f7059 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,14 +15,14 @@ "@datadog/browser-logs": "^5.11.0", "@datadog/browser-rum": "^5.11.0", "@deriv-com/analytics": "1.4.13", - "@deriv-com/ui": "^1.12.17", + "@deriv-com/ui": "^1.14.1", "@deriv-com/utils": "^0.0.14", "@deriv/api-types": "^1.0.172", "@deriv/deriv-api": "^1.0.15", "@deriv/deriv-charts": "^2.1.13", "@deriv/js-interpreter": "^3.0.0", "@deriv/quill-design": "^1.3.2", - "@deriv/quill-icons": "^1.21.1", + "@deriv/quill-icons": "^1.22.4", "@deriv/react-joyride": "^2.6.2", "@deriv/ui": "^0.6.0", "@livechat/customer-sdk": "^2.0.4", @@ -2962,9 +2962,9 @@ } }, "node_modules/@deriv-com/ui": { - "version": "1.12.17", - "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.12.17.tgz", - "integrity": "sha512-dCV53ugag3dApg/HX+XgIpUFxsi3Y7UUkLObjXqcue/kABzBii5aNxA01561JgUEO8EkjHNxSEHk7i7wi8Po8g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.14.1.tgz", + "integrity": "sha512-gaLopXyvYQrB0DLT/fpbU4JNd5R9u6XDnKvBqrsyRgidSPmth/Q3ar6M4qe5Q2GBisbOkcMawPmIkHJkZ71kfQ==", "dependencies": { "@types/react-modal": "^3.16.3" }, @@ -3078,9 +3078,9 @@ } }, "node_modules/@deriv/quill-icons": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/@deriv/quill-icons/-/quill-icons-1.21.3.tgz", - "integrity": "sha512-Wp7Qssly/tsTU2vCiWEAdqUUqIcBVz3p18BgwvZUJT2+MUEJtuJNJx9KbrnhJzBO8sC92Gzjo4zB0lJnNnN4vA==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/@deriv/quill-icons/-/quill-icons-1.22.4.tgz", + "integrity": "sha512-05/DpUwWo17ECaPHeSlcFHeJOSF60ONDa6BthkIFwpBzTSaQgeD/s+Hwd0CivQDEaqjxJPoY2y54+EZ3ubmaWA==", "peerDependencies": { "react": ">= 16", "react-dom": ">= 16" diff --git a/packages/account-v2/package.json b/packages/account-v2/package.json index 99dd5634f458..5e0b389d2a23 100644 --- a/packages/account-v2/package.json +++ b/packages/account-v2/package.json @@ -11,11 +11,11 @@ "start": "rimraf dist && npm run test && npm run serve" }, "dependencies": { - "@deriv-com/ui": "^1.12.17", + "@deriv-com/ui": "^1.14.1", "@deriv-com/utils": "^0.0.14", "@deriv/api-types": "^1.0.172", "@deriv/api-v2": "^1.0.0", - "@deriv/quill-icons": "^1.21.1", + "@deriv/quill-icons": "^1.22.4", "class-variance-authority": "^0.7.0", "dayjs": "^1.11.10", "formik": "^2.1.4", diff --git a/packages/account-v2/src/App.tsx b/packages/account-v2/src/App.tsx index 7dc7199b4a58..6a40d409e051 100644 --- a/packages/account-v2/src/App.tsx +++ b/packages/account-v2/src/App.tsx @@ -8,7 +8,11 @@ import { ACCOUNT_MODAL_REF } from './constants'; import './index.scss'; const App: React.FC = () => { - Modal.setAppElement(ACCOUNT_MODAL_REF); + if (document.getElementById(ACCOUNT_MODAL_REF.replace('#', ''))) { + // Set the Modal REF only if the element exists + Modal.setAppElement(ACCOUNT_MODAL_REF); + } + return ( diff --git a/packages/account-v2/src/constants/connectedAppsConstants.tsx b/packages/account-v2/src/constants/connectedAppsConstants.ts similarity index 100% rename from packages/account-v2/src/constants/connectedAppsConstants.tsx rename to packages/account-v2/src/constants/connectedAppsConstants.ts diff --git a/packages/account-v2/src/constants/constants.ts b/packages/account-v2/src/constants/constants.ts index 3676e6c9eebf..4c76b5af6818 100644 --- a/packages/account-v2/src/constants/constants.ts +++ b/packages/account-v2/src/constants/constants.ts @@ -28,3 +28,9 @@ export const POI_SUBMISSION_STATUS = { selecting: 'selecting', submitting: 'submitting', } as const; + +export const EXTERNAL_LINKS = { + astroPayURL: 'https://app.astropay.com/profile', + onlinenairaBankURL: 'https://onlinenaira.com/members/bank.htm', + onlinenairaProfileURL: 'https://onlinenaira.com/members/index.htm', +} as const; diff --git a/packages/account-v2/src/constants/errorMessages.tsx b/packages/account-v2/src/constants/errorMessages.ts similarity index 100% rename from packages/account-v2/src/constants/errorMessages.tsx rename to packages/account-v2/src/constants/errorMessages.ts diff --git a/packages/account-v2/src/constants/index.ts b/packages/account-v2/src/constants/index.ts index 1ad1aeb6c8b8..b0df606ad7c0 100644 --- a/packages/account-v2/src/constants/index.ts +++ b/packages/account-v2/src/constants/index.ts @@ -7,5 +7,6 @@ export { export * from './constants'; export * from './errorMessages'; export * from './manualFormConstants'; +export * from './paymentMethodsConfig'; export * from './routes'; export * from './twoFactorAuthenticationConstants'; diff --git a/packages/account-v2/src/constants/paymentMethodsConfig.ts b/packages/account-v2/src/constants/paymentMethodsConfig.ts new file mode 100644 index 000000000000..a957caa4f16e --- /dev/null +++ b/packages/account-v2/src/constants/paymentMethodsConfig.ts @@ -0,0 +1,167 @@ +import { + DerivLightWalletIcon, + IconTypes, + PaymentMethodAdvcashBrandDarkIcon, + PaymentMethodAdvcashBrandIcon, + PaymentMethodAstropayBrandDarkIcon, + PaymentMethodAstropayBrandIcon, + PaymentMethodBeyonicBrandIcon, + PaymentMethodBoletoBrandIcon, + PaymentMethodBoletoWhiteIcon, + PaymentMethodJetonBrandIcon, + PaymentMethodMastercardBrandDarkIcon, + PaymentMethodMastercardBrandIcon, + PaymentMethodNetellerBrandIcon, + PaymentMethodNetellerWhiteIcon, + PaymentMethodOnlinenairaBrandDarkIcon, + PaymentMethodOnlinenairaBrandIcon, + PaymentMethodSkrillBrandIcon, + PaymentMethodSkrillWhiteIcon, + PaymentMethodSticpayBrandIcon, + PaymentMethodVisaBrandIcon, + PaymentMethodVisaWhiteIcon, +} from '@deriv/quill-icons'; +import { TPaymentMethod } from 'src/types'; + +/* eslint-disable sonarjs/no-duplicate-string */ +export const PAYMENT_METHOD_IDENTIFIER = Object.freeze({ + accountID: 'account_id', + accountNumber: 'account_number', + bankAccountNumber: 'bank_account_number', + cardNumber: 'card_number', + email: 'email_address', + mobileNumber: 'mobile_number', + userID: 'user_id', +}); + +export const getPaymentMethodsConfig = () => ({ + advcash: { + identifier: PAYMENT_METHOD_IDENTIFIER.email, + inputLabel: 'Email address', + }, + astropay: { + identifier: PAYMENT_METHOD_IDENTIFIER.accountNumber, + inputLabel: 'Account number', + }, + beyonic: { + identifier: PAYMENT_METHOD_IDENTIFIER.mobileNumber, + inputLabel: 'Mobile number', + }, + 'boleto (d24 voucher)': { + identifier: PAYMENT_METHOD_IDENTIFIER.bankAccountNumber, + inputLabel: 'Bank account number', + }, + jeton: { + identifier: PAYMENT_METHOD_IDENTIFIER.accountNumber, + inputLabel: 'Account number', + }, + mastercard: { + identifier: PAYMENT_METHOD_IDENTIFIER.cardNumber, + inputLabel: 'Card number', + }, + neteller: { + identifier: PAYMENT_METHOD_IDENTIFIER.email, + inputLabel: 'Email address', + }, + onlinenaira: { + identifier: PAYMENT_METHOD_IDENTIFIER.accountID, + inputLabel: 'Account ID', + }, + other: { + identifier: 'none', + inputLabel: null, + }, + pix: { + identifier: PAYMENT_METHOD_IDENTIFIER.userID, + inputLabel: 'User ID', + }, + skrill: { + identifier: PAYMENT_METHOD_IDENTIFIER.email, + inputLabel: 'Email address', + }, + sticpay: { + identifier: PAYMENT_METHOD_IDENTIFIER.email, + inputLabel: 'Email address', + }, + visa: { + identifier: PAYMENT_METHOD_IDENTIFIER.cardNumber, + inputLabel: 'Card number', + }, + webmoney: { + identifier: PAYMENT_METHOD_IDENTIFIER.accountNumber, + inputLabel: 'Account number', + }, + zingpay: { + identifier: PAYMENT_METHOD_IDENTIFIER.bankAccountNumber, + inputLabel: 'Bank account number', + }, +}); + +type TPaymentMethodIcon = Record; + +export const getPaymentMethodIcon: TPaymentMethodIcon = { + advcash: { + dark: PaymentMethodAdvcashBrandDarkIcon, + light: PaymentMethodAdvcashBrandIcon, + }, + astropay: { + dark: PaymentMethodAstropayBrandDarkIcon, + light: PaymentMethodAstropayBrandIcon, + }, + beyonic: { + dark: PaymentMethodBeyonicBrandIcon, + light: PaymentMethodBeyonicBrandIcon, + }, + 'boleto (d24 voucher)': { + dark: PaymentMethodBoletoWhiteIcon, + light: PaymentMethodBoletoBrandIcon, + }, + jeton: { + dark: PaymentMethodJetonBrandIcon, + light: PaymentMethodJetonBrandIcon, + }, + mastercard: { + dark: PaymentMethodMastercardBrandDarkIcon, + light: PaymentMethodMastercardBrandIcon, + }, + neteller: { + dark: PaymentMethodNetellerWhiteIcon, + light: PaymentMethodNetellerBrandIcon, + }, + onlinenaira: { + dark: PaymentMethodOnlinenairaBrandDarkIcon, + light: PaymentMethodOnlinenairaBrandIcon, + }, + other: { + // TODO: Change this icon once actual icon is available + dark: DerivLightWalletIcon, + light: DerivLightWalletIcon, + }, + pix: { + // TODO: Change this icon once actual icon is available + dark: DerivLightWalletIcon, + light: DerivLightWalletIcon, + }, + skrill: { + dark: PaymentMethodSkrillWhiteIcon, + light: PaymentMethodSkrillBrandIcon, + }, + sticpay: { + dark: PaymentMethodSticpayBrandIcon, + light: PaymentMethodSticpayBrandIcon, + }, + visa: { + dark: PaymentMethodVisaWhiteIcon, + light: PaymentMethodVisaBrandIcon, + }, + webmoney: { + // TODO: Change this icon once actual icon is available + dark: DerivLightWalletIcon, + light: DerivLightWalletIcon, + }, + zingpay: { + // TODO: Change this icon once actual icon is available + dark: DerivLightWalletIcon, + light: DerivLightWalletIcon, + }, +}; diff --git a/packages/account-v2/src/containers/MaskCardModal/MaskCardModal.tsx b/packages/account-v2/src/containers/MaskCardModal/MaskCardModal.tsx new file mode 100644 index 000000000000..1b767a7b0255 --- /dev/null +++ b/packages/account-v2/src/containers/MaskCardModal/MaskCardModal.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { DerivLightCreditCardSampleIcon } from '@deriv/quill-icons'; +import { Modal, Text } from '@deriv-com/ui'; + +type TMaskCardModal = { + isOpen: boolean; + onClose: () => void; +}; + +export const MaskCardModal = ({ isOpen, onClose }: TMaskCardModal) => { + return ( + + + + How to mask your card? + + + + + Black out digits 7 to 12 of the card number that’s shown on the front of your debit/credit card.⁤ + + + + + ); +}; diff --git a/packages/account-v2/src/containers/MaskCardModal/__tests__/MaskCardModal.spec.tsx b/packages/account-v2/src/containers/MaskCardModal/__tests__/MaskCardModal.spec.tsx new file mode 100644 index 000000000000..4dc261390905 --- /dev/null +++ b/packages/account-v2/src/containers/MaskCardModal/__tests__/MaskCardModal.spec.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Modal } from '@deriv-com/ui'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { ACCOUNT_MODAL_REF } from 'src/constants'; +import { MaskCardModal } from '../MaskCardModal'; + +describe('MaskCardModal', () => { + let elModalRoot: HTMLElement; + + beforeAll(() => { + elModalRoot = document.createElement('div'); + elModalRoot.setAttribute('id', ACCOUNT_MODAL_REF.replace('#', '')); + document.body.appendChild(elModalRoot); + Modal.setAppElement(ACCOUNT_MODAL_REF); + }); + + afterAll(() => { + document.body.removeChild(elModalRoot); + }); + + it('should render correctly with the modal open', () => { + const isOpen = true; + const onClose = jest.fn(); + + render(); + + expect(screen.getByText('How to mask your card?')).toBeInTheDocument(); + expect( + screen.getByText( + 'Black out digits 7 to 12 of the card number that’s shown on the front of your debit/credit card.⁤' + ) + ).toBeInTheDocument(); + }); + + it('should close the modal when close icon is clicked', () => { + const isOpen = true; + const onClose = jest.fn(); + + render(); + + const elCloseIcon = screen.getByTestId('dt-close-icon'); + userEvent.click(elCloseIcon); + + expect(onClose).toHaveBeenCalled(); + }); +}); diff --git a/packages/account-v2/src/containers/PaymentMethods/PaymentMethodInstructions.tsx b/packages/account-v2/src/containers/PaymentMethods/PaymentMethodInstructions.tsx new file mode 100644 index 000000000000..a919ca29d819 --- /dev/null +++ b/packages/account-v2/src/containers/PaymentMethods/PaymentMethodInstructions.tsx @@ -0,0 +1,153 @@ +import React from 'react'; +import { Text } from '@deriv-com/ui'; +import { EXTERNAL_LINKS } from 'src/constants'; +import { TPaymentMethod } from 'src/types'; + +type TPaymentMethodInstructionsProps = { paymentMethod: TPaymentMethod }; + +export const PaymentMethodInstructions = ({ paymentMethod }: TPaymentMethodInstructionsProps) => { + switch (paymentMethod) { + case 'advcash': + case 'neteller': { + return ( + + Upload a screenshot of your name and email address from the personal information section. + + ); + } + case 'astropay': { + return ( +
+ + Upload 2 separate screenshots from the personal details page and the account page via{' '} + + + {EXTERNAL_LINKS.astroPayURL} + +
+ ); + } + case 'beyonic': { + return ( + + Upload your mobile bill statement showing your name and phone number. + + ); + } + case 'boleto (d24 voucher)': { + return ( + + Upload your bank statement showing your name and account details. + + ); + } + case 'jeton': { + return ( + + Upload a screenshot of your name and account number from the personal details section. + + ); + } + case 'mastercard': + case 'visa': { + return ( + + Upload a photo showing your name and the first six and last four digits of your card number. If the + card does not display your name, upload the bank statement showing your name and card number in the + transaction history. + + ); + } + case 'onlinenaira': { + return ( +
    + + Upload a screenshot of your account profile section on the website. + + {EXTERNAL_LINKS.onlinenairaProfileURL} + + + + + Upload a screenshot of your account number and phone number on the Bank Account/Mobile + wallet page at + + + {EXTERNAL_LINKS.onlinenairaBankURL} + + +
+ ); + } + case 'pix': { + return ( +
+ + Upload a screenshot of either of the following to process the transaction: + + + - your account profile section on the website + + + - the Account Information page on the app + + + - your account details of the bank linked to your account + +
+ ); + } + case 'skrill': { + return ( + + Upload a screenshot of your name, account number, and email address from the personal details + section of the app or profile section of your account on the website. + + ); + } + case 'sticpay': { + return ( + + Upload a screenshot of your name and email address from the personal details section. + + ); + } + case 'webmoney': { + return ( + + Upload a screenshot of your account and personal details page with your name, account number, phone + number, and email address. + + ); + } + case 'zingpay': { + return ( + + Upload your bank statement showing your name, account number, and transaction history. + + ); + } + default: { + return ( + + Upload a document showing your name and bank account number or account details. + + ); + } + } +}; diff --git a/packages/account-v2/src/containers/PaymentMethods/__tests__/PaymentMethodInstructions.spec.tsx b/packages/account-v2/src/containers/PaymentMethods/__tests__/PaymentMethodInstructions.spec.tsx new file mode 100644 index 000000000000..9f7613f0393b --- /dev/null +++ b/packages/account-v2/src/containers/PaymentMethods/__tests__/PaymentMethodInstructions.spec.tsx @@ -0,0 +1,128 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { PaymentMethodInstructions } from '../PaymentMethodInstructions'; + +describe('PaymentMethodInstructions', () => { + it('should render correct instructions for advcash', () => { + render(); + expect( + screen.getByText( + 'Upload a screenshot of your name and email address from the personal information section.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for neteller', () => { + render(); + expect( + screen.getByText( + 'Upload a screenshot of your name and email address from the personal information section.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for astropay', () => { + render(); + expect( + screen.getByText('Upload 2 separate screenshots from the personal details page and the account page via') + ).toBeInTheDocument(); + expect(screen.getByText('https://app.astropay.com/profile')).toBeInTheDocument(); + }); + + it('should render correct instructions for beyonic', () => { + render(); + expect( + screen.getByText('Upload your mobile bill statement showing your name and phone number.') + ).toBeInTheDocument(); + }); + + it('should render correct instructions for boleto (d24 voucher)', () => { + render(); + expect( + screen.getByText('Upload your bank statement showing your name and account details.') + ).toBeInTheDocument(); + }); + + it('should render correct instructions for jeton', () => { + render(); + expect( + screen.getByText('Upload a screenshot of your name and account number from the personal details section.') + ).toBeInTheDocument(); + }); + + it('should render correct instructions for mastercard', () => { + render(); + expect( + screen.getByText( + 'Upload a photo showing your name and the first six and last four digits of your card number. If the card does not display your name, upload the bank statement showing your name and card number in the transaction history.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for visa', () => { + render(); + expect( + screen.getByText( + 'Upload a photo showing your name and the first six and last four digits of your card number. If the card does not display your name, upload the bank statement showing your name and card number in the transaction history.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for onlinenaira', () => { + render(); + expect(screen.getAllByRole('listitem')).toHaveLength(2); + expect(screen.getByText('https://onlinenaira.com/members/index.htm')).toBeInTheDocument(); + expect(screen.getByText('https://onlinenaira.com/members/bank.htm')).toBeInTheDocument(); + }); + + it('should render correct instructions for pix', () => { + render(); + expect( + screen.getByText('Upload a screenshot of either of the following to process the transaction:') + ).toBeInTheDocument(); + expect(screen.getByText('- your account profile section on the website')).toBeInTheDocument(); + expect(screen.getByText('- the Account Information page on the app')).toBeInTheDocument(); + expect(screen.getByText('- your account details of the bank linked to your account')).toBeInTheDocument(); + }); + + it('should render correct instructions for skrill', () => { + render(); + expect( + screen.getByText( + 'Upload a screenshot of your name, account number, and email address from the personal details section of the app or profile section of your account on the website.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for sticpay', () => { + render(); + expect( + screen.getByText('Upload a screenshot of your name and email address from the personal details section.') + ).toBeInTheDocument(); + }); + + it('should render correct instructions for webmoney', () => { + render(); + expect( + screen.getByText( + 'Upload a screenshot of your account and personal details page with your name, account number, phone number, and email address.' + ) + ).toBeInTheDocument(); + }); + + it('should render correct instructions for zingpay', () => { + render(); + expect( + screen.getByText('Upload your bank statement showing your name, account number, and transaction history.') + ).toBeInTheDocument(); + }); + + it('should render correct instructions for other payment methods', () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore: Ignore the type error related to paymentMethod + render(); + expect( + screen.getByText('Upload a document showing your name and bank account number or account details.') + ).toBeInTheDocument(); + }); +}); diff --git a/packages/account-v2/src/containers/index.ts b/packages/account-v2/src/containers/index.ts index c227c07768c2..008c70ea2c8c 100644 --- a/packages/account-v2/src/containers/index.ts +++ b/packages/account-v2/src/containers/index.ts @@ -2,7 +2,9 @@ export { AccountClosureForm } from './AccountClosureForm/AccountClosureForm'; export { AccountClosureSteps } from './AccountClosureSteps/AccountClosureSteps'; export { LoginHistoryTable } from './LoginHistoryTable/LoginHistoryTable'; export { LoginHistoryTableCard } from './LoginHistoryTable/LoginHistoryTableCard'; +export { MaskCardModal } from './MaskCardModal/MaskCardModal'; export { OnfidoView } from './Onfido/OnfidoView'; +export { PaymentMethodInstructions } from './PaymentMethods/PaymentMethodInstructions'; export { PersonalDetailsFormWithExample } from './PersonalDetailsFormWithExample/PersonalDetailsFormWithExample'; export { POICountrySelector } from './POICountrySelector/POICountrySelector'; export { POIFlowContainer } from './POIFlowContainer/POIFlowContainer'; diff --git a/packages/account-v2/src/hooks/__tests__/usePaymentMethodDetails.spec.ts b/packages/account-v2/src/hooks/__tests__/usePaymentMethodDetails.spec.ts new file mode 100644 index 000000000000..154e6fcb892f --- /dev/null +++ b/packages/account-v2/src/hooks/__tests__/usePaymentMethodDetails.spec.ts @@ -0,0 +1,153 @@ +import { useGetAccountStatus } from '@deriv/api-v2'; +import { renderHook } from '@testing-library/react-hooks'; +import { AUTH_STATUS_CODES } from 'src/constants'; +import { TPaymentMethod, TPaymentMethodInfo } from 'src/types'; +import { usePaymentMethodDetails } from '../usePaymentMethodDetails'; + +jest.mock('@deriv/api-v2', () => ({ + ...jest.requireActual('@deriv/api-v2'), + useGetAccountStatus: jest.fn(), +})); + +describe('usePaymentMethodDetails', () => { + const mockData = { + other: { + documentsRequired: 3, + identifier: 'none', + inputLabel: null, + isGenericPM: true, + items: [ + { + documents_required: 3, + payment_method: 'UPI', + }, + ], + paymentMethod: 'UPI', + }, + skrill: { + documentsRequired: 2, + identifier: 'email_address', + inputLabel: 'Email address', + isGenericPM: false, + items: [ + { + documents_required: 2, + payment_method: 'SKRILL', + }, + ], + paymentMethod: 'SKRILL', + }, + visa: { + documentsRequired: 1, + + identifier: 'card_number', + inputLabel: 'Card number', + isGenericPM: false, + items: [ + { + documents_required: 1, + payment_method: 'VISA', + }, + ], + paymentMethod: 'VISA', + }, + }; + + type TMockData = keyof typeof mockData; + + it('should return ownershipStatus and paymentMethodData', () => { + (useGetAccountStatus as jest.Mock).mockReturnValue({ + data: { + authentication: { + ownership: { + requests: [ + { + documents_required: 1, + payment_method: 'VISA', + }, + { + documents_required: 2, + payment_method: 'SKRILL', + }, + ], + status: AUTH_STATUS_CODES.VERIFIED.toUpperCase(), + }, + }, + }, + isLoading: false, + }); + + const { result } = renderHook(() => usePaymentMethodDetails()); + const { ownershipStatus, paymentMethodData } = result.current; + expect(ownershipStatus).toBe('verified'); + + Object.keys(paymentMethodData).forEach(payment => { + const { documentsRequired, identifier, inputLabel, isGenericPM, items, paymentMethod } = paymentMethodData[ + payment as TPaymentMethod + ] as TPaymentMethodInfo; + expect({ documentsRequired, identifier, inputLabel, isGenericPM, items, paymentMethod }).toEqual( + mockData[payment as TMockData] + ); + }); + }); + + it('should return details of default payment method when payment method is not configured', () => { + (useGetAccountStatus as jest.Mock).mockReturnValue({ + data: { + authentication: { + ownership: { + requests: [ + { + documents_required: 3, + payment_method: 'UPI', + }, + ], + status: AUTH_STATUS_CODES.VERIFIED.toUpperCase(), + }, + }, + }, + isLoading: false, + }); + + const { result } = renderHook(() => usePaymentMethodDetails()); + const { paymentMethodData } = result.current; + + Object.keys(paymentMethodData).forEach(payment => { + const { documentsRequired, identifier, inputLabel, isGenericPM, items, paymentMethod } = paymentMethodData[ + payment as TPaymentMethod + ] as TPaymentMethodInfo; + expect({ documentsRequired, identifier, inputLabel, isGenericPM, items, paymentMethod }).toEqual( + mockData.other + ); + }); + }); + + it('should populate items with multiple requests for the same payment method', () => { + (useGetAccountStatus as jest.Mock).mockReturnValue({ + data: { + authentication: { + ownership: { + requests: [ + { + documents_required: 1, + payment_method: 'VISA', + }, + { + documents_required: 1, + payment_method: 'VISA', + }, + ], + status: AUTH_STATUS_CODES.VERIFIED.toUpperCase(), + }, + }, + }, + isLoading: false, + }); + + const { result } = renderHook(() => usePaymentMethodDetails()); + const { paymentMethodData } = result.current; + + const { items } = paymentMethodData.visa as TPaymentMethodInfo; + expect(items).toHaveLength(2); + }); +}); diff --git a/packages/account-v2/src/hooks/index.ts b/packages/account-v2/src/hooks/index.ts index aa6e1ee03f56..e6baaa6f4cbb 100644 --- a/packages/account-v2/src/hooks/index.ts +++ b/packages/account-v2/src/hooks/index.ts @@ -1,3 +1,4 @@ export { useManualForm } from './useManualForm'; +export { usePaymentMethodDetails } from './usePaymentMethodDetails'; export { usePOAInfo } from './usePOAInfo'; export { usePOIInfo } from './usePOIInfo'; diff --git a/packages/account-v2/src/hooks/usePaymentMethodDetails.ts b/packages/account-v2/src/hooks/usePaymentMethodDetails.ts new file mode 100644 index 000000000000..cc201e23a33b --- /dev/null +++ b/packages/account-v2/src/hooks/usePaymentMethodDetails.ts @@ -0,0 +1,40 @@ +import { useMemo } from 'react'; +import { useGetAccountStatus } from '@deriv/api-v2'; +import { getPaymentMethodsConfig } from 'src/constants'; +import { TPaymentMethod, TPaymentMethodData, TPaymentMethodIdentifier } from 'src/types'; + +export const usePaymentMethodDetails = () => { + const { data: accountStatus, ...rest } = useGetAccountStatus(); + + const ownership = accountStatus?.authentication?.ownership; + const ownershipStatus = ownership?.status?.toLowerCase(); + + const paymentMethodData = useMemo(() => { + const groups: Partial = {}; + const paymentMethodConfig = getPaymentMethodsConfig(); + ownership?.requests?.forEach(request => { + const paymentMethod = request?.payment_method?.toLowerCase() as TPaymentMethod; + const paymentMethodDetails = paymentMethodConfig[paymentMethod] ?? paymentMethodConfig.other; + + if (groups[paymentMethod]) { + groups[paymentMethod]?.items?.push(request); + } else { + groups[paymentMethod] = { + documentsRequired: request?.documents_required, + identifier: paymentMethodDetails.identifier as TPaymentMethodIdentifier, + inputLabel: paymentMethodDetails.inputLabel, + isGenericPM: !paymentMethodDetails.inputLabel, + items: [request], + paymentMethod: request.payment_method as string, + }; + } + }); + return groups; + }, [ownership?.requests]); + + return { + ownershipStatus, + paymentMethodData, + ...rest, + }; +}; diff --git a/packages/account-v2/src/modules/package.json b/packages/account-v2/src/modules/package.json index f1205e812e22..3b8d41d3bcbb 100644 --- a/packages/account-v2/src/modules/package.json +++ b/packages/account-v2/src/modules/package.json @@ -1,71 +1,73 @@ { - "name": "@deriv-lib/account-v2-lib", - "version": "1.0.0", - "main": "dist/js/index.js", - "sideEffects": ["*.css"], - "types": "dist/types/index.d.ts", - "engines": { - "node": "18.x" - }, - "scripts": { - "prebuild": "node scripts/webpack-entries.js", - "build": "NODE_ENV=production rimraf dist && NODE_OPTIONS='-r ts-node/register' webpack --progress --config \"./webpack.config.ts\"", - "prepublishOnly": "npm run build" - }, - "dependencies": { - "class-variance-authority": "^0.7.0", - "clsx": "^2.0.0", - "i18n-iso-countries": "^6.8.0", - "i18next": "^22.4.6", - "usehooks-ts": "^2.7.0" - }, - "files": [ - "dist", - "README.md" - ], - "peerDependencies": { - "@deriv-com/ui": "1.11.2", - "@deriv/quill-icons": "^1.21.1", - "@deriv/api-v2": "1.0.0", - "yup": "^0.32.11", - "formik": "^2.1.4", - "react-calendar": "^4.7.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-dropzone": "11.0.1", - "react-i18next": "^11.11.0", - "react-router-dom": "^5.2.0", - "tailwind-merge": "^1.14.0" - }, - "devDependencies": { - "@testing-library/react": "^12.0.0", - "@testing-library/user-event": "^13.5.0", - "@types/copy-webpack-plugin": "^10.1.0", - "@types/css-modules": "^1.0.2", - "@types/react-dom": "^18.0.0", - "@types/react-modal": "^3.16.3", - "@types/react-router-dom": "^5.1.6", - "@types/webpack": "^5.28.5", - "@typescript-eslint/eslint-plugin": "5.45.0", - "@typescript-eslint/parser": "5.45.0", - "autoprefixer": "^10.4.16", - "copy-webpack-plugin": "^9.0.1", - "css-loader": "^5.0.1", - "eslint-plugin-local-rules": "2.0.0", - "eslint-plugin-react": "^7.22.0", - "eslint-plugin-react-hooks": "^4.2.0", - "eslint-plugin-simple-import-sort": "^10.0.0", - "eslint-plugin-sonarjs": "^0.23.0", - "eslint-plugin-sort-destructure-keys": "^1.5.0", - "eslint-plugin-typescript-sort-keys": "^2.3.0", - "postcss": "^8.4.24", - "postcss-import": "^16.0.1", - "style-loader": "^1.2.1", - "tailwindcss": "^3.3.6", - "tailwind-merge": "^1.14.0", - "typescript": "^4.6.3", - "webpack": "^5.81.0", - "webpack-bundle-analyzer": "^4.3.0", - "webpack-cli": "^4.7.2" - } + "name": "@deriv-lib/account-v2-lib", + "version": "1.0.0", + "main": "dist/js/index.js", + "sideEffects": [ + "*.css" + ], + "types": "dist/types/index.d.ts", + "engines": { + "node": "18.x" + }, + "scripts": { + "prebuild": "node scripts/webpack-entries.js", + "build": "NODE_ENV=production rimraf dist && NODE_OPTIONS='-r ts-node/register' webpack --progress --config \"./webpack.config.ts\"", + "prepublishOnly": "npm run build" + }, + "dependencies": { + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", + "i18n-iso-countries": "^6.8.0", + "i18next": "^22.4.6", + "usehooks-ts": "^2.7.0" + }, + "files": [ + "dist", + "README.md" + ], + "peerDependencies": { + "@deriv-com/ui": "~1.14.1", + "@deriv/quill-icons": "~1.22.4", + "@deriv/api-v2": "1.0.0", + "yup": "^0.32.11", + "formik": "^2.1.4", + "react-calendar": "^4.7.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-dropzone": "11.0.1", + "react-i18next": "^11.11.0", + "react-router-dom": "^5.2.0", + "tailwind-merge": "^1.14.0" + }, + "devDependencies": { + "@testing-library/react": "^12.0.0", + "@testing-library/user-event": "^13.5.0", + "@types/copy-webpack-plugin": "^10.1.0", + "@types/css-modules": "^1.0.2", + "@types/react-dom": "^18.0.0", + "@types/react-modal": "^3.16.3", + "@types/react-router-dom": "^5.1.6", + "@types/webpack": "^5.28.5", + "@typescript-eslint/eslint-plugin": "5.45.0", + "@typescript-eslint/parser": "5.45.0", + "autoprefixer": "^10.4.16", + "copy-webpack-plugin": "^9.0.1", + "css-loader": "^5.0.1", + "eslint-plugin-local-rules": "2.0.0", + "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-sonarjs": "^0.23.0", + "eslint-plugin-sort-destructure-keys": "^1.5.0", + "eslint-plugin-typescript-sort-keys": "^2.3.0", + "postcss": "^8.4.24", + "postcss-import": "^16.0.1", + "style-loader": "^1.2.1", + "tailwindcss": "^3.3.6", + "tailwind-merge": "^1.14.0", + "typescript": "^4.6.3", + "webpack": "^5.81.0", + "webpack-bundle-analyzer": "^4.3.0", + "webpack-cli": "^4.7.2" + } } diff --git a/packages/account-v2/src/pages/ProofOfOwnership/ProofOfOwnership.tsx b/packages/account-v2/src/pages/ProofOfOwnership/ProofOfOwnership.tsx new file mode 100644 index 000000000000..8b1491e24d98 --- /dev/null +++ b/packages/account-v2/src/pages/ProofOfOwnership/ProofOfOwnership.tsx @@ -0,0 +1,69 @@ +import React, { useEffect, useState } from 'react'; +import { DerivLightWaitingPoaIcon } from '@deriv/quill-icons'; +import { Button, Loader, Text } from '@deriv-com/ui'; +import { IconWithMessage } from 'src/components'; +import { AUTH_STATUS_CODES } from 'src/constants'; +import { usePaymentMethodDetails } from 'src/hooks'; +import { TAuthStatusCodes } from 'src/types'; + +export const ProofOfOwnership = () => { + const { isLoading, ownershipStatus, paymentMethodData } = usePaymentMethodDetails(); + + const [status, setStatus] = useState(); + + useEffect(() => { + setStatus(ownershipStatus as TAuthStatusCodes); + }, [ownershipStatus]); + + if (isLoading) { + return ; + } + + if (Object.keys(paymentMethodData)?.length && status !== AUTH_STATUS_CODES.REJECTED) { + return
ProofOfOwnership
; + } + + switch (status) { + case AUTH_STATUS_CODES.VERIFIED: { + // TODO: Use actual icon once available in Quill + return ( + } title='Proof of ownership verification passed.' /> + ); + } + case AUTH_STATUS_CODES.PENDING: { + // TODO: Use actual icon once available in Quill + return ( + } title='We’ve received your proof of ownership.'> + + We’ll review your documents and notify you of its status within 3 days. + + + ); + } + case AUTH_STATUS_CODES.REJECTED: { + // TODO: Use actual icon once available in Quill + return ( + setStatus(AUTH_STATUS_CODES.NONE)}>Try again} + icon={} + title='Proof of ownership verification failed.' + > + + We were unable to verify your proof of ownership. + + + ); + } + default: { + // TODO: Use actual icon once available in Quill + return ( + } title="Your proof of ownership isn't required."> + + You are not required to submit proof of ownership at this time. We will inform you if proof of + ownership is required in the future. + + + ); + } + } +}; diff --git a/packages/account-v2/src/pages/index.ts b/packages/account-v2/src/pages/index.ts index 9ca6b82160d2..c08cf5657a66 100644 --- a/packages/account-v2/src/pages/index.ts +++ b/packages/account-v2/src/pages/index.ts @@ -2,4 +2,5 @@ export { AccountClosure } from './AccountClosure/AccountClosure'; export { ConnectedApps } from './ConnectedApps/ConnectedApps'; export { LoginHistory } from './LoginHistory/LoginHistory'; export { ManualUploadContainer } from './ManualUploadContainer/ManualUploadContainer'; +export { ProofOfOwnership } from './ProofOfOwnership/ProofOfOwnership'; export { TwoFactorAuthentication } from './TwoFactorAuthentication'; diff --git a/packages/account-v2/src/router/routesConfig.tsx b/packages/account-v2/src/router/routesConfig.tsx index 822b40a550d0..9a8008249c14 100644 --- a/packages/account-v2/src/router/routesConfig.tsx +++ b/packages/account-v2/src/router/routesConfig.tsx @@ -4,7 +4,7 @@ import { TradingAssessmentForm } from '../containers/TradingAssessmentForm'; import { FinancialAssessmentForm } from '../modules/src/FinancialAssessment/FinancialAssessmentForm'; import { POAFormContainer } from '../modules/src/POAForm/POAFormContainer'; import { ProofOfIdentity } from '../modules/src/POI/POI'; -import { AccountClosure, ConnectedApps, LoginHistory, TwoFactorAuthentication } from '../pages'; +import { AccountClosure, ConnectedApps, LoginHistory, ProofOfOwnership, TwoFactorAuthentication } from '../pages'; import { DummyRoute } from './components/DummyRoute/DummyRoute'; export const routes = [ @@ -39,7 +39,7 @@ export const routes = [ routePath: ACCOUNT_V2_ROUTES.ProofOfAddress, }, { - routeComponent: DummyRoute, + routeComponent: ProofOfOwnership, routeName: 'Proof of ownership', routePath: ACCOUNT_V2_ROUTES.ProofOfOwnership, }, diff --git a/packages/account-v2/src/types.ts b/packages/account-v2/src/types.ts index e8298b375e99..b03bd3b94a39 100644 --- a/packages/account-v2/src/types.ts +++ b/packages/account-v2/src/types.ts @@ -1,5 +1,11 @@ -import { useKycAuthStatus, useSettings } from '@deriv/api-v2'; -import { IDV_ERROR_CODES, POI_SERVICE } from './constants'; +import { useGetAccountStatus, useKycAuthStatus, useSettings } from '@deriv/api-v2'; +import { + AUTH_STATUS_CODES, + getPaymentMethodsConfig, + IDV_ERROR_CODES, + PAYMENT_METHOD_IDENTIFIER, + POI_SERVICE, +} from './constants'; export type TSupportedDocuments = Exclude< Exclude['kyc_auth_status'], undefined>['identity']['supported_documents'], @@ -18,6 +24,41 @@ export type TPOIStatus = Exclude< export type TGetSettingsResponse = ReturnType['data']; +export type TAuthStatusCodes = typeof AUTH_STATUS_CODES[keyof typeof AUTH_STATUS_CODES]; + +export type TPaymentMethod = keyof ReturnType; + +export type TPaymentMethodIdentifier = typeof PAYMENT_METHOD_IDENTIFIER[keyof typeof PAYMENT_METHOD_IDENTIFIER]; + +export type TPaymentMethodInfo = { + documentsRequired?: number; + identifier: TPaymentMethodIdentifier | 'none'; + inputLabel: string | null; + isGenericPM: boolean; + items: Exclude< + Exclude< + Exclude['data'], undefined>['authentication'], + undefined + >['ownership'], + undefined + >['requests']; + paymentMethod: string; +}; + +export type TFile = File & { file: Blob }; + +export type TPaymentMethodData = Record; + +export type TProofOfOwnershipData = { + documentsRequired: number; + files: TFile[]; + id: number; + identifierType: TPaymentMethodIdentifier | 'none'; + isGenericPM: boolean; + paymentMethodIdentifier: string; +}; + +export type TProofOfOwnershipFormValue = Record>; export type TPOIService = typeof POI_SERVICE[keyof typeof POI_SERVICE]; export type TIDVErrorStatusCode = typeof IDV_ERROR_CODES[keyof typeof IDV_ERROR_CODES]['code']; diff --git a/packages/account-v2/src/utils/index.ts b/packages/account-v2/src/utils/index.ts index e3d8d9af006c..44418d335bfa 100644 --- a/packages/account-v2/src/utils/index.ts +++ b/packages/account-v2/src/utils/index.ts @@ -4,4 +4,5 @@ export * from './idvFormUtils'; export * from './manualFormUtils'; export * from './personalDetailsUtils'; export * from './poiUtils'; +export * from './pooUtils'; export * from './twoFactorAuthenticationUtils'; diff --git a/packages/account-v2/src/utils/pooUtils.ts b/packages/account-v2/src/utils/pooUtils.ts new file mode 100644 index 000000000000..efe6ef61a73e --- /dev/null +++ b/packages/account-v2/src/utils/pooUtils.ts @@ -0,0 +1,32 @@ +import { TPaymentMethod, TPaymentMethodData, TProofOfOwnershipData, TProofOfOwnershipFormValue } from 'src/types'; + +const defaultValue: TProofOfOwnershipData = { + documentsRequired: 0, + files: [], + id: 0, + identifierType: 'none', + isGenericPM: false, + paymentMethodIdentifier: '', +}; + +export const generatePOOInitialValues = (paymentMethodData: TPaymentMethodData) => { + const paymentMethods = Object.keys(paymentMethodData) as TPaymentMethod[]; + + return paymentMethods.reduce((acc, paymentMethod) => { + const documentsRequired = paymentMethodData[paymentMethod]?.documentsRequired ?? 0; + const items = paymentMethodData[paymentMethod]?.items; + const identifierType = paymentMethodData[paymentMethod]?.identifier ?? 'none'; + const isGenericPM = paymentMethodData[paymentMethod]?.isGenericPM ?? false; + acc[paymentMethod] = {}; + items?.forEach(item => { + acc[paymentMethod][item.id as number] = { + ...defaultValue, + documentsRequired, + id: item.id as number, + identifierType, + isGenericPM, + }; + }); + return acc; + }, {} as TProofOfOwnershipFormValue); +}; diff --git a/packages/cashier-v2/package.json b/packages/cashier-v2/package.json index 1529a2015f73..4a0652cfc916 100644 --- a/packages/cashier-v2/package.json +++ b/packages/cashier-v2/package.json @@ -12,11 +12,11 @@ "start": "rimraf dist && npm run test && npm run serve" }, "dependencies": { - "@deriv-com/ui": "^1.12.17", + "@deriv-com/ui": "^1.14.1", "@deriv-com/utils": "^0.0.14", "@deriv/api-v2": "^1.0.0", "@deriv/integration": "^1.0.0", - "@deriv/quill-icons": "^1.21.1", + "@deriv/quill-icons": "^1.22.4", "@deriv/utils": "^1.0.0", "clsx": "^2.0.0", "formik": "^2.1.4", diff --git a/packages/cashier-v2/src/lib/Transfer/components/TransferForm/components/TransferAccountSelection/components/TransferDropdown/TransferDropdown.tsx b/packages/cashier-v2/src/lib/Transfer/components/TransferForm/components/TransferAccountSelection/components/TransferDropdown/TransferDropdown.tsx index a05959c2fcbb..89f9079e51a2 100644 --- a/packages/cashier-v2/src/lib/Transfer/components/TransferForm/components/TransferAccountSelection/components/TransferDropdown/TransferDropdown.tsx +++ b/packages/cashier-v2/src/lib/Transfer/components/TransferForm/components/TransferAccountSelection/components/TransferDropdown/TransferDropdown.tsx @@ -1,7 +1,8 @@ import React, { useRef, useState } from 'react'; import clsx from 'clsx'; +import { useOnClickOutside } from 'usehooks-ts'; import { LabelPairedChevronDownMdRegularIcon } from '@deriv/quill-icons'; -import { Text, useOnClickOutside } from '@deriv-com/ui'; +import { Text } from '@deriv-com/ui'; import { TTransferableAccounts, TTransferFormikContext } from '../../../../../../types'; import { TransferAccountTile, TransferDropdownList } from './components'; import styles from './TransferDropdown.module.scss'; diff --git a/packages/p2p-v2/package.json b/packages/p2p-v2/package.json index cb9057051395..aa225779d81a 100644 --- a/packages/p2p-v2/package.json +++ b/packages/p2p-v2/package.json @@ -12,11 +12,11 @@ "start": "rimraf dist && npm run test && npm run serve" }, "dependencies": { - "@deriv-com/ui": "^1.12.17", + "@deriv-com/ui": "^1.14.1", "@deriv-com/utils": "^0.0.14", "@deriv/api-v2": "^1.0.0", "@deriv/integration": "^1.0.0", - "@deriv/quill-icons": "^1.21.1", + "@deriv/quill-icons": "^1.22.4", "@deriv/react-joyride": "^2.6.2", "@sendbird/chat": "^4.9.7", "@tanstack/react-table": "^8.10.3", diff --git a/packages/tradershub/package.json b/packages/tradershub/package.json index 8466d695368a..08d40e5b3a33 100644 --- a/packages/tradershub/package.json +++ b/packages/tradershub/package.json @@ -15,8 +15,8 @@ "dependencies": { "@deriv/api-v2": "^1.0.0", "@deriv-lib/account-v2-lib": "1.0.0", - "@deriv/quill-icons": "^1.21.1", - "@deriv-com/ui": "^1.12.17", + "@deriv/quill-icons": "^1.22.4", + "@deriv-com/ui": "^1.14.1", "@deriv-com/utils": "^0.0.14", "@deriv/react-joyride": "^2.6.2", "class-variance-authority": "^0.7.0", diff --git a/packages/wallets/package.json b/packages/wallets/package.json index 6bff5d0399c4..6411e53e4922 100644 --- a/packages/wallets/package.json +++ b/packages/wallets/package.json @@ -16,7 +16,7 @@ "@deriv-com/utils": "^0.0.14", "@deriv/api-v2": "^1.0.0", "@deriv/integration": "^1.0.0", - "@deriv/quill-icons": "^1.21.1", + "@deriv/quill-icons": "^1.22.4", "@deriv/react-joyride": "^2.6.2", "@deriv/utils": "^1.0.0", "@tanstack/react-table": "^8.10.3",