From dea2e541bfba83374a9b5228508f60f43b360014 Mon Sep 17 00:00:00 2001 From: Jim Daniels Wasswa <104334373+jim-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:31:55 +0800 Subject: [PATCH 01/20] Jim/74386/bot-web-ui-ts-config-fix (#6354) * refactor: update tsconfigurations for bot-web-ui * fix: resolve typescript error by disabling ts-check --- packages/bot-web-ui/globals.d.ts | 5 ----- packages/bot-web-ui/src/components/chart/chart.tsx | 3 +++ packages/bot-web-ui/tsconfig.json | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 packages/bot-web-ui/globals.d.ts diff --git a/packages/bot-web-ui/globals.d.ts b/packages/bot-web-ui/globals.d.ts deleted file mode 100644 index bdef84478fe3..000000000000 --- a/packages/bot-web-ui/globals.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module '@deriv/components'; -declare module '@deriv/shared'; -declare module '@deriv/bot-skeleton'; -declare module '@deriv/translations'; -declare module '@deriv/deriv-charts'; diff --git a/packages/bot-web-ui/src/components/chart/chart.tsx b/packages/bot-web-ui/src/components/chart/chart.tsx index f01dccdad19f..3274174c01b3 100644 --- a/packages/bot-web-ui/src/components/chart/chart.tsx +++ b/packages/bot-web-ui/src/components/chart/chart.tsx @@ -1,4 +1,7 @@ import React from 'react'; +// TODO Remove this after smartcharts is replaced +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import { ChartTitle, SmartChart } from '@deriv/deriv-charts'; import RootStore from 'Stores/index'; import { connect } from 'Stores/connect'; diff --git a/packages/bot-web-ui/tsconfig.json b/packages/bot-web-ui/tsconfig.json index 4f6c4d95ceb8..32b93c8fc701 100644 --- a/packages/bot-web-ui/tsconfig.json +++ b/packages/bot-web-ui/tsconfig.json @@ -2,14 +2,14 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": "./dist", - "rootDir": "./src", "baseUrl": "./", "paths": { "Components/*": ["src/components/*"], "Constants/*": ["src/constants/*"], "Stores/*": ["src/stores/*"], - "Utils/*": ["src/utils/*"] + "Utils/*": ["src/utils/*"], + "@deriv/*": ["../*/src"] } }, - "include": ["./src", "./src/**/*.ts", "./src/**/*.tsx", "globals.d.ts"] + "include": ["src"] } From 02378064bd0d6002a122c9a51e82304fcb3668e9 Mon Sep 17 00:00:00 2001 From: Farzin Mirzaie <72082844+farzin-fs@users.noreply.github.com> Date: Wed, 19 Oct 2022 13:04:32 +0330 Subject: [PATCH 02/20] Farzin/78410/Replace `connect` method with `useStore` hook for components related to `Deposit` (#6746) * refactor(cashier): :fire: replace `connect` method with `useStore` hook in `deposit` * fix(cashier): :white_check_mark: fix failing test due to `StoreProvider` not being provided * Trigger Build --- .../pages/deposit/__tests__/deposit.spec.tsx | 452 ++++++++++++++++-- .../__tests__/crypto-deposit.spec.tsx | 207 ++++++-- .../deposit/crypto-deposit/crypto-deposit.tsx | 43 +- .../__tests__/deposit-locked.spec.tsx | 177 +++---- .../deposit/deposit-locked/deposit-locked.tsx | 45 +- .../cashier/src/pages/deposit/deposit.tsx | 132 ++--- 6 files changed, 748 insertions(+), 308 deletions(-) diff --git a/packages/cashier/src/pages/deposit/__tests__/deposit.spec.tsx b/packages/cashier/src/pages/deposit/__tests__/deposit.spec.tsx index e11e19aa9e20..966ccd55b208 100644 --- a/packages/cashier/src/pages/deposit/__tests__/deposit.spec.tsx +++ b/packages/cashier/src/pages/deposit/__tests__/deposit.spec.tsx @@ -1,12 +1,9 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import Deposit from '../deposit'; +import { StoreProvider } from '../../../hooks'; +import { TRootStore, DeepPartial } from '../../../types'; -jest.mock('Stores/connect.js', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => Component, -})); jest.mock('@deriv/components', () => ({ ...jest.requireActual('@deriv/components'), Loading: () =>
Loading
, @@ -49,102 +46,475 @@ jest.mock('../deposit-locked', () => { }); describe('', () => { - const props = { - currency: 'USD', - current_currency_type: 'fiat', - error: { is_ask_uk_funds_protection: false, message: '' }, - is_cashier_locked: false, - is_crypto_transactions_visible: false, - is_deposit: false, - is_deposit_locked: false, - is_eu: false, - is_loading: false, - is_switching: false, - is_system_maintenance: false, - is_virtual: false, - onMount: jest.fn(), - recentTransactionOnMount: jest.fn(), - setActiveTab: jest.fn(), - setIsDeposit: jest.fn(), - setErrorMessage: jest.fn(), - setSideNotes: jest.fn(), - }; - it('should render component', () => { - const { rerender } = render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: true, + is_virtual: false, + }, + modules: { + cashier: { + iframe: { + iframe_url: '', + }, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + const { rerender } = render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('Loading')).toBeInTheDocument(); - rerender(); + rerender(); expect(screen.getByText('Loading')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: true, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('Virtual')).toBeInTheDocument(); }); it('should render component', () => { - const { rerender } = render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: true, + is_deposit: false, + is_loading: false, + is_system_maintenance: true, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + const { rerender } = render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('CashierLocked')).toBeInTheDocument(); - rerender(); + rerender( + + ); expect(screen.getByText('CashierLocked')).toBeInTheDocument(); - rerender(); + rerender(); expect(screen.getByText('CashierLocked')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: true, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('FundsProtection')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: true, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('DepositLocked')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: true, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('CryptoTransactionsHistory')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: 'error', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: true, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('Error')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: true, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_crypto: true, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('CryptoDeposit')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: true, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('Real')).toBeInTheDocument(); }); it('should render component', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'USD', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_deposit: false, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('CashierOnboarding')).toBeInTheDocument(); }); it('should trigger "setSideNotes" callback', () => { - render(); + const mockRootStore: DeepPartial = { + client: { + currency: 'UST', + can_change_fiat_currency: false, + current_currency_type: 'fiat', + is_eu: false, + is_switching: false, + is_virtual: false, + }, + modules: { + cashier: { + iframe: {}, + transaction_history: { + crypto_transactions: [{}], + is_crypto_transactions_visible: false, + onMount: jest.fn(), + }, + deposit: { + error: { is_ask_uk_funds_protection: false, message: '', setErrorMessage: jest.fn() }, + is_deposit_locked: false, + onMountDeposit: jest.fn(), + }, + general_store: { + is_cashier_locked: false, + is_crypto: true, + is_deposit: true, + is_loading: false, + is_system_maintenance: false, + setActiveTab: jest.fn(), + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + const setSideNotes = jest.fn(); + + render(, { + wrapper: ({ children }) => {children}, + }); - expect(props.setSideNotes).toHaveBeenCalledTimes(2); + expect(setSideNotes).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/cashier/src/pages/deposit/crypto-deposit/__tests__/crypto-deposit.spec.tsx b/packages/cashier/src/pages/deposit/crypto-deposit/__tests__/crypto-deposit.spec.tsx index dc642c1ef529..5275ec119998 100644 --- a/packages/cashier/src/pages/deposit/crypto-deposit/__tests__/crypto-deposit.spec.tsx +++ b/packages/cashier/src/pages/deposit/crypto-deposit/__tests__/crypto-deposit.spec.tsx @@ -4,12 +4,8 @@ import CryptoDeposit from '../crypto-deposit'; import { createBrowserHistory } from 'history'; import { Router } from 'react-router'; import { getCurrencyName, isMobile } from '@deriv/shared'; - -jest.mock('Stores/connect.js', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => Component, -})); +import { StoreProvider } from '../../../../hooks'; +import { TRootStore, DeepPartial } from '../../../../types'; jest.mock('@deriv/components', () => ({ ...jest.requireActual('@deriv/components'), @@ -33,30 +29,67 @@ jest.mock('Components/recent-transaction', () => { describe('', () => { let history; - const renderWithRouter = component => { + const renderWithRouter = (component, mockRootStore) => { history = createBrowserHistory(); - return render({component}); - }; - - const props = { - api_error: '', - crypto_transactions: [{}], - currency: 'BTC', - deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', - is_deposit_address_loading: false, - pollApiForDepositAddress: jest.fn(), - recentTransactionOnMount: jest.fn(), - setIsDeposit: jest.fn(), + return render({component}, { + wrapper: ({ children }) => {children}, + }); }; it('should show loader', () => { - renderWithRouter(); + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: true, + api_error: '', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + renderWithRouter(, mockRootStore); expect(screen.getByText('Loading')).toBeInTheDocument(); }); it('should show proper error message and button', () => { - renderWithRouter(); + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: 'api_error', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + renderWithRouter(, mockRootStore); expect( screen.getByText( @@ -67,17 +100,63 @@ describe('', () => { }); it('should trigger onClick callback when the user clicks "Refresh" button', () => { - renderWithRouter(); + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: 'api_error', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + renderWithRouter(, mockRootStore); const refresh_btn = screen.getByRole('button', { name: 'Refresh' }); fireEvent.click(refresh_btn); - expect(props.pollApiForDepositAddress).toHaveBeenCalledTimes(2); + expect(mockRootStore.modules!.cashier!.onramp!.pollApiForDepositAddress).toHaveBeenCalledTimes(2); }); it('should show proper messages for BTC cryptocurrency', () => { + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: '', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + (getCurrencyName as jest.Mock).mockReturnValueOnce('Bitcoin'); - renderWithRouter(); + renderWithRouter(, mockRootStore); expect(screen.getByText('Send only Bitcoin (BTC) to this address.')).toBeInTheDocument(); expect( @@ -93,8 +172,31 @@ describe('', () => { }); it('should show proper messages for ETH cryptocurrency', () => { + const mockRootStore: DeepPartial = { + client: { + currency: 'ETH', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: '', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + (getCurrencyName as jest.Mock).mockReturnValueOnce('Ethereum'); - renderWithRouter(); + renderWithRouter(, mockRootStore); expect(screen.getByText('Send only Ethereum (ETH) to this address.')).toBeInTheDocument(); expect( @@ -105,11 +207,34 @@ describe('', () => { it('should show proper messages for selected options for ETH, USDC, eUSDT cryptocurrency', () => { const checkMessagesForOptions = (currency, token) => { - const { rerender, unmount } = renderWithRouter(); + const mockRootStore: DeepPartial = { + client: { + currency, + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: '', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + + const { rerender, unmount } = renderWithRouter(, mockRootStore); const rerenderAndOpenDropdownOptions = () => { rerender( - + ); const dropdown_display = screen.getByTestId('dti_dropdown_display'); @@ -208,11 +333,35 @@ describe('', () => { }); it('should show "RecentTransactions" in Mobile mode', () => { + const mockRootStore: DeepPartial = { + client: { + currency: 'BTC', + }, + modules: { + cashier: { + onramp: { + is_deposit_address_loading: false, + api_error: '', + deposit_address: 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt', + pollApiForDepositAddress: jest.fn(), + }, + transaction_history: { + crypto_transactions: [{}], + onMount: jest.fn(), + }, + general_store: { + setIsDeposit: jest.fn(), + }, + }, + }, + }; + (isMobile as jest.Mock).mockReturnValue(true); render( - - + + , + { wrapper: ({ children }) => {children} } ); expect(screen.getByText('RecentTransactions')).toBeInTheDocument(); diff --git a/packages/cashier/src/pages/deposit/crypto-deposit/crypto-deposit.tsx b/packages/cashier/src/pages/deposit/crypto-deposit/crypto-deposit.tsx index c68409f93ddc..1e6b0c4494a9 100644 --- a/packages/cashier/src/pages/deposit/crypto-deposit/crypto-deposit.tsx +++ b/packages/cashier/src/pages/deposit/crypto-deposit/crypto-deposit.tsx @@ -3,32 +3,20 @@ import { Button, ButtonLink, Clipboard, Dropdown, Icon, Loading, Text } from '@d import { localize, Localize } from '@deriv/translations'; import { CryptoConfig, getCurrencyName, isCryptocurrency, isMobile } from '@deriv/shared'; import QRCode from 'qrcode.react'; -import { connect } from 'Stores/connect'; -import { TRootStore, TClientStore, TCryptoTransactionDetails } from 'Types'; +import { observer } from 'mobx-react-lite'; import RecentTransaction from 'Components/recent-transaction'; +import { useStore } from '../../../hooks'; import './crypto-deposit.scss'; -type TCryptoDeposit = { - api_error: string; - crypto_transactions: Array; - currency: TClientStore['currency']; - deposit_address: string; - is_deposit_address_loading: boolean; - recentTransactionOnMount: () => void; - pollApiForDepositAddress: (poll: boolean) => void; - setIsDeposit: (is_deposit: boolean) => void; -}; +const CryptoDeposit = () => { + const { client, modules } = useStore(); + const { cashier } = modules; + const { currency } = client; + const { onramp, transaction_history, general_store } = cashier; + const { api_error, deposit_address, is_deposit_address_loading, pollApiForDepositAddress } = onramp; + const { crypto_transactions, onMount: recentTransactionOnMount } = transaction_history; + const { setIsDeposit } = general_store; -const CryptoDeposit = ({ - api_error, - currency, - crypto_transactions, - deposit_address, - is_deposit_address_loading, - recentTransactionOnMount, - pollApiForDepositAddress, - setIsDeposit, -}: TCryptoDeposit) => { React.useEffect(() => { recentTransactionOnMount(); }, [recentTransactionOnMount]); @@ -256,13 +244,4 @@ const CryptoDeposit = ({ ); }; -export default connect(({ modules, client }: TRootStore) => ({ - api_error: modules.cashier.onramp.api_error, - crypto_transactions: modules.cashier.transaction_history.crypto_transactions, - currency: client.currency, - deposit_address: modules.cashier.onramp.deposit_address, - is_deposit_address_loading: modules.cashier.onramp.is_deposit_address_loading, - recentTransactionOnMount: modules.cashier.transaction_history.onMount, - pollApiForDepositAddress: modules.cashier.onramp.pollApiForDepositAddress, - setIsDeposit: modules.cashier.general_store.setIsDeposit, -}))(CryptoDeposit); +export default observer(CryptoDeposit); diff --git a/packages/cashier/src/pages/deposit/deposit-locked/__tests__/deposit-locked.spec.tsx b/packages/cashier/src/pages/deposit/deposit-locked/__tests__/deposit-locked.spec.tsx index 5950e449e525..968af0c1db09 100644 --- a/packages/cashier/src/pages/deposit/deposit-locked/__tests__/deposit-locked.spec.tsx +++ b/packages/cashier/src/pages/deposit/deposit-locked/__tests__/deposit-locked.spec.tsx @@ -2,98 +2,106 @@ import React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { Checklist } from '@deriv/components'; import DepositLocked from '../deposit-locked'; +import { StoreProvider } from '../../../../hooks'; +import { TRootStore, DeepPartial } from '../../../../types'; -jest.mock('Stores/connect', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => Component, -})); +jest.mock('Components/cashier-locked', () => { + const CashierLocked = () => ( +
+
+ We were unable to verify your information automatically. To enable this function, you must complete the + following: +
+
Complete the financial assessment form
+
+ ); + return CashierLocked; +}); describe('', () => { - const onMount = jest.fn(); - const standpoint = { - iom: false, - }; - const account_status = { - authentication: { - identity: { - status: '', - }, - document: { - status: '', - }, - needs_verification: [], - }, - }; - it('should show the proof of identity document verification message', () => { - const poi_account_status = { - authentication: { - identity: { - status: 'pending', + const mockRootStore: DeepPartial = { + client: { + account_status: { + cashier_validation: [], + authentication: { + identity: { + status: 'pending', + }, + document: { + status: 'none', + }, + needs_verification: ['identity'], + }, }, - document: { - status: 'none', - }, - needs_verification: ['identity'], + standpoint: { iom: undefined }, + is_tnc_needed: false, + is_financial_information_incomplete: false, + is_trading_experience_incomplete: false, + is_financial_account: false, }, + modules: { cashier: { deposit: { onMountDeposit: jest.fn() } } }, }; - render( - - ); + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('To enable this feature you must complete the following:')).toBeInTheDocument(); expect(screen.getByText('Check proof of identity document verification status')).toBeInTheDocument(); }); it('should show the proof of address document verification message', () => { - const poa_account_status = { - authentication: { - identity: { - status: 'none', + const mockRootStore: DeepPartial = { + client: { + account_status: { + cashier_validation: [], + authentication: { + identity: { + status: 'none', + }, + document: { + status: 'pending', + }, + needs_verification: ['document'], + }, }, - document: { - status: 'pending', - }, - needs_verification: ['document'], + standpoint: { iom: undefined }, + is_tnc_needed: false, + is_financial_information_incomplete: false, + is_trading_experience_incomplete: false, + is_financial_account: false, }, + modules: { cashier: { deposit: { onMountDeposit: jest.fn() } } }, }; - render( - - ); + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('To enable this feature you must complete the following:')).toBeInTheDocument(); expect(screen.getByText('Check proof of address document verification status')).toBeInTheDocument(); }); it('should show the terms and conditions accept button', () => { - render( - - ); + const mockRootStore: DeepPartial = { + client: { + account_status: { + cashier_validation: [], + authentication: {}, + }, + standpoint: { iom: undefined }, + is_tnc_needed: true, + is_financial_information_incomplete: false, + is_trading_experience_incomplete: false, + is_financial_account: false, + }, + modules: { cashier: { deposit: { onMountDeposit: jest.fn() } } }, + }; + + render(, { + wrapper: ({ children }) => {children}, + }); expect(screen.getByText('To enable this feature you must complete the following:')).toBeInTheDocument(); expect( @@ -104,19 +112,24 @@ describe('', () => { }); it('should show the financial assessment completion message', () => { - standpoint.iom = true; + const mockRootStore: DeepPartial = { + client: { + account_status: { + cashier_validation: [], + authentication: {}, + }, + standpoint: { iom: 'true' }, + is_tnc_needed: false, + is_financial_information_incomplete: true, + is_trading_experience_incomplete: false, + is_financial_account: false, + }, + modules: { cashier: { deposit: { onMountDeposit: jest.fn() } } }, + }; - render( - - ); + render(, { + wrapper: ({ children }) => {children}, + }); expect( screen.getByText( diff --git a/packages/cashier/src/pages/deposit/deposit-locked/deposit-locked.tsx b/packages/cashier/src/pages/deposit/deposit-locked/deposit-locked.tsx index 9c288b8c1cb7..65571ffa8628 100644 --- a/packages/cashier/src/pages/deposit/deposit-locked/deposit-locked.tsx +++ b/packages/cashier/src/pages/deposit/deposit-locked/deposit-locked.tsx @@ -3,29 +3,24 @@ import { useHistory } from 'react-router-dom'; import { routes, WS } from '@deriv/shared'; import { Icon, Checklist, StaticUrl, Text } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; -import { TRootStore, TClientStore } from 'Types'; +import { observer } from 'mobx-react-lite'; import CashierLocked from 'Components/cashier-locked'; +import { useStore } from '../../../hooks'; -type TDepositLocked = { - account_status: TClientStore['account_status']; - is_financial_account: TClientStore['is_financial_account']; - is_financial_information_incomplete: TClientStore['is_financial_information_incomplete']; - is_tnc_needed: TClientStore['is_tnc_needed']; - is_trading_experience_incomplete: TClientStore['is_trading_experience_incomplete']; - onMount: () => void; - standpoint: TClientStore['standpoint']; -}; +const DepositLocked = () => { + const { client, modules } = useStore(); + const { + account_status, + is_financial_account, + is_financial_information_incomplete, + is_tnc_needed, + is_trading_experience_incomplete, + standpoint, + } = client; + const { cashier } = modules; + const { deposit } = cashier; + const { onMountDeposit: onMount } = deposit; -const DepositLocked = ({ - account_status, - is_financial_account, - is_financial_information_incomplete, - is_tnc_needed, - is_trading_experience_incomplete, - onMount, - standpoint, -}: TDepositLocked) => { // handle authentication locked const identity = account_status?.authentication?.identity; const document = account_status?.authentication?.document; @@ -114,12 +109,4 @@ const DepositLocked = ({ ); }; -export default connect(({ client, modules }: TRootStore) => ({ - account_status: client.account_status, - is_financial_account: client.is_financial_account, - is_financial_information_incomplete: client.is_financial_information_incomplete, - is_tnc_needed: client.is_tnc_needed, - is_trading_experience_incomplete: client.is_trading_experience_incomplete, - onMount: modules.cashier.deposit.onMountDeposit, - standpoint: client.standpoint, -}))(DepositLocked); +export default observer(DepositLocked); diff --git a/packages/cashier/src/pages/deposit/deposit.tsx b/packages/cashier/src/pages/deposit/deposit.tsx index aec5877593c3..35f14ccdc468 100644 --- a/packages/cashier/src/pages/deposit/deposit.tsx +++ b/packages/cashier/src/pages/deposit/deposit.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Loading } from '@deriv/components'; -import { connect } from 'Stores/connect'; -import { TRootStore, TClientStore } from 'Types'; +import { observer } from 'mobx-react-lite'; import { Real, Virtual } from 'Components/cashier-container'; import { CashierOnboarding, CashierOnboardingSideNote } from 'Components/cashier-onboarding'; import CashierLocked from 'Components/cashier-locked'; @@ -13,72 +12,44 @@ import RecentTransaction from 'Components/recent-transaction'; import CryptoDeposit from './crypto-deposit'; import DepositLocked from './deposit-locked'; import SideNote from 'Components/side-note'; +import { useStore } from '../../hooks'; type TDeposit = { - can_change_fiat_currency: TClientStore['can_change_fiat_currency']; - container: string; - crypto_transactions: Array; - currency: TClientStore['currency']; - current_currency_type: TClientStore['current_currency_type']; - clearIframe: () => void; - error: { - is_ask_uk_funds_protection?: boolean; - message?: string; - }; - iframe_height: number | string; - iframe_url: string; - is_cashier_locked: boolean; - is_cashier_onboarding: boolean; - is_crypto_transactions_visible: boolean; - is_crypto: boolean; - is_deposit_locked: boolean; - is_deposit: boolean; - is_eu: TClientStore['is_eu']; - is_loading: boolean; - is_switching: TClientStore['is_switching']; - is_system_maintenance: boolean; - is_virtual: TClientStore['is_virtual']; - landing_company_shortcode: TClientStore['landing_company_shortcode']; - onMount: () => void; - recentTransactionOnMount: () => void; - setActiveTab: (container: string) => void; - setErrorMessage: (error: string) => void; - setIsDeposit: (isDeposit: boolean) => void; setSideNotes: (notes: object | null) => void; - standpoint: TClientStore['standpoint']; - tab_index: number; }; -const Deposit = ({ - can_change_fiat_currency, - crypto_transactions, - container, - currency, - current_currency_type, - error, - is_cashier_locked, - is_cashier_onboarding, - is_crypto, - is_crypto_transactions_visible, - is_deposit, - is_deposit_locked, - is_eu, - iframe_height, - iframe_url, - clearIframe, - is_loading, - is_switching, - is_system_maintenance, - is_virtual, - landing_company_shortcode, - onMount, - recentTransactionOnMount, - setActiveTab, - setErrorMessage, - setIsDeposit, - setSideNotes, - tab_index, -}: TDeposit) => { +const Deposit = ({ setSideNotes }: TDeposit) => { + const { client, modules } = useStore(); + const { + can_change_fiat_currency, + currency, + current_currency_type, + is_eu, + is_switching, + is_virtual, + landing_company_shortcode, + } = client; + const { cashier } = modules; + const { iframe, deposit, transaction_history, general_store } = cashier; + const { clearIframe, iframe_height, iframe_url } = iframe; + const { container, error, is_deposit_locked, onMountDeposit: onMount } = deposit; + const { + crypto_transactions, + is_crypto_transactions_visible, + onMount: recentTransactionOnMount, + } = transaction_history; + const { + is_cashier_locked, + is_cashier_onboarding, + is_crypto, + is_deposit, + is_loading, + is_system_maintenance, + setActiveTab, + setIsDeposit, + cashier_route_tab_index: tab_index, + } = general_store; + const is_fiat_currency_banner_visible_for_MF_clients = landing_company_shortcode === 'maltainvest' && !is_crypto && !can_change_fiat_currency && !!iframe_height; React.useEffect(() => { @@ -93,10 +64,10 @@ const Deposit = ({ onMount(); return () => { setIsDeposit(false); - setErrorMessage(''); + error.setErrorMessage({ code: '', message: '' }); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [setActiveTab, onMount, container, setErrorMessage]); + }, [setActiveTab, onMount, container, error.setErrorMessage]); React.useEffect(() => { if (typeof setSideNotes === 'function') { if (is_switching || is_deposit) setSideNotes(null); @@ -172,33 +143,4 @@ const Deposit = ({ return ; }; -export default connect(({ client, modules }: TRootStore) => ({ - can_change_fiat_currency: client.can_change_fiat_currency, - clearIframe: modules.cashier.iframe.clearIframe, - container: modules.cashier.deposit.container, - crypto_transactions: modules.cashier.transaction_history.crypto_transactions, - currency: client.currency, - current_currency_type: client.current_currency_type, - error: modules.cashier.deposit.error, - iframe_height: modules.cashier.iframe.iframe_height, - iframe_url: modules.cashier.iframe.iframe_url, - is_cashier_locked: modules.cashier.general_store.is_cashier_locked, - is_cashier_onboarding: modules.cashier.general_store.is_cashier_onboarding, - is_crypto_transactions_visible: modules.cashier.transaction_history.is_crypto_transactions_visible, - is_crypto: modules.cashier.general_store.is_crypto, - is_deposit_locked: modules.cashier.deposit.is_deposit_locked, - is_deposit: modules.cashier.general_store.is_deposit, - is_eu: client.is_eu, - is_loading: modules.cashier.general_store.is_loading, - is_switching: client.is_switching, - is_system_maintenance: modules.cashier.general_store.is_system_maintenance, - is_virtual: client.is_virtual, - landing_company_shortcode: client.landing_company_shortcode, - onMount: modules.cashier.deposit.onMountDeposit, - recentTransactionOnMount: modules.cashier.transaction_history.onMount, - setActiveTab: modules.cashier.general_store.setActiveTab, - setErrorMessage: modules.cashier.deposit.error.setErrorMessage, - setIsDeposit: modules.cashier.general_store.setIsDeposit, - standpoint: client.standpoint, - tab_index: modules.cashier.general_store.cashier_route_tab_index, -}))(Deposit); +export default observer(Deposit); From 9db323de0a9fabeaf5f9e29d6da679b6ab694ddd Mon Sep 17 00:00:00 2001 From: Farzin Mirzaie <72082844+farzin-fs@users.noreply.github.com> Date: Wed, 19 Oct 2022 13:05:04 +0330 Subject: [PATCH 03/20] fix(components): :lipstick: fix `Timeline` item alignment issue (#6682) --- .../p2p/src/components/advertiser-page/advertiser-page.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page.scss b/packages/p2p/src/components/advertiser-page/advertiser-page.scss index c82a07c5c9db..262673c0da55 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page.scss +++ b/packages/p2p/src/components/advertiser-page/advertiser-page.scss @@ -101,7 +101,7 @@ height: fit-content; width: fit-content; - > span { + > span { padding-right: 0.8rem; } From f921df53bf1e15bdf0de0c1bf1687f2dcb4e4b92 Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 13:36:01 +0400 Subject: [PATCH 04/20] refactor: :arrow_up: upgraded depenedency that caused build failure (#6656) --- packages/account/.eslintrc.js | 5 ++++- packages/account/build/constants.js | 1 + packages/account/build/global.d.ts | 1 + packages/account/package.json | 1 + packages/account/src/Types/common-prop.type.ts | 11 +++++++++++ packages/account/src/Types/context.type.ts | 18 ++++++++++++++++++ packages/account/src/Types/index.ts | 2 ++ packages/account/tsconfig.json | 3 ++- 8 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 packages/account/build/global.d.ts create mode 100644 packages/account/src/Types/common-prop.type.ts create mode 100644 packages/account/src/Types/context.type.ts create mode 100644 packages/account/src/Types/index.ts diff --git a/packages/account/.eslintrc.js b/packages/account/.eslintrc.js index b5fe2450213a..8842b63e58a1 100644 --- a/packages/account/.eslintrc.js +++ b/packages/account/.eslintrc.js @@ -7,4 +7,7 @@ module.exports = { webpack: { config: webpackConfig({}) }, }, }, -}; \ No newline at end of file + rules: { + 'import/no-extraneous-dependencies': ['off', { devDependencies: ['**/*.spec.*'] }], + }, +}; diff --git a/packages/account/build/constants.js b/packages/account/build/constants.js index 807b4047aa10..77d6e833d2bb 100644 --- a/packages/account/build/constants.js +++ b/packages/account/build/constants.js @@ -31,6 +31,7 @@ const ALIASES = { Services: path.resolve(__dirname, '../src/Services'), Stores: path.resolve(__dirname, '../src/Stores'), Styles: path.resolve(__dirname, '../src/Styles'), + Types: path.resolve(__dirname, '../src/Types'), }; const rules = (is_test_env = false, is_mocha_only = false) => [ diff --git a/packages/account/build/global.d.ts b/packages/account/build/global.d.ts new file mode 100644 index 000000000000..5ac902685ee5 --- /dev/null +++ b/packages/account/build/global.d.ts @@ -0,0 +1 @@ +declare module '@binary-com/binary-document-uploader'; diff --git a/packages/account/package.json b/packages/account/package.json index b27fb7d140ce..71ef3c50956a 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -28,6 +28,7 @@ }, "dependencies": { "@binary-com/binary-document-uploader": "^2.4.7", + "@deriv/api-types": "^1.0.54", "@deriv/components": "^1.0.0", "@deriv/shared": "^1.0.0", "@deriv/translations": "^1.0.0", diff --git a/packages/account/src/Types/common-prop.type.ts b/packages/account/src/Types/common-prop.type.ts new file mode 100644 index 000000000000..3c4592d190d0 --- /dev/null +++ b/packages/account/src/Types/common-prop.type.ts @@ -0,0 +1,11 @@ +export type TFormValidation = { + warnings: { [key: string]: string }; + errors: { [key: string]: string }; +}; + +export type TToken = { + display_name: string; + last_used: string; + scopes: string[]; + token: string; +}; diff --git a/packages/account/src/Types/context.type.ts b/packages/account/src/Types/context.type.ts new file mode 100644 index 000000000000..8edbccc6eca8 --- /dev/null +++ b/packages/account/src/Types/context.type.ts @@ -0,0 +1,18 @@ +import { TToken } from './common-prop.type'; + +export type TPlatformContext = { + is_appstore: boolean; + displayName: string; +}; + +export type TApiContext = { + api_tokens: NonNullable | undefined; + deleteToken: (token: string) => Promise; + footer_ref: Element | DocumentFragment | undefined; + overlay_ref: + | ((...args: unknown[]) => unknown) + | import('prop-types').InferProps<{ + current: import('prop-types').Requireable; + }>; + toggleOverlay: () => void; +}; diff --git a/packages/account/src/Types/index.ts b/packages/account/src/Types/index.ts new file mode 100644 index 000000000000..07ac06fc0417 --- /dev/null +++ b/packages/account/src/Types/index.ts @@ -0,0 +1,2 @@ +export * from './common-prop.type'; +export * from './context.type'; diff --git a/packages/account/tsconfig.json b/packages/account/tsconfig.json index 182c1c0c7d40..1a92d82ee4aa 100644 --- a/packages/account/tsconfig.json +++ b/packages/account/tsconfig.json @@ -15,8 +15,9 @@ "Sections/*": ["src/Sections/*"], "Stores/*": ["src/Stores/*"], "Styles/*": ["src/Styles/*"], + "Types": ["src/Types"], "@deriv/*": ["../*/src"] } }, - "include": ["src"] + "include": ["src","globals.d.ts"] } From 4607906ed0a27944af9bf27565ff9e8a14549070 Mon Sep 17 00:00:00 2001 From: thisyahlen <104053934+thisyahlen-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:36:28 +0800 Subject: [PATCH 05/20] thisyahlen/create new account text align in button (#6684) * create new account text align in button * removed classname --- .../password-selection-modal.jsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/core/src/App/Containers/PasswordSelectionModal/password-selection-modal.jsx b/packages/core/src/App/Containers/PasswordSelectionModal/password-selection-modal.jsx index d94942366a32..46bec0bc098a 100644 --- a/packages/core/src/App/Containers/PasswordSelectionModal/password-selection-modal.jsx +++ b/packages/core/src/App/Containers/PasswordSelectionModal/password-selection-modal.jsx @@ -76,13 +76,15 @@ const PasswordSelectionModal = ({ type='button' onClick={() => isModalVisible(false)} /> - + + ); +}; + +describe('useSubscription', () => { + test('should subscribe to p2p_order_info and get the order updates', async () => { + mockUseWSShared.mockReturnValue({ + subscribe: jest.fn(() => { + return { + subscribe: async (onData, onError) => { + const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + + await delay(500); + + onData({ p2p_order_info: { status: 'pending' } }); + + await delay(500); + + onData({ p2p_order_info: { status: 'buyer-confirmed' } }); + + await delay(500); + + onData({ p2p_order_info: { status: 'disputed' } }); + + await delay(500); + + onError({ error: { code: 'Foo', message: 'Error message' } }); + + await delay(500); + + onData({ p2p_order_info: { status: 'completed' } }); + + return { unsubscribe: () => Promise.resolve() }; + }, + }; + }), + }); + + render(); + + const is_loading = screen.getByTestId('dt_is_loading'); + const error = screen.getByTestId('dt_error'); + const data = screen.getByTestId('dt_data'); + const subscribe = screen.getByTestId('dt_subscribe'); + + expect(is_loading).toHaveTextContent('false'); + expect(error).toHaveTextContent('undefined'); + expect(data).toHaveTextContent('undefined'); + userEvent.click(subscribe); + await waitFor(() => expect(data).toHaveTextContent('{"status":"pending"}')); + await waitFor(() => expect(data).toHaveTextContent('{"status":"buyer-confirmed"}')); + await waitFor(() => expect(data).toHaveTextContent('{"status":"disputed"}')); + await waitFor(() => expect(error).toHaveTextContent('{"code":"Foo","message":"Error message"}')); + await waitFor(() => expect(data).toHaveTextContent('{"status":"completed"}')); + }); +}); diff --git a/packages/cashier/src/hooks/__tests__/useWS.test.tsx b/packages/cashier/src/hooks/__tests__/useWS.spec.tsx similarity index 64% rename from packages/cashier/src/hooks/__tests__/useWS.test.tsx rename to packages/cashier/src/hooks/__tests__/useWS.spec.tsx index 3f71b69a7a99..fe6ec1d86138 100644 --- a/packages/cashier/src/hooks/__tests__/useWS.test.tsx +++ b/packages/cashier/src/hooks/__tests__/useWS.spec.tsx @@ -4,7 +4,7 @@ import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { useWS as useWSShared } from '@deriv/shared'; import useWS from '../useWS'; -import { TSocketEndpointNames, TSocketRequestProps } from '../../types'; +import { TSocketEndpointNames, TSocketRequestProps, TSocketResponse } from '../../types'; jest.mock('@deriv/shared'); @@ -46,7 +46,13 @@ describe('useWS', () => { test('should call ping and get pong in response', async () => { mockUseWSShared.mockReturnValue({ - send: jest.fn(() => Promise.resolve({ ping: 'pong' })), + send: jest.fn(() => + Promise.resolve>({ + msg_type: 'ping', + ping: 'pong', + echo_req: {}, + }) + ), }); render(); @@ -68,7 +74,13 @@ describe('useWS', () => { test('should call verify_email and get 1 in response', async () => { mockUseWSShared.mockReturnValue({ - send: jest.fn(() => Promise.resolve({ verify_email: 1 })), + send: jest.fn(() => + Promise.resolve>({ + verify_email: 1, + msg_type: 'verify_email', + echo_req: {}, + }) + ), }); render( @@ -90,5 +102,34 @@ describe('useWS', () => { await waitFor(() => expect(is_loading).toHaveTextContent('false')); }); - // TODO: Add more test cases. + test('should call cashier and get ASK_TNC_APPROVAL error code in response', async () => { + mockUseWSShared.mockReturnValue({ + send: jest.fn(() => + Promise.resolve>({ + msg_type: 'cashier', + echo_req: {}, + error: { + code: 'ASK_TNC_APPROVAL', + message: 'Error message', + }, + }) + ), + }); + + render(); + + const is_loading = screen.getByTestId('dt_is_loading'); + const error = screen.getByTestId('dt_error'); + const data = screen.getByTestId('dt_data'); + const send = screen.getByTestId('dt_send'); + + expect(is_loading).toHaveTextContent('false'); + expect(error).toHaveTextContent('undefined'); + expect(data).toHaveTextContent('undefined'); + userEvent.click(send); + await waitFor(() => expect(is_loading).toHaveTextContent('true')); + await waitFor(() => expect(data).toHaveTextContent('undefined')); + await waitFor(() => expect(error).toHaveTextContent('{"code":"ASK_TNC_APPROVAL","message":"Error message"}')); + await waitFor(() => expect(is_loading).toHaveTextContent('false')); + }); }); diff --git a/packages/cashier/src/hooks/index.ts b/packages/cashier/src/hooks/index.ts index 4ed6c4b7c354..729085c341e8 100644 --- a/packages/cashier/src/hooks/index.ts +++ b/packages/cashier/src/hooks/index.ts @@ -1,4 +1,10 @@ export * from './useStore'; export { default as useCountdown } from './useCountdown'; export { default as useWS } from './useWS'; +export { default as useSubscription } from './useSubscription'; export { default as useVerifyEmail } from './useVerifyEmail'; +export { default as useNeedAuthentication } from './useNeedAuthentication'; +export { default as useNeedFinancialAssessment } from './useNeedFinancialAssessment'; +export { default as useRealSTPAccount } from './useRealSTPAccount'; +export { default as useNeedTNC } from './useNeedTNC'; +export { default as useDepositLocked } from './useDepositLocked'; diff --git a/packages/cashier/src/hooks/useDepositLocked.ts b/packages/cashier/src/hooks/useDepositLocked.ts new file mode 100644 index 000000000000..75282fc17181 --- /dev/null +++ b/packages/cashier/src/hooks/useDepositLocked.ts @@ -0,0 +1,17 @@ +import useNeedAuthentication from './useNeedAuthentication'; +import useNeedFinancialAssessment from './useNeedFinancialAssessment'; +import useNeedTNC from './useNeedTNC'; +import { useStore } from './useStore'; + +const useDepositLocked = () => { + const { client } = useStore(); + const { is_deposit_lock } = client; + const is_need_authentication = useNeedAuthentication(); + const is_need_tnc = useNeedTNC(); + const is_need_financial_assessment = useNeedFinancialAssessment(); + const is_deposit_locked = is_deposit_lock || is_need_authentication || is_need_tnc || is_need_financial_assessment; + + return is_deposit_locked; +}; + +export default useDepositLocked; diff --git a/packages/cashier/src/hooks/useNeedAuthentication.ts b/packages/cashier/src/hooks/useNeedAuthentication.ts new file mode 100644 index 000000000000..43879816774c --- /dev/null +++ b/packages/cashier/src/hooks/useNeedAuthentication.ts @@ -0,0 +1,11 @@ +import { useStore } from './useStore'; + +const useNeedAuthentication = () => { + const { client } = useStore(); + const { is_authentication_needed, is_eu } = client; + const is_need_authentication = is_authentication_needed && is_eu; + + return is_need_authentication; +}; + +export default useNeedAuthentication; diff --git a/packages/cashier/src/hooks/useNeedFinancialAssessment.ts b/packages/cashier/src/hooks/useNeedFinancialAssessment.ts new file mode 100644 index 000000000000..8b88bde779c5 --- /dev/null +++ b/packages/cashier/src/hooks/useNeedFinancialAssessment.ts @@ -0,0 +1,12 @@ +import { useStore } from './useStore'; + +const useNeedFinancialAssessment = () => { + const { client } = useStore(); + const { is_financial_account, is_financial_information_incomplete, is_trading_experience_incomplete } = client; + const is_need_financial_assessment = + is_financial_account && (is_financial_information_incomplete || is_trading_experience_incomplete); + + return is_need_financial_assessment; +}; + +export default useNeedFinancialAssessment; diff --git a/packages/cashier/src/hooks/useNeedTNC.ts b/packages/cashier/src/hooks/useNeedTNC.ts new file mode 100644 index 000000000000..d1a077d0e68f --- /dev/null +++ b/packages/cashier/src/hooks/useNeedTNC.ts @@ -0,0 +1,13 @@ +import useRealSTPAccount from './useRealSTPAccount'; +import { useStore } from './useStore'; + +const useNeedTNC = () => { + const { client } = useStore(); + const { is_eu, is_tnc_needed } = client; + const has_real_stp_account = useRealSTPAccount(); + const is_need_tnc = (is_eu || has_real_stp_account) && is_tnc_needed; + + return is_need_tnc; +}; + +export default useNeedTNC; diff --git a/packages/cashier/src/hooks/useRealSTPAccount.ts b/packages/cashier/src/hooks/useRealSTPAccount.ts new file mode 100644 index 000000000000..3e8ecf88eeb7 --- /dev/null +++ b/packages/cashier/src/hooks/useRealSTPAccount.ts @@ -0,0 +1,13 @@ +import { useStore } from './useStore'; + +const useRealSTPAccount = () => { + const { client } = useStore(); + const { mt5_login_list } = client; + const has_real_stp_account = mt5_login_list.some( + item => item.account_type === 'real' && item.sub_account_type === 'financial_stp' + ); + + return has_real_stp_account; +}; + +export default useRealSTPAccount; diff --git a/packages/cashier/src/hooks/useSubscription.ts b/packages/cashier/src/hooks/useSubscription.ts new file mode 100644 index 000000000000..ac1340add3a3 --- /dev/null +++ b/packages/cashier/src/hooks/useSubscription.ts @@ -0,0 +1,44 @@ +import { TSocketRequestProps, TSocketResponseData, TSocketSubscribableEndpointNames } from 'Types'; +import { useWS as useWSShared } from '@deriv/shared'; +import { useState } from 'react'; + +const useSubscription = (name: T) => { + const [is_loading, setIsLoading] = useState(false); + const [is_subscribed, setSubscribed] = useState(false); + const [error, setError] = useState(); + const [data, setData] = useState>(); + const [subscriber, setSubscriber] = useState<{ unsubscribe?: VoidFunction }>(); + const WS = useWSShared(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onData = (response: any) => { + setData(response[name]); + setIsLoading(false); + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const onError = (response: any) => { + setError(response.error); + setIsLoading(false); + }; + + const subscribe = (...props: TSocketRequestProps extends never ? [undefined?] : [TSocketRequestProps]) => { + setIsLoading(true); + setSubscribed(true); + + try { + setSubscriber(WS.subscribe({ [name]: 1, subscribe: 1, ...(props[0] || {}) }).subscribe(onData, onError)); + } catch (e) { + setError(e); + } + }; + + const unsubscribe = () => { + subscriber?.unsubscribe?.(); + setSubscribed(false); + }; + + return { subscribe, unsubscribe, is_loading, is_subscribed, error, data }; +}; + +export default useSubscription; diff --git a/packages/cashier/src/hooks/useWS.ts b/packages/cashier/src/hooks/useWS.ts index 8a6e36313fe0..39511a999d8d 100644 --- a/packages/cashier/src/hooks/useWS.ts +++ b/packages/cashier/src/hooks/useWS.ts @@ -14,7 +14,7 @@ const useWS = (name: T) => { setIsLoading(true); try { - const response = await WS.send({ [name]: 1, ...props }); + const response = await WS.send({ [name]: 1, ...(props[0] || {}) }); if (response.error) { setError(response.error); diff --git a/packages/cashier/src/types/types.ts b/packages/cashier/src/types/types.ts index 64d39082a20b..5031a516ef7a 100644 --- a/packages/cashier/src/types/types.ts +++ b/packages/cashier/src/types/types.ts @@ -9,6 +9,24 @@ import { P2POrderInformationResponse, ServerStatusRequest, ServerStatusResponse, + TermsAndConditionsApprovalRequest, + TermsAndConditionsApprovalResponse, + CashierInformationRequest, + CashierInformationResponse, + CryptocurrencyConfigurationsRequest, + CryptocurrencyConfigurationsResponse, + PaymentAgentTransferRequest, + PaymentAgentTransferResponse, + PaymentAgentListRequest, + PaymentAgentListResponse, + PaymentAgentDetailsRequest, + PaymentAgentDetailsResponse, + PaymentAgentWithdrawRequest, + PaymentAgentWithdrawResponse, + TransferBetweenAccountsRequest, + TransferBetweenAccountsResponse, + BalanceRequest, + BalanceResponse, } from '@deriv/api-types'; import { KeysMatching } from './utils'; @@ -33,20 +51,61 @@ export type TSocketEndpoints = { request: ServerStatusRequest; response: ServerStatusResponse; }; + tnc_approval: { + request: TermsAndConditionsApprovalRequest; + response: TermsAndConditionsApprovalResponse; + }; + cashier: { + request: CashierInformationRequest; + response: CashierInformationResponse; + }; + crypto_config: { + request: CryptocurrencyConfigurationsRequest; + response: CryptocurrencyConfigurationsResponse; + }; + paymentagent_transfer: { + request: PaymentAgentTransferRequest; + response: PaymentAgentTransferResponse; + }; + paymentagent_list: { + request: PaymentAgentListRequest; + response: PaymentAgentListResponse; + }; + paymentagent_details: { + request: PaymentAgentDetailsRequest; + response: PaymentAgentDetailsResponse; + }; + paymentagent_withdraw: { + request: PaymentAgentWithdrawRequest; + response: PaymentAgentWithdrawResponse; + }; + transfer_between_accounts: { + request: TransferBetweenAccountsRequest; + response: TransferBetweenAccountsResponse; + }; + balance: { + request: BalanceRequest; + response: BalanceResponse; + }; }; export type TSocketEndpointNames = keyof TSocketEndpoints; + export type TSocketSubscribableEndpointNames = | KeysMatching | 'exchange_rates'; + export type TSocketResponse = TSocketEndpoints[T]['response']; + export type TSocketResponseData = TSocketResponse[T]; -export type TSocketResponseSubscriptionInformation = TSocketResponse['subscription']; + export type TSocketRequest = TSocketEndpoints[T]['request']; + type TSocketRequestCleaned = Omit< TSocketRequest, - (T extends KeysMatching, 1> ? T : never) | 'passthrough' | 'req_id' + (T extends KeysMatching, 1> ? T : never) | 'passthrough' | 'req_id' | 'subscribe' >; + export type TSocketRequestProps = TSocketRequestCleaned extends Record ? never : TSocketRequestCleaned; From 76419f2a1c360bfc39da0c03992372648f3ddac6 Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:38:19 +0800 Subject: [PATCH 09/20] Ameerul /Bug 77290 Dialogue box looks small in responsive view (#6633) * added width to error-modal and removed small prop * added ic-blocked-advertisers-barred icon --- .../p2p/src/components/advertiser-page/advertiser-page.jsx | 2 +- packages/p2p/src/components/error-modal/error-modal.jsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page.jsx b/packages/p2p/src/components/advertiser-page/advertiser-page.jsx index ebda18c26d13..26b41928a42e 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page.jsx +++ b/packages/p2p/src/components/advertiser-page/advertiser-page.jsx @@ -88,7 +88,7 @@ const AdvertiserPage = () => { advertiser_page_store.onCancel(); general_store.setBlockUnblockUserError(''); }} - small + width={isMobile() ? '90rem' : '40rem'} /> { return ( {error_message} @@ -37,7 +37,7 @@ ErrorModal.propTypes = { has_close_icon: PropTypes.bool, is_error_modal_open: PropTypes.bool, setIsErrorModalOpen: PropTypes.func, - small: PropTypes.bool, + width: PropTypes.string, }; export default observer(ErrorModal); From 1f30692e812c5f13795fa734bc1cde04805d059b Mon Sep 17 00:00:00 2001 From: Jim Daniels Wasswa <104334373+jim-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:38:45 +0800 Subject: [PATCH 10/20] chore: remove unnecessary appcard, virtualwalletcard and realwalletcard components (#6546) --- .../app-card-items/app-card-action-item.jsx | 36 -- .../app-card-items/app-card-actions.jsx | 76 ----- .../app-card/app-card-items/app-card-body.jsx | 133 -------- .../app-card-items/app-card-footer-item.jsx | 25 -- .../app-card-items/app-card-footer.jsx | 29 -- .../app-card-items/app-card-header.jsx | 51 --- .../real-app-card-background.jsx | 33 -- .../src/components/app-card/app-card.jsx | 120 ------- .../src/components/app-card/app-card.scss | 307 ------------------ .../src/components/app-card/index.js | 4 - .../src/components/real-wallet-card/index.js | 4 - .../real-wallet-card-content.jsx | 31 -- .../real-wallet-card-footer-actions.jsx | 132 -------- .../real-wallet-card-footer.jsx | 75 ----- .../real-wallet-card-header.jsx | 47 --- .../real-wallet-card/real-wallet-card.jsx | 118 ------- .../real-wallet-card/real-wallet-card.scss | 104 ------ .../components/virtual-wallet-card/index.js | 4 - .../virtual-wallet-card-content.jsx | 31 -- .../virtual-wallet-card-footer-actions.jsx | 59 ---- .../virtual-wallet-card-footer.jsx | 53 --- .../virtual-wallet-card-header.jsx | 12 - .../virtual-wallet-card.jsx | 87 ----- .../virtual-wallet-card.scss | 67 ---- packages/components/src/index.js | 3 - .../components/stories/app-card/README.md | 107 ------ .../stories/app-card/app-card.stories.js | 62 ---- .../stories/app-card/statics/labels.js | 13 - .../stories/real-wallet-card/README.md | 79 ----- .../real-wallet-card.stories.js | 55 ---- .../stories/real-wallet-card/wallet-labels.js | 11 - .../stories/virtual-wallet-card/README.md | 61 ---- .../virtual-wallet-card.stories.js | 41 --- 33 files changed, 2070 deletions(-) delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-action-item.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-actions.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-body.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-footer-item.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-footer.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/app-card-header.jsx delete mode 100644 packages/components/src/components/app-card/app-card-items/real-app-card-background.jsx delete mode 100644 packages/components/src/components/app-card/app-card.jsx delete mode 100644 packages/components/src/components/app-card/app-card.scss delete mode 100644 packages/components/src/components/app-card/index.js delete mode 100644 packages/components/src/components/real-wallet-card/index.js delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card-content.jsx delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card-footer-actions.jsx delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card-footer.jsx delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card-header.jsx delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card.jsx delete mode 100644 packages/components/src/components/real-wallet-card/real-wallet-card.scss delete mode 100644 packages/components/src/components/virtual-wallet-card/index.js delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card-content.jsx delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer-actions.jsx delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer.jsx delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card-header.jsx delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card.jsx delete mode 100644 packages/components/src/components/virtual-wallet-card/virtual-wallet-card.scss delete mode 100644 packages/components/stories/app-card/README.md delete mode 100644 packages/components/stories/app-card/app-card.stories.js delete mode 100644 packages/components/stories/app-card/statics/labels.js delete mode 100644 packages/components/stories/real-wallet-card/README.md delete mode 100644 packages/components/stories/real-wallet-card/real-wallet-card.stories.js delete mode 100644 packages/components/stories/real-wallet-card/wallet-labels.js delete mode 100644 packages/components/stories/virtual-wallet-card/README.md delete mode 100644 packages/components/stories/virtual-wallet-card/virtual-wallet-card.stories.js diff --git a/packages/components/src/components/app-card/app-card-items/app-card-action-item.jsx b/packages/components/src/components/app-card/app-card-items/app-card-action-item.jsx deleted file mode 100644 index b0a9ddfda736..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-action-item.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import PropTypes from 'prop-types'; -import Text from '../../text'; -import Icon from '../../icon'; - -const AppCardActionItem = React.forwardRef(({ icon, is_hovered, is_virtual, label, onClickHandler }, ref) => ( -
- - {is_hovered && ( - - {label} - - )} -
-)); - -AppCardActionItem.displayName = 'AppCardActionItem'; - -AppCardActionItem.propTypes = { - icon: PropTypes.string, - is_hovered: PropTypes.bool, - is_virtual: PropTypes.bool, - label: PropTypes.string, - onClickHandler: PropTypes.func, -}; - -export default AppCardActionItem; diff --git a/packages/components/src/components/app-card/app-card-items/app-card-actions.jsx b/packages/components/src/components/app-card/app-card-items/app-card-actions.jsx deleted file mode 100644 index fc5bb93e7574..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-actions.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import AppCardActionItem from './app-card-action-item.jsx'; -import Icon from '../../icon'; -import { useHover } from '../../../hooks/use-hover'; - -const AppCardActions = ({ - card_labels, - is_virtual, - onDepositClick, - onPlayClick, - onSettingsClick, - onTransactionsClick, - onWithdrawClick, -}) => { - const [deposit_ref, is_deposit_hovered] = useHover(null, true); - const [withdraw_ref, is_withdraw_hovered] = useHover(null, true); - const [transactions_ref, is_transactions_hovered] = useHover(null, true); - const [settings_ref, is_settings_hovered] = useHover(null, true); - - return ( -
- - {!is_virtual && ( - - )} - {!is_virtual && ( - - )} - -
- -
-
- ); -}; - -AppCardActions.propTypes = { - card_labels: PropTypes.object, - is_virtual: PropTypes.bool, - onDepositClick: PropTypes.func, - onPlayClick: PropTypes.func, - onSettingsClick: PropTypes.func, - onTransactionsClick: PropTypes.func, - onWithdrawClick: PropTypes.func, -}; - -export default AppCardActions; diff --git a/packages/components/src/components/app-card/app-card-items/app-card-body.jsx b/packages/components/src/components/app-card/app-card-items/app-card-body.jsx deleted file mode 100644 index 8c1ae801b36f..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-body.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { isMobile } from '@deriv/shared'; -import Icon from '../../icon'; -import Money from '../../money'; -import Text from '../../text'; - -const AppCardBody = ({ - amount, - app_icon, - app_name, - currency, - card_labels, - getFontColor, - is_swap_free, - is_virtual, - linked_wallet, - onPlayClick, - show_footer, - show_hover_actions, - variant, -}) => { - const is_real_swap_free = !is_virtual && is_swap_free && variant === 'default'; - - const getAppNameFontSize = () => { - if (variant === 'default') { - return isMobile() ? 'xsm' : 'sm'; - } - return isMobile() ? 'xxs' : 'xs'; - }; - - const getBalanceAmountFontSize = () => { - if (variant === 'default') { - return isMobile() ? 'xs' : 's'; - } - return 'xs'; - }; - - return ( -
- {is_real_swap_free && ( -
- - {card_labels.SWAP_FREE} - -
- )} -
- - - {app_name} - -
-
-
- - - - - {card_labels.LINKED}: {linked_wallet} - -
- {isMobile() && variant === 'default' && ( -
- -
- )} -
-
- ); -}; - -AppCardBody.propTypes = { - amount: PropTypes.string, - app_icon: PropTypes.string, - app_name: PropTypes.string, - currency: PropTypes.string, - card_labels: PropTypes.object, - getFontColor: PropTypes.func, - is_swap_free: PropTypes.bool, - is_virtual: PropTypes.bool, - linked_wallet: PropTypes.string, - onPlayClick: PropTypes.func, - show_footer: PropTypes.bool, - show_hover_actions: PropTypes.bool, - variant: PropTypes.oneOf(['default', 'mini', 'micro']), -}; - -export default AppCardBody; diff --git a/packages/components/src/components/app-card/app-card-items/app-card-footer-item.jsx b/packages/components/src/components/app-card/app-card-items/app-card-footer-item.jsx deleted file mode 100644 index 015a26c7d142..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-footer-item.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { isMobile } from '@deriv/shared'; -import Text from '../../text'; - -const AppCardFooterItem = ({ info, getFontColor, label }) => { - return ( -
- - {label} - - - {info} - -
- ); -}; - -AppCardFooterItem.propTypes = { - info: PropTypes.string, - getFontColor: PropTypes.func, - label: PropTypes.string, -}; - -export default AppCardFooterItem; diff --git a/packages/components/src/components/app-card/app-card-items/app-card-footer.jsx b/packages/components/src/components/app-card/app-card-items/app-card-footer.jsx deleted file mode 100644 index 674e8e0d6f5e..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-footer.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import PropTypes from 'prop-types'; -import AppCardFooterItem from './app-card-footer-item.jsx'; - -const AppCardFooter = ({ broker, card_labels, getFontColor, login_id, server, variant }) => ( -
- - - -
-); - -AppCardFooter.propTypes = { - broker: PropTypes.string, - card_labels: PropTypes.object, - getFontColor: PropTypes.func, - login_id: PropTypes.string, - server: PropTypes.string, - variant: PropTypes.oneOf(['default', 'mini', 'micro']), -}; - -export default AppCardFooter; diff --git a/packages/components/src/components/app-card/app-card-items/app-card-header.jsx b/packages/components/src/components/app-card/app-card-items/app-card-header.jsx deleted file mode 100644 index 8177881ac47f..000000000000 --- a/packages/components/src/components/app-card/app-card-items/app-card-header.jsx +++ /dev/null @@ -1,51 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import PropTypes from 'prop-types'; -import Icon from '../../icon'; -import Text from '../../text'; - -const AppCardHeader = ({ card_labels, is_swap_free, onAddRealClick }) => ( -
-
-
- - {card_labels.DEMO} - -
- {is_swap_free && ( -
- - {card_labels.SWAP_FREE} - -
- )} -
-
- - - {card_labels.ADD_REAL} - -
-
-); - -AppCardHeader.propTypes = { - card_labels: PropTypes.object, - is_swap_free: PropTypes.bool, - onAddRealClick: PropTypes.func, -}; - -export default AppCardHeader; diff --git a/packages/components/src/components/app-card/app-card-items/real-app-card-background.jsx b/packages/components/src/components/app-card/app-card-items/real-app-card-background.jsx deleted file mode 100644 index 32e09f60d8b9..000000000000 --- a/packages/components/src/components/app-card/app-card-items/real-app-card-background.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { isMobile } from '@deriv/shared'; - -const RealAppCardBackground = ({ is_swap_free, variant }) => { - const getSVGForegroundPath = () => { - if (variant === 'default') { - return isMobile() ? 'M0 0h272v12L0 30V0z' : 'M0 0h280v16L0 40V0z'; - } - return 'M0 0h216v9L0 21V0z'; - }; - - const getSVGbackgroundPath = () => { - if (variant === 'default') { - return isMobile() ? 'M0 0h272v12L0 44V0z' : 'M0 0h280v16L0 60V0z'; - } - return 'M0 0h216v9L0 32V0z'; - }; - - return ( - - - - - ); -}; - -RealAppCardBackground.propTypes = { - is_swap_free: PropTypes.bool, - variant: PropTypes.oneOf(['default', 'mini', 'micro']), -}; - -export default RealAppCardBackground; diff --git a/packages/components/src/components/app-card/app-card.jsx b/packages/components/src/components/app-card/app-card.jsx deleted file mode 100644 index f944c3bd42d8..000000000000 --- a/packages/components/src/components/app-card/app-card.jsx +++ /dev/null @@ -1,120 +0,0 @@ -import classNames from 'classnames'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { isMobile } from '@deriv/shared'; -import RealAppCardBackground from './app-card-items/real-app-card-background.jsx'; -import AppCardHeader from './app-card-items/app-card-header.jsx'; -import AppCardBody from './app-card-items/app-card-body.jsx'; -import AppCardActions from './app-card-items/app-card-actions.jsx'; -import AppCardFooter from './app-card-items/app-card-footer.jsx'; -import { useHover } from '../../hooks'; - -const AppCard = ({ - amount, - app_icon, - app_name, - broker, - currency, - getCardLabels, - is_swap_free, - is_virtual, - linked_wallet, - login_id, - onAddRealClick, - onDepositClick, - onPlayClick, - onSettingsClick, - onTransactionsClick, - onWithdrawClick, - server, - show_footer, - show_hover_actions, - variant = 'default', -}) => { - const [card_ref, is_hovered] = useHover(null, true); - const getFontColor = () => { - if (is_virtual) return 'colored-background'; - return 'general'; - }; - const card_labels = getCardLabels(); - - return ( -
- {!is_virtual && } - {is_virtual && variant === 'default' && ( - - )} - - {show_footer && variant !== 'micro' && !is_hovered && ( - - )} - {show_hover_actions && variant !== 'micro' && !isMobile() && is_hovered && ( - - )} -
- ); -}; - -AppCard.propTypes = { - amount: PropTypes.string, - app_icon: PropTypes.string, - app_name: PropTypes.string, - broker: PropTypes.string, - currency: PropTypes.string, - getCardLabels: PropTypes.func.isRequired, - is_swap_free: PropTypes.bool, - is_virtual: PropTypes.bool, - linked_wallet: PropTypes.string, - login_id: PropTypes.string, - onAddRealClick: PropTypes.func, - onDepositClick: PropTypes.func, - onPlayClick: PropTypes.func, - onSettingsClick: PropTypes.func, - onTransactionsClick: PropTypes.func, - onWithdrawClick: PropTypes.func, - server: PropTypes.string, - show_footer: PropTypes.bool, - show_hover_actions: PropTypes.bool, - variant: PropTypes.oneOf(['default', 'mini', 'micro']), -}; - -export default AppCard; diff --git a/packages/components/src/components/app-card/app-card.scss b/packages/components/src/components/app-card/app-card.scss deleted file mode 100644 index 3990b8e05178..000000000000 --- a/packages/components/src/components/app-card/app-card.scss +++ /dev/null @@ -1,307 +0,0 @@ -.dc-app-card { - &__wrapper { - display: flex; - flex-direction: column; - position: relative; - align-items: flex-start; - - &--virtual { - width: 28rem; - height: 21.4rem; - background: var(--app-card-virtual); // TODO: Update after #2476 is merged - border-radius: 0.8rem; - padding: 0.8rem 1.6rem; - - @include mobile { - width: 27.2rem; - height: 17.6rem; - padding: 0.8rem 1.2rem; - } - - &-swap-free { - background: var(--app-card-virtual-swap-free); // TODO: Update after #2476 is merged - } - } - &--real { - width: 28rem; - height: 18.2rem; - background: var(--general-main-1); - box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.05), 0px 16px 20px rgba(0, 0, 0, 0.05); - border-radius: 1.6rem; - padding: 1.6rem; - - &-background { - position: absolute; - top: 0; - left: 0; - height: 6rem; - width: 100%; - border-radius: 1.6rem 1.6rem 0 0; - } - @include mobile { - width: 27.2rem; - height: 14.4rem; - padding: 1.2rem; - } - } - &--mini { - height: 12.8rem; - width: 21.6rem; - padding: 1.6rem; - } - &--micro { - height: 9.6rem; - width: 16.2rem; - padding: 1.2rem; - } - } - &__badge { - height: 1.6rem; - display: flex; - justify-content: center; - align-items: center; - margin-right: 0.8rem; - padding: 0.2rem 0.8rem; - border-radius: 1.2rem; - } - &-header { - &__wrapper { - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - } - &__container { - display: flex; - flex-direction: row; - } - &__badge { - &--demo { - background: var(--badge-white); - cursor: text; - } - &--swap-free { - background: var(--badge-green); - cursor: text; - } - &--add-real { - height: 2.4rem; - background: var(--badge-blue); - margin-right: unset; - cursor: pointer; - - &-icon { - height: 1.2rem; - width: 1.2rem; - border: 1px solid var(--general-main-1); - border-radius: 0.6rem; - } - &-text { - margin-left: 0.4rem; - } - } - } - } - &-body { - &__wrapper { - width: 100%; - display: flex; - flex-direction: column; - justify-content: space-evenly; - align-items: flex-start; - z-index: 5; - - &--no-hover { - flex-grow: 1; - justify-content: space-between; - } - - &--virtual { - &-default { - margin-top: 1.6rem; - - @include mobile { - margin-top: 0.8rem; - } - } - &-mini { - margin-top: 0; - } - &-micro { - flex-grow: unset; - justify-content: unset; - } - } - &--real { - &-micro { - flex-grow: unset; - justify-content: unset; - } - } - } - &__app-info { - &-wrapper { - display: flex; - align-items: center; - } - &-icon { - &--default { - height: 48px; - width: 48px; - - @include mobile { - height: 32px; - width: 32px; - } - } - &--mini { - height: 24px; - width: 24px; - } - &--micro { - height: 18px; - width: 18px; - } - } - &-name { - &--default { - margin-left: 0.8rem; - } - &--mini { - margin-left: 0.6rem; - } - &--micro { - margin-left: 0.4rem; - } - } - } - &__balance-info { - &-wrapper { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - width: 100%; - } - &-content { - display: flex; - flex-direction: column; - justify-content: center; - - &--default { - margin-top: 1.6rem; - - @include mobile { - margin-top: 0.8rem; - } - } - &--mini { - margin-top: 0.8rem; - } - &--micro { - margin-top: 0.4rem; - } - } - } - &__badge { - &--swap-free { - background: var(--badge-violet); - cursor: text; - margin-right: unset; - position: absolute; - right: 1rem; - top: 1rem; - } - } - } - &-footer { - &__wrapper { - width: calc(100% - 3.2rem); - height: 3.2rem; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - position: absolute; - bottom: 1.6rem; - - &--default { - bottom: 1.8rem; - } - &--mini { - bottom: 1.2rem; - } - - @include mobile { - height: unset; - bottom: 1.2rem; - } - } - &__info { - display: flex; - flex-direction: column; - justify-content: center; - } - } - &-actions { - &__wrapper { - height: 3.2rem; - width: calc(100% - 2.4rem); - display: flex; - flex-direction: row; - justify-content: space-around; - align-items: center; - position: absolute; - bottom: 1.2rem; - } - &__content { - &-wrapper { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - transition: transform 0.2s; - cursor: pointer; - - &:hover { - transform: scale(1.5); - } - } - } - &__icon { - height: 1.6rem; - width: 1.6rem; - - &--hover { - padding: 0.2rem; - border-radius: 0.8rem; - - &-virtual { - border: 1px solid var(--general-main-1); - } - &-real { - border: 1px solid var(--border-hover-1); - } - } - - &--play { - height: 3.2rem; - width: 3.2rem; - display: flex; - justify-content: center; - align-items: center; - border-radius: 1.6rem; - background: var(--brand-red-coral); - transition: transform 0.2s; - cursor: pointer; - - @include desktop { - &:hover { - transform: scale(1.3); - } - } - } - } - } -} diff --git a/packages/components/src/components/app-card/index.js b/packages/components/src/components/app-card/index.js deleted file mode 100644 index 46e8e6b23a52..000000000000 --- a/packages/components/src/components/app-card/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import AppCard from './app-card.jsx'; -import './app-card.scss'; - -export default AppCard; diff --git a/packages/components/src/components/real-wallet-card/index.js b/packages/components/src/components/real-wallet-card/index.js deleted file mode 100644 index 4ec1b98d9163..000000000000 --- a/packages/components/src/components/real-wallet-card/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import RealWalletCard from './real-wallet-card.jsx'; -import './real-wallet-card.scss'; - -export default RealWalletCard; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card-content.jsx b/packages/components/src/components/real-wallet-card/real-wallet-card-content.jsx deleted file mode 100644 index 7caa7b78809b..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card-content.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import Money from '../money'; -import Text from '../text'; - -const RealWalletCardContent = ({ amount, currency, has_footer, wallet_name }) => { - return ( -
- - {wallet_name} - - - - -
- ); -}; - -RealWalletCardContent.propTypes = { - amount: PropTypes.number, - currency: PropTypes.string, - has_footer: PropTypes.bool, - wallet_name: PropTypes.string, -}; - -export default RealWalletCardContent; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card-footer-actions.jsx b/packages/components/src/components/real-wallet-card/real-wallet-card-footer-actions.jsx deleted file mode 100644 index fc94d52b2d4e..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card-footer-actions.jsx +++ /dev/null @@ -1,132 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { useHover } from '../../hooks/use-hover'; -import Icon from '../icon'; -import Text from '../text'; - -const RealWalletCardFooterActions = ({ - getWalletLabels, - is_temporarily_unavailable, - onClickDeposit, - onClickSettings, - onClickTransactions, - onClickTransfer, - onClickWithdrawal, -}) => { - const [hover_ref_deposit, is_deposit_hovered] = useHover(null, true); - const [hover_ref_settings, is_settings_settings] = useHover(null, true); - const [hover_ref_transactions, is_transactions_hovered] = useHover(null, true); - const [hover_ref_transfer, is_transfer_hovered] = useHover(null, true); - const [hover_ref_withdrawal, is_withdrawal_hovered] = useHover(null, true); - - return ( -
-
- - {is_deposit_hovered && ( - - {getWalletLabels().DEPOSIT} - - )} -
-
- - {is_withdrawal_hovered && ( - - {getWalletLabels().WITHDRAWAL} - - )} -
-
- - {is_transfer_hovered && ( - - {getWalletLabels().TRANSFER} - - )} -
-
- - {is_transactions_hovered && ( - - {getWalletLabels().TRANSACTIONS} - - )} -
-
- - {is_settings_settings && ( - - {getWalletLabels().SETTINGS} - - )} -
-
- ); -}; - -RealWalletCardFooterActions.propTypes = { - getWalletLabels: PropTypes.func, - is_temporarily_unavailable: PropTypes.bool, - onClickDeposit: PropTypes.func, - onClickSettings: PropTypes.func, - onClickTransactions: PropTypes.func, - onClickTransfer: PropTypes.func, - onClickWithdrawal: PropTypes.func, -}; - -export default RealWalletCardFooterActions; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card-footer.jsx b/packages/components/src/components/real-wallet-card/real-wallet-card-footer.jsx deleted file mode 100644 index 79ade93b92d1..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card-footer.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import RealWalletCardFooterActions from './real-wallet-card-footer-actions.jsx'; -import Button from '../button'; -import Icon from '../icon'; -import Text from '../text'; - -const RealWalletCardFooter = ({ - getWalletLabels, - is_actions_footer, - is_deposit_footer, - is_temporarily_unavailable, - onClickDeposit, - onClickSettings, - onClickTransactions, - onClickTransfer, - onClickWithdrawal, - should_show_footer_actions, -}) => { - if (is_actions_footer || is_temporarily_unavailable) { - return ( - - {should_show_footer_actions && ( - - )} - - {is_temporarily_unavailable && ( -
- {getWalletLabels().TEMPORARILY_UNAVAILABLE} -
- )} -
- ); - } - - if (is_deposit_footer) { - return ( - - ); - } - - return null; // For empty footer -}; - -RealWalletCardFooter.propTypes = { - getWalletLabels: PropTypes.func, - is_actions_footer: PropTypes.bool, - is_deposit_footer: PropTypes.bool, - is_temporarily_unavailable: PropTypes.bool, - onClickDeposit: PropTypes.func, - onClickSettings: PropTypes.func, - onClickTransactions: PropTypes.func, - onClickTransfer: PropTypes.func, - onClickWithdrawal: PropTypes.func, - should_show_footer_actions: PropTypes.bool, -}; - -export default RealWalletCardFooter; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card-header.jsx b/packages/components/src/components/real-wallet-card/real-wallet-card-header.jsx deleted file mode 100644 index 3e8d53f500f3..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card-header.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import Icon from '../icon'; -import Money from '../money'; -import Text from '../text'; - -const RealWalletCardHeader = ({ - amount, - currency, - is_selected, - is_temporarily_unavailable, - wallet_name, - wallet_type, -}) => { - return ( -
- {is_temporarily_unavailable && ( -
- - {wallet_name} - - - - -
- )} - {is_selected && } - -
- ); -}; - -RealWalletCardHeader.propTypes = { - amount: PropTypes.number, - currency: PropTypes.string, - is_selected: PropTypes.bool, - is_temporarily_unavailable: PropTypes.bool, - wallet_name: PropTypes.string, - wallet_type: PropTypes.string, -}; - -export default RealWalletCardHeader; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card.jsx b/packages/components/src/components/real-wallet-card/real-wallet-card.jsx deleted file mode 100644 index 1074f6ccc927..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card.jsx +++ /dev/null @@ -1,118 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import RealWalletCardContent from './real-wallet-card-content.jsx'; -import RealWalletCardHeader from './real-wallet-card-header.jsx'; -import RealWalletCardFooter from './real-wallet-card-footer.jsx'; - -const RealWalletCard = ({ - amount, - currency, - getWalletLabels, - has_footer = true, - has_no_funds = false, - is_actions_footer = false, - is_deposit_footer = false, - is_linked = false, - is_selected = false, - is_temporarily_unavailable = false, - onClickDeposit, - onClickSettings, - onClickTransactions, - onClickTransfer, - onClickWithdrawal, - wallet_name, - width = '280', -}) => { - const [should_show_footer_actions, setShouldShowFooterActions] = React.useState(false); - const height = (width / 5) * 3; - - // Get wallet type (first word) before space or forward slash for background and icon - const wallet_type = wallet_name.match(/(^[^/ || ^\s]+)/)[0]; - - const onMouseEnter = () => { - setShouldShowFooterActions(true); - }; - - const onMouseLeave = () => { - setShouldShowFooterActions(false); - }; - - return ( -
- {/* Creating an overlay to add opacity to background but not to deposit button */} - {has_no_funds && ( -
- )} - - {!is_temporarily_unavailable && ( - - )} - {has_footer && ( - - )} -
- ); -}; - -RealWalletCard.propTypes = { - amount: PropTypes.number, - currency: PropTypes.string, - getWalletLabels: PropTypes.func, - has_footer: PropTypes.bool, - has_no_funds: PropTypes.bool, - is_actions_footer: PropTypes.bool, - is_deposit_footer: PropTypes.bool, - is_linked: PropTypes.bool, - is_selected: PropTypes.bool, - is_temporarily_unavailable: PropTypes.bool, - onClickDeposit: PropTypes.func, - onClickSettings: PropTypes.func, - onClickTransactions: PropTypes.func, - onClickTransfer: PropTypes.func, - onClickWithdrawal: PropTypes.func, - wallet_name: PropTypes.string, - width: PropTypes.string, -}; - -export default RealWalletCard; diff --git a/packages/components/src/components/real-wallet-card/real-wallet-card.scss b/packages/components/src/components/real-wallet-card/real-wallet-card.scss deleted file mode 100644 index f6101a277945..000000000000 --- a/packages/components/src/components/real-wallet-card/real-wallet-card.scss +++ /dev/null @@ -1,104 +0,0 @@ -.dc-real-wallet-card { - border-radius: 16px; - display: flex; - flex-direction: column; - justify-content: space-between; - - &__actions-container { - align-self: center; - display: flex; - flex-direction: row; - height: 4.3rem; - justify-content: space-between; - width: calc(100% - 3.2rem); - - &--temporarily-unavailable { - height: unset; - } - } - - &__action { - align-items: center; - cursor: pointer; - display: flex; - flex-direction: column; - transition: transform 0.25s ease-in-out; - - &--icon { - border: 0.33px solid var(--general-main-1); - border-radius: 0.8rem; - padding: 0.24rem; - transform: scale(1.6); - transition: transform 0.25s ease-in-out; - } - - &--text { - display: flex; - padding-top: 0.4rem; - transform: scale(1); - transition: transform 0.25s ease-in-out; - } - } - - &__content { - display: flex; - flex-direction: column; - flex-grow: 1; - padding: 0 1.6rem; - - &--no-footer { - justify-content: flex-end; - padding-bottom: 1.6rem; - } - } - - &__footer { - &--temporarily-unavailable { - align-items: center; - align-self: center; - background: var(--status-warning); - border-radius: 1.6rem; - display: flex; - height: 2.2rem; - justify-content: center; - margin: 0 1rem 0.8rem; - width: calc(100% - 2rem); - } - - &--deposit { - align-self: flex-end; - border-radius: 2.1rem; - height: 2.4rem; - margin: 0 1.6rem 1.6rem; - width: 7.1rem; - - .dc-btn__icon { - padding-right: 0.3rem; - } - } - } - - &__header { - display: flex; - justify-content: flex-end; - padding: 1.6rem 1.6rem 0.4rem; - - &--icon { - height: 4rem; - width: 6.4rem; - } - - &--selected { - justify-content: space-between; - } - } - - &--linked { - border: 4px solid var(--status-info); - } - - &--no-funds { - background: rgba(255, 255, 255, 0.32); - position: absolute; - } -} diff --git a/packages/components/src/components/virtual-wallet-card/index.js b/packages/components/src/components/virtual-wallet-card/index.js deleted file mode 100644 index 073fc52a99a5..000000000000 --- a/packages/components/src/components/virtual-wallet-card/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import VirtualWalletCard from './virtual-wallet-card.jsx'; -import './virtual-wallet-card.scss'; - -export default VirtualWalletCard; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-content.jsx b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-content.jsx deleted file mode 100644 index fe75c8c2b0dd..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-content.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import Money from '../money'; -import Text from '../text'; - -const VirtualWalletCardContent = ({ amount, currency, has_footer, wallet_name }) => { - return ( -
- - {wallet_name} - - - - -
- ); -}; - -VirtualWalletCardContent.propTypes = { - amount: PropTypes.number, - currency: PropTypes.string, - has_footer: PropTypes.bool, - wallet_name: PropTypes.string, -}; - -export default VirtualWalletCardContent; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer-actions.jsx b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer-actions.jsx deleted file mode 100644 index 7347dc483cba..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer-actions.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { useHover } from '../../hooks/use-hover'; -import Icon from '../icon'; -import Text from '../text'; - -const VirtualWalletCardFooterActions = ({ getWalletLabels, onClickReset, onClickTransactions }) => { - const [hover_ref_reset, is_reset_hovered] = useHover(null, true); - const [hover_ref_transactions, is_transactions_hovered] = useHover(null, true); - - return ( -
-
- - {is_reset_hovered && ( - - {getWalletLabels().RESET} - - )} -
-
- - {is_transactions_hovered && ( - - {getWalletLabels().TRANSACTIONS} - - )} -
-
- ); -}; - -VirtualWalletCardFooterActions.propTypes = { - getWalletLabels: PropTypes.func, - onClickReset: PropTypes.func, - onClickTransactions: PropTypes.func, -}; - -export default VirtualWalletCardFooterActions; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer.jsx b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer.jsx deleted file mode 100644 index 27a12747100e..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-footer.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import VirtualWalletCardFooterActions from './virtual-wallet-card-footer-actions.jsx'; -import Button from '../button'; -import Icon from '../icon'; -import Text from '../text'; - -const VirtualWalletCardFooter = ({ - getWalletLabels, - is_actions_footer, - is_topup_footer, - onClickReset, - onClickTransactions, - should_show_footer_actions, -}) => { - if (is_topup_footer) { - return ( - - ); - } - - if (is_actions_footer && should_show_footer_actions) { - return ( - - ); - } - - return null; // For empty footer -}; - -VirtualWalletCardFooter.propTypes = { - getWalletLabels: PropTypes.func, - is_actions_footer: PropTypes.bool, - is_topup_footer: PropTypes.bool, - onClickReset: PropTypes.func, - onClickTransactions: PropTypes.func, - should_show_footer_actions: PropTypes.bool, -}; - -export default VirtualWalletCardFooter; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-header.jsx b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-header.jsx deleted file mode 100644 index bfe330bfef56..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card-header.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import Icon from '../icon'; - -const VirtualWalletCardHeader = () => { - return ( -
- -
- ); -}; - -export default VirtualWalletCardHeader; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.jsx b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.jsx deleted file mode 100644 index 8c9ede9df45d..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import VirtualWalletCardContent from './virtual-wallet-card-content.jsx'; -import VirtualWalletCardHeader from './virtual-wallet-card-header.jsx'; -import VirtualWalletCardFooter from './virtual-wallet-card-footer.jsx'; - -const VirtualWalletCard = ({ - amount, - currency, - getWalletLabels, - has_footer = true, - has_no_funds = false, - is_actions_footer = false, - is_topup_footer = false, - onClickReset, - onClickTransactions, - wallet_name, - width = '280', -}) => { - const [should_show_footer_actions, setShouldShowFooterActions] = React.useState(false); - - const height = (width / 5) * 3; - - const onMouseEnter = () => { - setShouldShowFooterActions(true); - }; - - const onMouseLeave = () => { - setShouldShowFooterActions(false); - }; - - return ( -
- {/* Creating an overlay to add opacity to background but not to top-up button */} - {has_no_funds && ( -
- )} - - - {has_footer && ( - - )} -
- ); -}; - -VirtualWalletCard.propTypes = { - amount: PropTypes.number, - currency: PropTypes.string, - getWalletLabels: PropTypes.func, - has_footer: PropTypes.bool, - has_no_funds: PropTypes.bool, - is_actions_footer: PropTypes.bool, - is_topup_footer: PropTypes.bool, - onClickReset: PropTypes.func, - onClickTransactions: PropTypes.func, - wallet_name: PropTypes.string, - width: PropTypes.string, -}; - -export default VirtualWalletCard; diff --git a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.scss b/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.scss deleted file mode 100644 index 39f15d84b35e..000000000000 --- a/packages/components/src/components/virtual-wallet-card/virtual-wallet-card.scss +++ /dev/null @@ -1,67 +0,0 @@ -.dc-virtual-wallet-card { - background: var(--wallet-virtual); // TODO: Update after #2476 is merged - border-radius: 16px; - display: flex; - flex-direction: column; - justify-content: space-between; - - &__actions-container { - display: flex; - flex-direction: row; - height: 4.3rem; - justify-content: space-between; - padding-left: 1.6rem; - width: calc(100% - 18rem); - } - - &__action { - align-items: center; - cursor: pointer; - display: flex; - flex-direction: column; - transition: transform 0.25s ease-in-out; - - &--icon { - border: 0.33px solid var(--general-main-1); - border-radius: 0.8rem; - padding: 0.24rem; - transform: scale(1.6); - transition: transform 0.25s ease-in-out; - } - - &--text { - display: flex; - padding-top: 0.4rem; - transform: scale(1); - transition: transform 0.25s ease-in-out; - } - } - - &__content { - display: flex; - flex-direction: column; - flex-grow: 1; - padding: 0 1.6rem; - - &--no-footer { - justify-content: flex-end; - padding-bottom: 1.6rem; - } - } - - &__header { - display: flex; - justify-content: flex-end; - padding: 1.6rem 1.6rem 0.4rem; - - &--icon { - height: 4rem; - width: 6.4rem; - } - } - - &--no-funds { - background: rgba(255, 255, 255, 0.32); - position: absolute; - } -} diff --git a/packages/components/src/index.js b/packages/components/src/index.js index e661f4553684..6d24e15642d1 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -10,7 +10,6 @@ // export default { Label, Button }; export { default as Accordion } from './components/accordion'; -export { default as AppCard } from './components/app-card'; export { default as AppSettings } from './components/app-settings'; export { default as AutoHeightWrapper } from './components/auto-height-wrapper'; export { default as Autocomplete } from './components/autocomplete'; @@ -87,7 +86,6 @@ export { default as ProgressSlider } from './components/progress-slider'; export { default as ProgressSliderMobile } from './components/progress-slider-mobile'; export { default as RadioGroup } from './components/radio-group'; export { default as ReadMore } from './components/read-more'; -export { default as RealWalletCard } from './components/real-wallet-card'; export { default as RouteWithSubroutes } from './components/route-with-subroutes'; export { default as SelectNative } from './components/select-native'; export { default as StaticUrl } from './components/static-url'; @@ -107,6 +105,5 @@ export { default as Timeline } from './components/timeline'; export { default as Tooltip } from './components/tooltip'; export { default as UILoader } from './components/u-i-loader'; export { default as VerticalTab } from './components/vertical-tab'; -export { default as VirtualWalletCard } from './components/virtual-wallet-card'; export { default as Wizard } from './components/wizard'; export * from './hooks'; diff --git a/packages/components/stories/app-card/README.md b/packages/components/stories/app-card/README.md deleted file mode 100644 index dbcab18aa2f6..000000000000 --- a/packages/components/stories/app-card/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# AppCard Component - -Show detailed information of apps in the form of cards. There are 3 variants of `AppCards`: - -- `default`: Default size with all details. -- `mini`: Mini version of AppCard with reduced size. -- `micro`: Micro version of AppCard with reduced size and essential details only. - -#### Supported Gestures: - -- Hover -- Click - -## Usage - -```jsx -import AppCard from 'deriv-components'; - -const DummyComponent = props => ( - -); -``` - -## Props - -| Name | Type | Default | Description | -| ------------------- | ---------- | --------- | ---------------------------------------------------------- | -| amount | {string} | null | Amount to be shown on the AppCard. | -| app_icon | {string} | null | Icon name for the AppCard. | -| app_name | {string} | null | App name to be shown on the AppCard | -| broker | {string} | null | Broker name to be shown on the AppCard | -| currency | {string} | null | Currency linked to the AppCard. | -| getCardLabels | {function} | null | Function returns the labels to show in the card. | -| is\_swap\_free | {boolean} | null | Defines whether the AppCard is Swap-Free or not. | -| is_virtual | {boolean} | null | Defines whether the AppCard is virtual or not. | -| linked_wallet | {string} | null | Linked wallet name to be shown on the AppCard. | -| login_id | {string} | null | Login ID to be shown on the AppCard | -| onAddRealClick | {function} | null | Function triggers when user clicks on `Add Real` badge. | -| onDepositClick | {function} | null | Function triggers when user clicks on `Deposit` icon. | -| onPlayClick | {function} | null | Function triggers when user clicks on `Play` icon. | -| onSettingsClick | {function} | null | Function triggers when user clicks on `Settings` icon. | -| onTransactionsClick | {function} | null | Function triggers when user clicks on `Transactions` icon. | -| onWithdrawClick | {function} | null | Function triggers when user clicks on `Withdraw` icon. | -| server | {string} | null | Server name to be shown on the AppCard. | -| show_footer | {boolean} | null | Define whether the AppCard should render Footer. | -| show\_hover\_actions | {boolean} | null | Define whether the AppCard should show Actions on hover. | -| variant | {string} | `default` | The variant to use. | - -# Full example: - -```jsx -import React from 'react'; -import AppCard from 'deriv-components'; - -const DummyComponent = props => { - return ( - - { - console.log('Add real clicked!'); - }} - onDepositClick={() => { - console.log('Deposit clicked!'); - }} - onPlayClick={() => { - console.log('Play clicked!'); - }} - onSettingsClick={() => { - console.log('Settings clicked!'); - }} - onTransactionsClick={() => { - console.log('Transactions clicked!'); - }} - onWithdrawClick={() => { - console.log('Withdraw clicked!'); - }} - server='Deriv Server' - show_footer={true} - show_hover_actions={true} - variant='default' - /> - - ); -}; -``` diff --git a/packages/components/stories/app-card/app-card.stories.js b/packages/components/stories/app-card/app-card.stories.js deleted file mode 100644 index 0ff9ac72f310..000000000000 --- a/packages/components/stories/app-card/app-card.stories.js +++ /dev/null @@ -1,62 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import { withKnobs, boolean, text } from '@storybook/addon-knobs'; -import AppCard from 'Components/app-card'; -import React from 'react'; -import notes from './README.md'; -import { getCardLabels } from './statics/labels'; -import Wrapper from '../shared/wrapper'; - -storiesOf('AppCard', module) - .addDecorator(withKnobs) - .add( - 'Basic Usage', - () => { - return ( - - { - /* eslint-disable no-console */ - console.log('Add real clicked'); - }} - onDepositClick={() => { - /* eslint-disable no-console */ - console.log('Deposit clicked!'); - }} - onPlayClick={() => { - /* eslint-disable no-console */ - console.log('Play clicked!'); - }} - onSettingsClick={() => { - /* eslint-disable no-console */ - console.log('Settings clicked!'); - }} - onTransactionsClick={() => { - /* eslint-disable no-console */ - console.log('Transactions clicked!'); - }} - onWithdrawClick={() => { - /* eslint-disable no-console */ - console.log('Withdraw clicked!'); - }} - server='Deriv Server' - show_footer={boolean('showFooter', true)} - show_hover_actions={boolean('showHoverActions', true)} - variant={text('variant', 'default')} - /> - - ); - }, - { - notes, - } - ); diff --git a/packages/components/stories/app-card/statics/labels.js b/packages/components/stories/app-card/statics/labels.js deleted file mode 100644 index ff76fb070d28..000000000000 --- a/packages/components/stories/app-card/statics/labels.js +++ /dev/null @@ -1,13 +0,0 @@ -export const getCardLabels = () => ({ - ADD: 'Add', - WITHDRAW: 'Withdraw', - TRANSACTIONS: 'Transactions', - SETTINGS: 'Settings', - SWAP_FREE: 'Swap-free', - LINKED: 'Linked', - LOGIN_ID: 'Login ID', - BROKER: 'Broker', - SERVER: 'Server', - DEMO: 'Demo', - ADD_REAL: 'Add real', -}); diff --git a/packages/components/stories/real-wallet-card/README.md b/packages/components/stories/real-wallet-card/README.md deleted file mode 100644 index f7d99188287b..000000000000 --- a/packages/components/stories/real-wallet-card/README.md +++ /dev/null @@ -1,79 +0,0 @@ -# RealWalletCard Component - -RealWalletCard shows real wallet information. - -#### Supported Gestures: - -- Click -- Hover - -## Usage - -```jsx -import RealWalletCard from 'deriv-components'; -const DummyComponent = props => ( - -); -``` - -## Props - -| Name | Type | Default | Description | -| -------------------------- | ---------- | ------- | ------------------------------------------------------------------------- | -| amount | {number} | null | Amount shown on the card. | -| currency | {string} | null | Currency linked to the card. | -| getWalletLabels | {function} | null | Constants used in the card. | -| has_footer | {boolean} | true | Defines whether the card has a footer. | -| has_no_funds | {boolean} | false | Defines whether the wallet has no funds. | -| is_actions_footer | {boolean} | false | Defines whether the footer should show hover actions. | -| is_deposit_footer | {boolean} | false | Defines whether the footer should show deposit button. | -| is_linked | {boolean} | false | Defines whether the wallet is linked to an app. | -| is_selected | {boolean} | false | Defines whether the wallet is selected. | -| is_temporarily_unavailable | {boolean} | false | Defines whether the wallet is temporarily unavailable. | -| onClickDeposit | {function} | null | Function triggers when user clicks on `Deposit` badge in the footer. | -| onClickSettings | {function} | null | Function triggers when user clicks on `Settings` badge in the footer. | -| onClickTransactions | {function} | null | Function triggers when user clicks on `Transactions` badge in the footer. | -| onClickTransfer | {function} | null | Function triggers when user clicks on `Transfer` badge in the footer. | -| onClickWithdrawal | {function} | null | Function triggers when user clicks on `Withdrawal` badge in the footer. | -| wallet_name | {string} | null | Wallet name shown on the card. | -| width | {string} | `280` | Width of the wallet card. | - -# Full example: - -```jsx -import React from 'react'; -import RealWalletCard from 'deriv-components'; -const DummyComponent = props => { - return ( - { - console.log('Deposit clicked!'); - }} - onClickSettings={() => { - console.log('Settings clicked!'); - }} - onClickTransactions={() => { - console.log('Transactions clicked!'); - }} - onClickTransfer={() => { - console.log('Transfer clicked!'); - }} - onClickWithdrawal={() => { - console.log('Withdrawal clicked!'); - }} - wallet_name='Credit/Debit USD Wallet' - width='280' - /> - ); -}; -``` diff --git a/packages/components/stories/real-wallet-card/real-wallet-card.stories.js b/packages/components/stories/real-wallet-card/real-wallet-card.stories.js deleted file mode 100644 index 96f5ada7a533..000000000000 --- a/packages/components/stories/real-wallet-card/real-wallet-card.stories.js +++ /dev/null @@ -1,55 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import { withKnobs, boolean } from '@storybook/addon-knobs'; -import RealWalletCard from 'Components/real-wallet-card'; -import React from 'react'; -import notes from './README.md'; -import { getWalletLabels } from './wallet-labels'; -import Wrapper from '../shared/wrapper'; - -storiesOf('RealWalletCard', module) - .addDecorator(withKnobs) - .add( - 'Basic Usage', - () => { - return ( - - { - /* eslint-disable no-console */ - console.log('Deposit clicked!'); - }} - onClickSettings={() => { - /* eslint-disable no-console */ - console.log('Settings clicked!'); - }} - onClickTransactions={() => { - /* eslint-disable no-console */ - console.log('Transactions clicked!'); - }} - onClickTransfer={() => { - console.log('Transfer clicked!'); - }} - onClickWithdrawal={() => { - /* eslint-disable no-console */ - console.log('Withdrawal clicked!'); - }} - wallet_name='Credit/Debit USD Wallet' - width='280' - /> - - ); - }, - { - notes, - } - ); diff --git a/packages/components/stories/real-wallet-card/wallet-labels.js b/packages/components/stories/real-wallet-card/wallet-labels.js deleted file mode 100644 index f085182d1cf7..000000000000 --- a/packages/components/stories/real-wallet-card/wallet-labels.js +++ /dev/null @@ -1,11 +0,0 @@ -export const getWalletLabels = () => ({ - DEPOSIT: 'Deposit', - GET_WALLET: 'Get more wallets', - RESET: 'Reset', - SETTINGS: 'Settings', - TEMPORARILY_UNAVAILABLE: 'Deposits and withdrawals temporarily unavailable ', - TOPUP: 'Top-up', - TRANSACTIONS: 'Transactions', - TRANSFER: 'Transfer', - WITHDRAWAL: 'Withdrawal', -}); diff --git a/packages/components/stories/virtual-wallet-card/README.md b/packages/components/stories/virtual-wallet-card/README.md deleted file mode 100644 index e545630b97b1..000000000000 --- a/packages/components/stories/virtual-wallet-card/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# VirtualWalletCard Component - -VirtualWalletCard shows real wallet information. - -#### Supported Gestures: - -- Click -- Hover - -## Usage - -```jsx -import VirtualWalletCard from 'deriv-components'; -const DummyComponent = props => ( - -); -``` - -## Props - -| Name | Type | Default | Description | -| ------------------- | ---------- | ------- | ------------------------------------------------------------------------- | -| amount | {number} | null | Amount shown on the card. | -| currency | {string} | null | Currency linked to the card. | -| getWalletLabels | {function} | null | Constants used in the card. | -| has_footer | {boolean} | true | Defines whether the card has a footer. | -| has_no_funds | {boolean} | false | Defines whether the wallet has no funds. | -| is_actions_footer | {boolean} | false | Defines whether the footer should show hover actions. | -| is_topup_footer | {boolean} | false | Defines whether the footer should show top-up button. | -| onClickReset | {function} | null | Function triggers when user clicks on `Reset` badge in the footer. | -| onClickTransactions | {function} | null | Function triggers when user clicks on `Transactions` badge in the footer. | -| wallet_name | {string} | null | Wallet name shown on the card. | -| width | {string} | `280` | Width of the wallet card. | - -# Full example: - -```jsx -import React from 'react'; -import VirtualWalletCard from 'deriv-components'; -const DummyComponent = props => { - return ( - { - console.log('Reset clicked!'); - }} - onClickTransactions={() => { - console.log('Transactions clicked!'); - }} - wallet_name='Virtual USD Wallet' - width='280' - /> - ); -}; -``` diff --git a/packages/components/stories/virtual-wallet-card/virtual-wallet-card.stories.js b/packages/components/stories/virtual-wallet-card/virtual-wallet-card.stories.js deleted file mode 100644 index 8090234d8061..000000000000 --- a/packages/components/stories/virtual-wallet-card/virtual-wallet-card.stories.js +++ /dev/null @@ -1,41 +0,0 @@ -import { storiesOf } from '@storybook/react'; -import { withKnobs, boolean } from '@storybook/addon-knobs'; -import VirtualWalletCard from 'Components/virtual-wallet-card'; -import React from 'react'; -import notes from './README.md'; -import { getWalletLabels } from '../real-wallet-card/wallet-labels'; -import Wrapper from '../shared/wrapper'; - -storiesOf('VirtualWalletCard', module) - .addDecorator(withKnobs) - .add( - 'Basic Usage', - () => { - return ( - - { - /* eslint-disable no-console */ - console.log('Reset clicked!'); - }} - onClickTransactions={() => { - /* eslint-disable no-console */ - console.log('Transactions clicked!'); - }} - wallet_name='Virtual USD Wallet' - width='280' - /> - - ); - }, - { - notes, - } - ); From b72cde7365d90d065270af061131a259d734b2d7 Mon Sep 17 00:00:00 2001 From: Carol Sachdeva <58209918+carol-binary@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:39:12 +0800 Subject: [PATCH 11/20] error codes cleanup (#6550) --- .../src/components/buy-sell/buy-sell-modal.jsx | 2 +- packages/p2p/src/constants/api-error-codes.js | 10 ++++++++-- packages/p2p/src/stores/buy-sell-store.js | 3 ++- packages/p2p/src/stores/general-store.js | 7 ++++--- packages/p2p/src/stores/my-ads-store.js | 3 ++- packages/p2p/src/stores/my-profile-store.js | 3 ++- packages/p2p/src/stores/order-store.js | 17 +++++++++-------- 7 files changed, 28 insertions(+), 17 deletions(-) diff --git a/packages/p2p/src/components/buy-sell/buy-sell-modal.jsx b/packages/p2p/src/components/buy-sell/buy-sell-modal.jsx index e27d8f0f7e68..61182c726276 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-modal.jsx +++ b/packages/p2p/src/components/buy-sell/buy-sell-modal.jsx @@ -108,7 +108,7 @@ const BuySellModal = ({ table_type, selected_ad, should_show_popup, setShouldSho icon='IcAlertDanger' message={ - {buy_sell_store.form_error_code === api_error_codes.INSUFFICIENT_BALANCE ? ( + {buy_sell_store.form_error_code === api_error_codes.ORDER_CREATE_FAIL_CLIENT_BALANCE ? ( ) : ( error_message diff --git a/packages/p2p/src/constants/api-error-codes.js b/packages/p2p/src/constants/api-error-codes.js index 21870c78a30b..45b2a13f7fad 100644 --- a/packages/p2p/src/constants/api-error-codes.js +++ b/packages/p2p/src/constants/api-error-codes.js @@ -1,6 +1,12 @@ export const api_error_codes = Object.freeze({ ADVERT_SAME_LIMITS: 'AdvertSameLimits', + ADVERTISER_NOT_FOUND: 'AdvertiserNotFound', DUPLICATE_ADVERT: 'DuplicateAdvert', - MARKET_RATE_CHANGE: 'OrderCreateFailRateChanged', - INSUFFICIENT_BALANCE: 'OrderCreateFailClientBalance', + EXCESSIVE_VERIFICATION_FAILURES: 'ExcessiveVerificationFailures', + EXCESSIVE_VERIFICATION_REQUESTS: 'ExcessiveVerificationRequests', + INVALID_VERIFICATION_TOKEN: 'InvalidVerificationToken', + ORDER_EMAIL_VERIFICATION_REQUIRED: 'OrderEmailVerificationRequired', + ORDER_CREATE_FAIL_CLIENT_BALANCE: 'OrderCreateFailClientBalance', + PERMISSION_DENIED: 'PermissionDenied', + RESTRICTED_COUNTRY: 'RestrictedCountry', }); diff --git a/packages/p2p/src/stores/buy-sell-store.js b/packages/p2p/src/stores/buy-sell-store.js index 423de408d003..7df9e6072df0 100644 --- a/packages/p2p/src/stores/buy-sell-store.js +++ b/packages/p2p/src/stores/buy-sell-store.js @@ -7,6 +7,7 @@ import { textValidator, lengthValidator } from 'Utils/validations'; import { countDecimalPlaces } from 'Utils/string'; import { removeTrailingZeros } from 'Utils/format-value'; import BaseStore from 'Stores/base_store'; +import { api_error_codes } from '../constants/api-error-codes'; export default class BuySellStore extends BaseStore { @observable api_error_message = ''; @@ -286,7 +287,7 @@ export default class BuySellStore extends BaseStore { } } // Added a check to prevent console errors - } else if (response && response.error.code === 'PermissionDenied') { + } else if (response && response.error.code === api_error_codes.PERMISSION_DENIED) { this.root_store.general_store.setIsBlocked(true); } else { this.setApiErrorMessage(response?.error.message); diff --git a/packages/p2p/src/stores/general-store.js b/packages/p2p/src/stores/general-store.js index 35a53888ea48..eca4f0b9efc1 100644 --- a/packages/p2p/src/stores/general-store.js +++ b/packages/p2p/src/stores/general-store.js @@ -8,6 +8,7 @@ import { createExtendedOrderDetails } from 'Utils/orders'; import { init as WebsocketInit, requestWS, subscribeWS } from 'Utils/websocket'; import { order_list } from 'Constants/order-list'; import { buy_sell } from 'Constants/buy-sell'; +import { api_error_codes } from '../constants/api-error-codes'; export default class GeneralStore extends BaseStore { @observable active_index = 0; @@ -632,11 +633,11 @@ export default class GeneralStore extends BaseStore { this.setUserBlockedCount(blocked_by_count); } else { this.ws_subscriptions.advertiser_subscription.unsubscribe(); - if (response.error.code === 'RestrictedCountry') { + if (response.error.code === api_error_codes.RESTRICTED_COUNTRY) { this.setIsRestricted(true); - } else if (response.error.code === 'AdvertiserNotFound') { + } else if (response.error.code === api_error_codes.ADVERTISER_NOT_FOUND) { this.setIsAdvertiser(false); - } else if (response.error.code === 'PermissionDenied') { + } else if (response.error.code === api_error_codes.PERMISSION_DENIED) { this.setIsBlocked(true); this.setIsLoading(false); return; diff --git a/packages/p2p/src/stores/my-ads-store.js b/packages/p2p/src/stores/my-ads-store.js index 755c8a508e57..7c877f19ee21 100644 --- a/packages/p2p/src/stores/my-ads-store.js +++ b/packages/p2p/src/stores/my-ads-store.js @@ -7,6 +7,7 @@ import BaseStore from 'Stores/base_store'; import { countDecimalPlaces } from 'Utils/string'; import { decimalValidator, lengthValidator, rangeValidator, textValidator } from 'Utils/validations'; import { requestWS } from 'Utils/websocket'; +import { api_error_codes } from '../constants/api-error-codes'; export default class MyAdsStore extends BaseStore { @observable activate_deactivate_error_message = ''; @@ -379,7 +380,7 @@ export default class MyAdsStore extends BaseStore { floating_rate_store.setChangeAdAlert(should_update_ads); } } - } else if (response.error.code === 'PermissionDenied') { + } else if (response.error.code === api_error_codes.PERMISSION_DENIED) { general_store.setIsBlocked(true); } else { this.setApiErrorMessage(response.error.message); diff --git a/packages/p2p/src/stores/my-profile-store.js b/packages/p2p/src/stores/my-profile-store.js index 42095c18ae1e..701a8f8f2783 100644 --- a/packages/p2p/src/stores/my-profile-store.js +++ b/packages/p2p/src/stores/my-profile-store.js @@ -4,6 +4,7 @@ import { localize } from 'Components/i18next'; import { textValidator } from 'Utils/validations'; import BaseStore from 'Stores/base_store'; import { my_profile_tabs } from 'Constants/my-profile-tabs'; +import { api_error_codes } from '../constants/api-error-codes'; export default class MyProfileStore extends BaseStore { @observable active_tab = my_profile_tabs.MY_STATS; @@ -209,7 +210,7 @@ export default class MyProfileStore extends BaseStore { this.setContactInfo(p2p_advertiser_info.contact_info); this.setDefaultAdvertDescription(p2p_advertiser_info.default_advert_description); this.root_store.general_store.setShouldShowRealName(!!p2p_advertiser_info.show_name); - } else if (response.error.code === 'PermissionDenied') { + } else if (response.error.code === api_error_codes.PERMISSION_DENIED) { this.root_store.general_store.setIsBlocked(true); } else { this.setErrorMessage(response.error.message); diff --git a/packages/p2p/src/stores/order-store.js b/packages/p2p/src/stores/order-store.js index 9dc10ced822d..660580773ef2 100644 --- a/packages/p2p/src/stores/order-store.js +++ b/packages/p2p/src/stores/order-store.js @@ -3,6 +3,7 @@ import { action, computed, observable, reaction } from 'mobx'; import { createExtendedOrderDetails } from 'Utils/orders'; import { requestWS, subscribeWS } from 'Utils/websocket'; import { order_list } from 'Constants/order-list'; +import { api_error_codes } from '../constants/api-error-codes'; export default class OrderStore { constructor(root_store) { @@ -72,12 +73,12 @@ export default class OrderStore { }).then(response => { if (response) { if (response.error) { - if (response.error.code === 'OrderEmailVerificationRequired') { + if (response.error.code === api_error_codes.ORDER_EMAIL_VERIFICATION_REQUIRED) { clearTimeout(wait); const wait = setTimeout(() => this.setIsEmailVerificationModalOpen(true), 250); } else if ( - response?.error.code === 'InvalidVerificationToken' || - response?.error.code === 'ExcessiveVerificationRequests' + response?.error.code === api_error_codes.INVALID_VERIFICATION_TOKEN || + response?.error.code === api_error_codes.EXCESSIVE_VERIFICATION_REQUESTS ) { clearTimeout(wait); if (this.is_email_verification_modal_open) { @@ -88,7 +89,7 @@ export default class OrderStore { } this.setVerificationLinkErrorMessage(response.error.message); const wait = setTimeout(() => this.setIsInvalidVerificationLinkModalOpen(true), 230); - } else if (response?.error.code === 'ExcessiveVerificationFailures') { + } else if (response?.error.code === api_error_codes.EXCESSIVE_VERIFICATION_FAILURES) { if (this.is_invalid_verification_link_modal_open) { this.setIsInvalidVerificationLinkModalOpen(false); } @@ -227,7 +228,7 @@ export default class OrderStore { this.setOrders([...old_list, ...new_list]); } - } else if (response.error.code === 'PermissionDenied') { + } else if (response.error.code === api_error_codes.PERMISSION_DENIED) { this.root_store.general_store.setIsBlocked(true); } else { this.setApiErrorMessage(response.error.message); @@ -438,13 +439,13 @@ export default class OrderStore { clearTimeout(wait); const wait = setTimeout(() => this.setIsEmailLinkVerifiedModalOpen(true), 650); } else if ( - response.error.code === 'InvalidVerificationToken' || - response.error.code === 'ExcessiveVerificationRequests' + response.error.code === api_error_codes.INVALID_VERIFICATION_TOKEN || + response.error.code === api_error_codes.EXCESSIVE_VERIFICATION_REQUESTS ) { clearTimeout(wait); this.setVerificationLinkErrorMessage(response.error.message); const wait = setTimeout(() => this.setIsInvalidVerificationLinkModalOpen(true), 750); - } else if (response.error.code === 'ExcessiveVerificationFailures') { + } else if (response.error.code === api_error_codes.EXCESSIVE_VERIFICATION_FAILURES) { if (this.is_invalid_verification_link_modal_open) { this.setIsInvalidVerificationLinkModalOpen(false); } From 82a3e93ccde4d9528c4d815626a75c82037e4969 Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:39:35 +0800 Subject: [PATCH 12/20] Ameerul /Bug 76675 Deriv P2P notification disappears when we refresh the page (#6603) * fixed notifications on refresh in cashier page * removed old function for getting unseen notifications * added jsdoc for p2p_unseen_notifications * Update packages/cashier/src/stores/general-store.js Co-authored-by: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> Co-authored-by: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> --- packages/cashier/src/stores/general-store.js | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/cashier/src/stores/general-store.js b/packages/cashier/src/stores/general-store.js index a261a0d5bc80..698e69a0ecbb 100644 --- a/packages/cashier/src/stores/general-store.js +++ b/packages/cashier/src/stores/general-store.js @@ -1,6 +1,6 @@ import React from 'react'; import { action, computed, observable, reaction, when } from 'mobx'; -import { isCryptocurrency, getPropertyValue, routes } from '@deriv/shared'; +import { isCryptocurrency, isEmptyObject, getPropertyValue, routes } from '@deriv/shared'; import { localize } from '@deriv/translations'; import Constants from 'Constants/constants'; import CashierNotifications from 'Components/cashier-notifications'; @@ -72,6 +72,28 @@ export default class GeneralStore extends BaseStore { return this.is_p2p_visible && !this.root_store.client.is_eu; } + /** + * Gets the notifications from local storage, within p2p_settings, where it checks which notification has + * been seen. The number of unseen notifications is displayed in vertical tab, notifications count, for P2P. + * + * @returns {number} Notifications that have not been seen by the user. + */ + @computed + get p2p_unseen_notifications() { + const p2p_settings = JSON.parse(localStorage.getItem('p2p_settings') || '{}'); + const local_storage_settings = p2p_settings[this.root_store.client.loginid]; + + if (isEmptyObject(local_storage_settings)) { + return 0; + } + + const unseen_notifications = local_storage_settings.notifications.filter( + notification => !notification.is_seen + ); + + return unseen_notifications.length; + } + @action.bound showP2pInCashierOnboarding() { const { account_list, is_virtual } = this.root_store.client; @@ -284,6 +306,8 @@ export default class GeneralStore extends BaseStore { const { account_transfer, onramp, payment_agent, payment_agent_transfer, transaction_history } = modules.cashier; + this.setNotificationCount(this.p2p_unseen_notifications); + if (client.is_logged_in) { // avoid calling this again if (this.is_populating_values) { From 9fec69624858fcd1112eaee0c810db16d7a1b05c Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 13:40:00 +0400 Subject: [PATCH 13/20] likhith/ preventing over throttling of onfido token fetch API (#6495) * feat: incorporated Exponential_backoff logic * perf: :zap: invokes API and on failure triggers retry Co-authored-by: System Administrator --- .../ProofOfIdentity/onfido-sdk-view.jsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/account/src/Sections/Verification/ProofOfIdentity/onfido-sdk-view.jsx b/packages/account/src/Sections/Verification/ProofOfIdentity/onfido-sdk-view.jsx index d19dbf25c584..808ff4254134 100644 --- a/packages/account/src/Sections/Verification/ProofOfIdentity/onfido-sdk-view.jsx +++ b/packages/account/src/Sections/Verification/ProofOfIdentity/onfido-sdk-view.jsx @@ -15,6 +15,7 @@ const OnfidoSdkView = ({ country_code, documents_supported, handleViewComplete, const [missing_personal_details, setMissingPersonalDetails] = React.useState(false); const [is_status_loading, setStatusLoading] = React.useState(true); const [retry_count, setRetryCount] = React.useState(0); + const token_timeout_ref = React.useRef(); // IDV country code - Alpha ISO2. Onfido country code - Alpha ISO3 // Ensures that any form of country code passed here is supported. @@ -145,8 +146,7 @@ const OnfidoSdkView = ({ country_code, documents_supported, handleViewComplete, } }; - React.useEffect(() => { - // retry state will re-run the token fetching + const fetchServiceToken = () => { getOnfidoServiceToken().then(response_token => { if (response_token.error) { handleError(response_token.error); @@ -158,7 +158,20 @@ const OnfidoSdkView = ({ country_code, documents_supported, handleViewComplete, setStatusLoading(false); }); } + if (token_timeout_ref.current) clearTimeout(token_timeout_ref.current); }); + }; + + React.useEffect(() => { + // retry state will re-run the token fetching + if (retry_count === 0) { + fetchServiceToken(); + } else if (retry_count !== 0 && retry_count < 3) { + // Incorporating Exponential_backoff algo to prevent immediate throttling + token_timeout_ref.current = setTimeout(() => { + fetchServiceToken(); + }, Math.pow(2, retry_count) + Math.random() * 1000); + } }, [getOnfidoServiceToken, initOnfido, retry_count]); let component_to_load; From 7351bbbf5ace0f2b1be9bf0a70bfd333523cad3e Mon Sep 17 00:00:00 2001 From: Bahar Date: Wed, 19 Oct 2022 17:40:26 +0800 Subject: [PATCH 14/20] remove_horizontal_scroll_of_onmapp_in_firefox (#6715) --- packages/cashier/src/pages/on-ramp/on-ramp.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cashier/src/pages/on-ramp/on-ramp.scss b/packages/cashier/src/pages/on-ramp/on-ramp.scss index b61878f877b9..95b71a743084 100644 --- a/packages/cashier/src/pages/on-ramp/on-ramp.scss +++ b/packages/cashier/src/pages/on-ramp/on-ramp.scss @@ -73,7 +73,8 @@ position: relative; white-space: nowrap; margin-top: auto; - grid-area: payment-icons; + grid-row: payment-icons; + grid-column-start: payment-icons; overflow: hidden; &-shadow { From 443ddf29d9cff6e7ebd83b8510947a14265b9836 Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:40:57 +0800 Subject: [PATCH 15/20] Ameerul /Bug 74362 Give feedback button does nothing when user in existing order page (#6456) * added new function in notifications store to get order id and show rating modal from p2p side * fixed spelling * renamed order_props to p2p_order_props and added toggleNotificationsModal to onClick for give feedback * fixed give action onClick for give feedback button in general store * added new function to redirect to order details page, changed logic for handling completed order notifications * removed text from Give Feedback * fixed notifications count bell bug when rating order, and refactored logic * removed setP2POrderConfig from order-details, moved to app.jsx in useEffect * called setP2POrderProps in order-details when unmounted so the id is set to null * renamed notification_action to notification_redirect_action * removed commented out console log --- .../src/pages/p2p-cashier/p2p-cashier.jsx | 4 ++ .../core/src/Stores/notification-store.js | 42 +++++++++++++++++-- packages/p2p/src/components/app.jsx | 5 +++ .../order-details/order-details.jsx | 5 +++ packages/p2p/src/stores/general-store.js | 17 ++++++-- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/packages/cashier/src/pages/p2p-cashier/p2p-cashier.jsx b/packages/cashier/src/pages/p2p-cashier/p2p-cashier.jsx index dc584d670e05..d17c48f49508 100644 --- a/packages/cashier/src/pages/p2p-cashier/p2p-cashier.jsx +++ b/packages/cashier/src/pages/p2p-cashier/p2p-cashier.jsx @@ -28,6 +28,7 @@ const P2PCashier = ({ removeNotificationByKey, removeNotificationMessage, residence, + setP2POrderProps, setNotificationCount, setCurrentFocus, balance, @@ -140,6 +141,7 @@ const P2PCashier = ({ setNotificationCount={setNotificationCount} setOrderId={setQueryOrder} setOnRemount={setOnRemount} + setP2POrderProps={setP2POrderProps} should_show_verification={/verification/.test(location.hash)} verification_action={action_param} verification_code={code_param} @@ -169,6 +171,7 @@ P2PCashier.propTypes = { residence: PropTypes.string, setNotificationCount: PropTypes.func, setCurrentFocus: PropTypes.func, + setP2POrderProps: PropTypes.func, }; export default connect(({ client, common, modules, notifications, ui }) => ({ @@ -189,6 +192,7 @@ export default connect(({ client, common, modules, notifications, ui }) => ({ residence: client.residence, setNotificationCount: modules.cashier.general_store.setNotificationCount, setOnRemount: modules.cashier.general_store.setOnRemount, + setP2POrderProps: notifications.setP2POrderProps, is_mobile: ui.is_mobile, setCurrentFocus: ui.setCurrentFocus, current_focus: ui.current_focus, diff --git a/packages/core/src/Stores/notification-store.js b/packages/core/src/Stores/notification-store.js index 2e8856eb9997..1cebb758f9e8 100644 --- a/packages/core/src/Stores/notification-store.js +++ b/packages/core/src/Stores/notification-store.js @@ -37,6 +37,7 @@ export default class NotificationStore extends BaseStore { @observable push_notifications = []; @observable client_notifications = {}; @observable should_show_popups = true; + @observable p2p_order_props = {}; constructor(root_store) { super({ root_store }); @@ -55,6 +56,7 @@ export default class NotificationStore extends BaseStore { root_store.common?.selected_contract_type, root_store.client.is_eu, root_store.client.has_enabled_two_fa, + this.p2p_order_props.order_id, ], async () => { if ( @@ -435,14 +437,41 @@ export default class NotificationStore extends BaseStore { } } + @action.bound showCompletedOrderNotification(advertiser_name, order_id) { const notification_key = `order-${order_id}`; + const notification_redirect_action = + routes.cashier_p2p === window.location.pathname + ? { + onClick: () => { + this.p2p_order_props.redirectToOrderDetails(order_id); + this.setP2POrderProps({ + ...this.p2p_order_props, + order_id, + }); + if (this.is_notifications_visible) this.toggleNotificationsModal(); + this.refreshNotifications(); + }, + text: localize('Give feedback'), + } + : { + route: `${routes.cashier_p2p}?order=${order_id}`, + text: localize('Give feedback'), + }; + this.addNotificationMessage({ - action: { - route: `${routes.cashier_p2p}?order=${order_id}`, - text: localize('Give feedback'), - }, + action: + this.p2p_order_props?.order_id === order_id + ? { + onClick: () => { + this.p2p_order_props.setIsRatingModalOpen(true); + if (this.is_notifications_visible) this.toggleNotificationsModal(); + this.refreshNotifications(); + }, + text: localize('Give feedback'), + } + : notification_redirect_action, header: , key: notification_key, message: ( @@ -1114,6 +1143,11 @@ export default class NotificationStore extends BaseStore { this.client_notifications = notifications; } + @action.bound + setP2POrderProps(p2p_order_props) { + this.p2p_order_props = p2p_order_props; + } + @action.bound setShouldShowPopups(should_show_popups) { this.should_show_popups = should_show_popups; diff --git a/packages/p2p/src/components/app.jsx b/packages/p2p/src/components/app.jsx index c484bd41e3cc..c718f88deef9 100644 --- a/packages/p2p/src/components/app.jsx +++ b/packages/p2p/src/components/app.jsx @@ -67,6 +67,11 @@ const App = props => { general_store.redirectTo('orders'); order_store.setOrderId(order_id); } + general_store.props.setP2POrderProps({ + order_id, + redirectToOrderDetails: general_store.redirectToOrderDetails, + setIsRatingModalOpen: order_store.setIsRatingModalOpen, + }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [order_id]); diff --git a/packages/p2p/src/components/order-details/order-details.jsx b/packages/p2p/src/components/order-details/order-details.jsx index f6fc536db5ef..2e569955f784 100644 --- a/packages/p2p/src/components/order-details/order-details.jsx +++ b/packages/p2p/src/components/order-details/order-details.jsx @@ -92,6 +92,11 @@ const OrderDetails = observer(() => { disposeReactions(); order_store.setOrderPaymentMethodDetails(undefined); order_store.setOrderId(null); + general_store.props.setP2POrderProps({ + order_id: order_store.order_id, + redirectToOrderDetails: general_store.redirectToOrderDetails, + setIsRatingModalOpen: order_store.setIsRatingModalOpen, + }); }; }, []); // eslint-disable-line react-hooks/exhaustive-deps diff --git a/packages/p2p/src/stores/general-store.js b/packages/p2p/src/stores/general-store.js index eca4f0b9efc1..89711126a59c 100644 --- a/packages/p2p/src/stores/general-store.js +++ b/packages/p2p/src/stores/general-store.js @@ -232,7 +232,17 @@ export default class GeneralStore extends BaseStore { this.updateP2pNotifications(notifications); } + @action.bound + redirectToOrderDetails(order_id) { + const { order_store } = this.root_store; + this.redirectTo('orders'); + this.setOrderTableType(order_list.INACTIVE); + order_store.setOrderId(order_id); + } + + @action.bound showCompletedOrderNotification(advertiser_name, order_id) { + const { order_store } = this.root_store; const notification_key = `order-${order_id}`; // we need to refresh notifications in notifications-store in the case of a bug when user closes the notification, the notification count is not synced up with the closed notification @@ -241,9 +251,10 @@ export default class GeneralStore extends BaseStore { this.props.addNotificationMessage({ action: { onClick: () => { - this.redirectTo('orders'); - this.setOrderTableType(order_list.INACTIVE); - this.root_store.order_store.setOrderId(order_id); + if (order_store.order_id === order_id) { + order_store.setIsRatingModalOpen(true); + } + this.redirectToOrderDetails(order_id); }, text: localize('Give feedback'), }, From d1f637779ba6f4459a69b8d4f6e2ea4d8ea6e71f Mon Sep 17 00:00:00 2001 From: adrienne-deriv <103016120+adrienne-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:41:20 +0800 Subject: [PATCH 16/20] Added margin spacing between advertiser page header and description (#6420) * Added margin spacing between advertiser page header and description * Aligned avatar icon to flex-start * time to fix merge conflicts --- .../components/advertiser-page/advertiser-page.scss | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page.scss b/packages/p2p/src/components/advertiser-page/advertiser-page.scss index 262673c0da55..53e699a7779a 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page.scss +++ b/packages/p2p/src/components/advertiser-page/advertiser-page.scss @@ -84,12 +84,16 @@ @include mobile { display: inline-grid; grid-template-columns: auto auto; - margin: 0 0 1rem; + margin: 0 0 3rem; .dp2p-avatar { - align-self: flex-start; - margin-top: 0.6rem; - margin-right: 0.7rem; + align-self: center; + + @include mobile { + align-self: flex-start; + margin-top: 0.6rem; + margin-right: 0.7rem; + } } } } From 0fa3f8d7d5a551caf406d221391afa74d13cd021 Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:41:47 +0800 Subject: [PATCH 17/20] Ameerul /Bug 69674 Improve floating rate field to handle large rate values (#6286) * changed the margin-top for mobile view for buy-sell * merging upstream master * changed the payment methods list modal and wrapped the text for long bank names * reverted changes * changed floating rate field and ad type styling * removed code from other PR * changed input field value text * removed local currency from market rate * changed floating rate spec file * changed floating rate msg font size to small * fixed font size --- .../floating-rate/__test__/floating-rate.spec.js | 2 +- .../p2p/src/components/floating-rate/floating-rate.jsx | 5 ++--- .../p2p/src/components/floating-rate/floating-rate.scss | 2 +- packages/p2p/src/components/my-ads/ad-type.scss | 8 ++++++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js b/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js index 8cbd16743ff7..36c6b09c0443 100644 --- a/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js +++ b/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js @@ -39,6 +39,6 @@ describe('', () => { it('should render the exchange rate in hint', () => { render(); - expect(screen.getByText('1 AED = 100.00 INR')).toBeInTheDocument(); + expect(screen.getByText('1 AED = 100.00')).toBeInTheDocument(); }); }); diff --git a/packages/p2p/src/components/floating-rate/floating-rate.jsx b/packages/p2p/src/components/floating-rate/floating-rate.jsx index 2888ddd6635b..0964d58e51d8 100644 --- a/packages/p2p/src/components/floating-rate/floating-rate.jsx +++ b/packages/p2p/src/components/floating-rate/floating-rate.jsx @@ -86,15 +86,14 @@ const FloatingRate = ({ 1 {fiat_currency} ={' '} - {removeTrailingZeros(formatMoney(local_currency, floating_rate_store.exchange_rate, true, 6))}{' '} - {local_currency} + {removeTrailingZeros(formatMoney(local_currency, floating_rate_store.exchange_rate, true, 6))}
diff --git a/packages/p2p/src/components/floating-rate/floating-rate.scss b/packages/p2p/src/components/floating-rate/floating-rate.scss index 97fa6ffeb1de..98951b6f8017 100644 --- a/packages/p2p/src/components/floating-rate/floating-rate.scss +++ b/packages/p2p/src/components/floating-rate/floating-rate.scss @@ -91,7 +91,6 @@ height: 18px; left: 8px; top: 18px; - font-style: normal; flex: none; order: 2; flex-grow: 0; @@ -143,6 +142,7 @@ border: unset; background-color: unset; padding: unset; + font-size: small; &:focus { border-color: unset; } diff --git a/packages/p2p/src/components/my-ads/ad-type.scss b/packages/p2p/src/components/my-ads/ad-type.scss index f12ea13ea9c6..393cad2664ae 100644 --- a/packages/p2p/src/components/my-ads/ad-type.scss +++ b/packages/p2p/src/components/my-ads/ad-type.scss @@ -1,7 +1,11 @@ .ad-type { display: flex; + flex-direction: row; align-items: center; - justify-content: space-around; + + @include mobile { + justify-content: flex-end; + } &__badge { align-items: center; @@ -9,7 +13,7 @@ border: 1px solid var(--border-normal); display: flex; flex-direction: row; - margin: 0.25rem; + margin: 0.3rem 0.5rem 0.3rem 0; padding: 0.1rem 0.8rem; width: fit-content; } From 6578966014ccdf11d05a20264609b0af04fdb2cd Mon Sep 17 00:00:00 2001 From: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 13:42:12 +0400 Subject: [PATCH 18/20] fixed decimal point in buy/sell amount (#6645) --- .../src/components/buy-sell/buy-sell-form.jsx | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx b/packages/p2p/src/components/buy-sell/buy-sell-form.jsx index b6d2792f10c4..cca1a7d63fb9 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx +++ b/packages/p2p/src/components/buy-sell/buy-sell-form.jsx @@ -3,7 +3,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Formik, Field, Form } from 'formik'; import { HintBox, Icon, Input, Text } from '@deriv/components'; -import { getRoundedNumber, isDesktop, isMobile, useIsMounted } from '@deriv/shared'; +import { getDecimalPlaces, isDesktop, isMobile, useIsMounted } from '@deriv/shared'; import { reaction } from 'mobx'; import { observer, Observer } from 'mobx-react-lite'; import { localize, Localize } from 'Components/i18next'; @@ -12,6 +12,7 @@ import { useStores } from 'Stores'; import BuySellFormReceiveAmount from './buy-sell-form-receive-amount.jsx'; import PaymentMethodCard from '../my-profile/payment-methods/payment-method-card/payment-method-card.jsx'; import { floatingPointValidator } from 'Utils/validations'; +import { countDecimalPlaces } from 'Utils/string'; import { generateEffectiveRate, setDecimalPlaces, roundOffDecimal, removeTrailingZeros } from 'Utils/format-value'; const BuySellForm = props => { @@ -378,16 +379,16 @@ const BuySellForm = props => { } }} onChange={event => { - if (event.target.value === '') { - setFieldValue('amount', ''); - setInputAmount(''); + const { value } = event.target; + + if ( + countDecimalPlaces(value) > + getDecimalPlaces(buy_sell_store.account_currency) + ) { + setFieldValue('amount', parseFloat(input_amount)); } else { - const amount = getRoundedNumber( - event.target.value, - buy_sell_store.account_currency - ); - setFieldValue('amount', amount); - setInputAmount(amount); + setFieldValue('amount', parseFloat(value)); + setInputAmount(value); } }} required From acfa06c63acf237e8348bdd8693ba9ac6907d45d Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:42:39 +0800 Subject: [PATCH 19/20] Ameerul /Bug 64212 Order limit is not reflected correctly in the buy sell pop up modal (#6649) * fixed order limit issue for available amount user can spend * implemented comments * fixed sell order limit --- .../src/components/buy-sell/buy-sell-form.jsx | 16 +++++++--- .../my-profile-details-table.jsx | 15 ++++------ packages/p2p/src/stores/general-store.js | 29 +++++++++++++++++-- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx b/packages/p2p/src/components/buy-sell/buy-sell-form.jsx index cca1a7d63fb9..7cab1415558f 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx +++ b/packages/p2p/src/components/buy-sell/buy-sell-form.jsx @@ -36,10 +36,10 @@ const BuySellForm = props => { } = buy_sell_store?.advert || {}; const [input_amount, setInputAmount] = React.useState(min_order_amount_limit); + const { advertiser_buy_limit, advertiser_sell_limit, balance } = general_store; + const should_disable_field = - !buy_sell_store.is_buy_advert && - (parseFloat(general_store.balance) === 0 || - parseFloat(general_store.balance) < buy_sell_store.advert?.min_order_amount_limit); + !buy_sell_store.is_buy_advert && (parseFloat(balance) === 0 || parseFloat(balance) < min_order_amount_limit); const style = { borderColor: 'var(--brand-secondary)', @@ -111,6 +111,14 @@ const BuySellForm = props => { } }; + const getAdvertiserMaxLimit = () => { + if (buy_sell_store.is_buy_advert) { + if (advertiser_buy_limit < max_order_amount_limit_display) return roundOffDecimal(advertiser_buy_limit); + } else if (advertiser_sell_limit < max_order_amount_limit_display) + return roundOffDecimal(advertiser_sell_limit); + return max_order_amount_limit_display; + }; + return ( {rate_type === ad_type.FLOAT && !should_disable_field && ( @@ -361,7 +369,7 @@ const BuySellForm = props => { i18n_default_text='Limit: {{min}}–{{max}} {{currency}}' values={{ min: min_order_amount_limit_display, - max: max_order_amount_limit_display, + max: getAdvertiserMaxLimit(), currency: buy_sell_store.account_currency, }} /> diff --git a/packages/p2p/src/components/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.jsx b/packages/p2p/src/components/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.jsx index 6faa24c3f168..18442affa3dc 100644 --- a/packages/p2p/src/components/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.jsx +++ b/packages/p2p/src/components/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.jsx @@ -7,7 +7,8 @@ import { observer } from 'mobx-react-lite'; const MyProfileDetailsTable = () => { const { general_store, my_profile_store } = useStores(); - const { daily_buy, daily_buy_limit, daily_sell, daily_sell_limit } = my_profile_store.advertiser_info; + const { daily_buy_limit, daily_sell_limit } = my_profile_store.advertiser_info; + const { advertiser_buy_limit, advertiser_sell_limit, client } = general_store; return (
@@ -23,7 +24,7 @@ const MyProfileDetailsTable = () => { - + @@ -31,11 +32,7 @@ const MyProfileDetailsTable = () => { - + @@ -52,7 +49,7 @@ const MyProfileDetailsTable = () => { - + @@ -61,7 +58,7 @@ const MyProfileDetailsTable = () => { diff --git a/packages/p2p/src/stores/general-store.js b/packages/p2p/src/stores/general-store.js index 89711126a59c..7dff5e1933e9 100644 --- a/packages/p2p/src/stores/general-store.js +++ b/packages/p2p/src/stores/general-store.js @@ -14,6 +14,8 @@ export default class GeneralStore extends BaseStore { @observable active_index = 0; @observable active_notification_count = 0; @observable advertiser_id = null; + @observable advertiser_buy_limit = null; + @observable advertiser_sell_limit = null; @observable block_unblock_user_error = ''; @observable balance; @observable inactive_notification_count = 0; @@ -440,6 +442,16 @@ export default class GeneralStore extends BaseStore { this.advertiser_id = advertiser_id; } + @action.bound + setAdvertiserBuyLimit(advertiser_buy_limit) { + this.advertiser_buy_limit = advertiser_buy_limit; + } + + @action.bound + setAdvertiserSellLimit(advertiser_sell_limit) { + this.advertiser_sell_limit = advertiser_sell_limit; + } + @action.bound setAppProps(props) { this.props = props; @@ -631,11 +643,24 @@ export default class GeneralStore extends BaseStore { @action.bound updateAdvertiserInfo(response) { - const { blocked_until, blocked_by_count, id, is_approved, is_blocked, is_listed, name } = - response?.p2p_advertiser_info || {}; + const { + daily_buy, + daily_buy_limit, + daily_sell, + daily_sell_limit, + blocked_until, + blocked_by_count, + id, + is_approved, + is_blocked, + is_listed, + name, + } = response?.p2p_advertiser_info || {}; if (!response.error) { this.setAdvertiserId(id); + this.setAdvertiserBuyLimit(daily_buy_limit - daily_buy); + this.setAdvertiserSellLimit(daily_sell_limit - daily_sell); this.setIsAdvertiser(!!is_approved); this.setIsAdvertiserBlocked(!!is_blocked); this.setIsListed(!!is_listed); From 79e51826bb3115394c97cf5b985d6b7397252666 Mon Sep 17 00:00:00 2001 From: ameerul-deriv <103412909+ameerul-deriv@users.noreply.github.com> Date: Wed, 19 Oct 2022 17:47:23 +0800 Subject: [PATCH 20/20] forced opacity for full page modal quick add (#6681) --- packages/p2p/src/components/my-ads/my-ads.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/p2p/src/components/my-ads/my-ads.scss b/packages/p2p/src/components/my-ads/my-ads.scss index e38f6d7983e2..b516ab207fca 100644 --- a/packages/p2p/src/components/my-ads/my-ads.scss +++ b/packages/p2p/src/components/my-ads/my-ads.scss @@ -28,6 +28,9 @@ padding-top: 0.4rem; } } + .dc-mobile-full-page-modal { + opacity: 1 !important; + } } .dc-input__wrapper {