Skip to content

Commit

Permalink
fix(wallets): 🚑 fix platform status badge
Browse files Browse the repository at this point in the history
  • Loading branch information
heorhi-deriv committed Oct 21, 2024
1 parent 17cdf1a commit 4fb5265
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 97 deletions.
20 changes: 13 additions & 7 deletions packages/api-v2/src/hooks/useTradingPlatformStatus.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CFD_PLATFORMS } from '@deriv/shared';
import { useCallback } from 'react';
import useAuthorizedQuery from '../useAuthorizedQuery';
import useQuery from '../useQuery';

Expand All @@ -24,14 +25,19 @@ const useTradingPlatformStatus = () => {
* @param platform The platform identifier (e.g., 'ctrader', 'dxtrade', 'mt5').
* @returns The status of the identified platform ('active', 'maintenance', 'unavailable').
*/
const getPlatformStatus = (platform: string) => {
const platformStatus =
platform === CFD_PLATFORMS.MT5 || platform === CFD_PLATFORMS.DXTRADE || platform === CFD_PLATFORMS.CTRADER
? tradingPlatformStatusData?.find((status: TPlatformStatus) => status.platform === platform)?.status
: undefined; // cashier may pass non-cfd platform (i.e. doughflow, p2p, paymentagent, etc) which doesn't have status property
const getPlatformStatus = useCallback(
(platform: string) => {
const platformStatus =
platform === CFD_PLATFORMS.MT5 ||
platform === CFD_PLATFORMS.DXTRADE ||
platform === CFD_PLATFORMS.CTRADER
? tradingPlatformStatusData?.find((status: TPlatformStatus) => status.platform === platform)?.status
: undefined; // cashier may pass non-cfd platform (i.e. doughflow, p2p, paymentagent, etc) which doesn't have status property

return platformStatus;
};
return platformStatus;
},
[tradingPlatformStatusData]
);

return {
...rest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import React, { useCallback, useRef } from 'react';
import { Formik } from 'formik';
import { Localize } from '@deriv-com/translations';
import { Button, Loader, useDevice } from '@deriv-com/ui';
import { MT5_ACCOUNT_STATUS, TRADING_PLATFORM_STATUS } from '../../../../../cfd/constants';
import { useTransfer } from '../../provider';
import type { TAccount, TInitialTransferFormValues } from '../../types';
import type { TInitialTransferFormValues } from '../../types';
import { TransferFormAmountInput } from '../TransferFormAmountInput';
import { TransferFormDropdown } from '../TransferFormDropdown';
import { TransferMessages } from '../TransferMessages';
import './TransferForm.scss';

const TransferForm = () => {
const { isDesktop } = useDevice();
const { activeWallet, isLoading, requestTransferBetweenAccounts } = useTransfer();
const { activeWallet, hasPlatformStatus, isLoading, requestTransferBetweenAccounts } = useTransfer();
const mobileAccountsListRef = useRef<HTMLDivElement | null>(null);

const initialValues: TInitialTransferFormValues = {
Expand All @@ -29,54 +28,48 @@ const TransferForm = () => {
[requestTransferBetweenAccounts]
);

const isAccountUnavailable = (account: TAccount) =>
account?.status === TRADING_PLATFORM_STATUS.UNAVAILABLE ||
account?.status === MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE;

const hasPlatformStatus = (values: TInitialTransferFormValues) =>
isAccountUnavailable(values.fromAccount) || isAccountUnavailable(values.toAccount);
if (isLoading) return <Loader />;

return (
<div className='wallets-transfer'>
<Formik initialValues={initialValues} onSubmit={onSubmit}>
{({ handleSubmit, values }) => (
<form className='wallets-transfer__form' onSubmit={handleSubmit}>
<div className='wallets-transfer__fields'>
<div className='wallets-transfer__fields-section'>
<TransferFormAmountInput fieldName='fromAmount' />
<TransferFormDropdown
fieldName='fromAccount'
mobileAccountsListRef={mobileAccountsListRef}
/>
{({ handleSubmit, values }) => {
const { fromAccount, fromAmount, isError, toAccount, toAmount } = values;
const isTransferBtnDisabled =
!fromAmount || !toAmount || isError || [fromAccount, toAccount].some(hasPlatformStatus);

return (
<form className='wallets-transfer__form' onSubmit={handleSubmit}>
<div className='wallets-transfer__fields'>
<div className='wallets-transfer__fields-section'>
<TransferFormAmountInput fieldName='fromAmount' />
<TransferFormDropdown
fieldName='fromAccount'
mobileAccountsListRef={mobileAccountsListRef}
/>
</div>
<TransferMessages />
<div className='wallets-transfer__fields-section'>
<TransferFormAmountInput fieldName='toAmount' />
<TransferFormDropdown
fieldName='toAccount'
mobileAccountsListRef={mobileAccountsListRef}
/>
</div>
</div>
<TransferMessages />
<div className='wallets-transfer__fields-section'>
<TransferFormAmountInput fieldName='toAmount' />
<TransferFormDropdown
fieldName='toAccount'
mobileAccountsListRef={mobileAccountsListRef}
/>
<div className='wallets-transfer__submit-button' data-testid='dt_transfer_form_submit_btn'>
<Button
borderWidth='sm'
disabled={isTransferBtnDisabled}
size={isDesktop ? 'lg' : 'md'}
textSize={isDesktop ? 'md' : 'sm'}
type='submit'
>
<Localize i18n_default_text='Transfer' />
</Button>
</div>
</div>
<div className='wallets-transfer__submit-button' data-testid='dt_transfer_form_submit_btn'>
<Button
borderWidth='sm'
disabled={
!values.fromAmount ||
!values.toAmount ||
values.isError ||
hasPlatformStatus(values)
}
size={isDesktop ? 'lg' : 'md'}
textSize={isDesktop ? 'md' : 'sm'}
type='submit'
>
<Localize i18n_default_text='Transfer' />
</Button>
</div>
</form>
)}
</form>
);
}}
</Formik>
{/* Portal for accounts list in mobile view */}
<div className='wallets-transfer__mobile-accounts-list' ref={mobileAccountsListRef} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe('<TransferForm />', () => {
it('should test that transfer button is disabled when fromAmount is 0', async () => {
(useTransfer as jest.Mock).mockReturnValue({
activeWallet: mockAccounts[0],
hasPlatformStatus: jest.fn(),
isLoading: false,
requestTransferBetweenAccounts: jest.fn(),
});
Expand All @@ -88,6 +89,7 @@ describe('<TransferForm />', () => {
it('should test that transfer button is disabled when toAmount is 0', async () => {
(useTransfer as jest.Mock).mockReturnValue({
activeWallet: mockAccounts[0],
hasPlatformStatus: jest.fn(),
isLoading: false,
requestTransferBetweenAccounts: jest.fn(),
});
Expand Down Expand Up @@ -122,6 +124,7 @@ describe('<TransferForm />', () => {

(useTransfer as jest.Mock).mockReturnValue({
activeWallet: mockAccounts[0],
hasPlatformStatus: jest.fn(),
isLoading: false,
requestTransferBetweenAccounts: dummyRequest,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@ import { Text, useDevice } from '@deriv-com/ui';
import { WalletCurrencyCard, WalletListCardBadge, WalletMarketCurrencyIcon } from '../../../../../../components';
import { TPlatforms } from '../../../../../../types';
import { PlatformStatusBadge } from '../../../../../cfd/components/PlatformStatusBadge';
import { TRADING_PLATFORM_STATUS } from '../../../../../cfd/constants';
import type { TAccount } from '../../types';
import './TransferFormAccountCard.scss';

type TProps = {
account?: TAccount;
hasPlatformStatus: (account: TAccount) => boolean;
type?: 'input' | 'modal';
};

const TransferFormAccountCard: React.FC<TProps> = ({ account, type = 'modal' }) => {
const TransferFormAccountCard: React.FC<TProps> = ({ account, hasPlatformStatus, type = 'modal' }) => {
const { isDesktop } = useDevice();
const isInput = type === 'input';
const isModal = type === 'modal';

const hasPlatformStatus =
account?.status === TRADING_PLATFORM_STATUS.UNAVAILABLE || TRADING_PLATFORM_STATUS.MAINTENANCE;

return (
<div
className={classNames('wallets-transfer-form-account-card', {
Expand Down Expand Up @@ -55,24 +52,25 @@ const TransferFormAccountCard: React.FC<TProps> = ({ account, type = 'modal' })
<Text as='p' size={isInput ? '2xs' : 'sm'} weight='bold'>
{account?.accountName}
</Text>
<Text size={isInput ? '2xs' : 'xs'}>
<Localize
i18n_default_text='Balance: {{balance}}'
values={{
balance: account?.displayBalance,
}}
{!hasPlatformStatus(account) && (
<Text size={isInput ? '2xs' : 'xs'}>
<Localize
i18n_default_text='Balance: {{balance}}'
values={{
balance: account?.displayBalance,
}}
/>
</Text>
)}
{isModal && hasPlatformStatus(account) && (
<PlatformStatusBadge
badgeSize='sm'
cashierAccount={account}
className='wallets-transfer-form-account-card--badge'
/>
</Text>
)}
</div>

{account?.status && hasPlatformStatus && (
<PlatformStatusBadge
badgeSize='sm'
cashierAccount={account}
className='wallets-transfer-form-account-card--badge'
/>
)}

{isModal && !!account?.demo_account && (
<div className='wallets-transfer-form-account-card__modal-badge'>
<WalletListCardBadge />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ describe('TransferFormAccountCard', () => {
);

it('should render without crashing', () => {
render(<TransferFormAccountCard account={undefined} type={undefined} />, { wrapper });
render(<TransferFormAccountCard account={undefined} hasPlatformStatus={jest.fn()} type={undefined} />, {
wrapper,
});

expect(screen.queryByText('Test Account')).not.toBeInTheDocument();
expect(screen.queryByText('Balance: 1000 USD')).not.toBeInTheDocument();
Expand All @@ -52,6 +54,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='modal'
/>,
{ wrapper }
Expand All @@ -70,6 +73,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='modal'
/>,
{ wrapper }
Expand All @@ -90,6 +94,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='modal'
/>,
{ wrapper }
Expand All @@ -108,6 +113,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='input'
/>,
{ wrapper }
Expand All @@ -126,6 +132,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='input'
/>,
{ wrapper }
Expand All @@ -142,6 +149,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='modal'
/>,
{ wrapper }
Expand All @@ -153,6 +161,7 @@ describe('TransferFormAccountCard', () => {
<TransferFormAccountCard
// @ts-expect-error - since this is a mock, we only need partial properties of the hook
account={mockNewAccount}
hasPlatformStatus={jest.fn()}
type='input'
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type TProps = {
accountsList: TAccountsList;
activeWallet: TAccount;
fromAccount?: TAccount;
hasPlatformStatus: (account: TAccount) => boolean;
isFromAccountDropdown: boolean;
label: string;
onSelect: (value?: TAccount) => void;
Expand All @@ -30,6 +31,7 @@ const TransferFormAccountSelection: React.FC<TProps> = ({
accountsList,
activeWallet,
fromAccount,
hasPlatformStatus,
isFromAccountDropdown,
label,
onSelect,
Expand Down Expand Up @@ -126,7 +128,10 @@ const TransferFormAccountSelection: React.FC<TProps> = ({
modal.hide();
}}
>
<TransferFormAccountCard account={account} />
<TransferFormAccountCard
account={account}
hasPlatformStatus={hasPlatformStatus}
/>
</button>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe('TransferFormAccountSelection', () => {
wallets: [{ accountName: 'Wallet 1', currencyConfig: { display_code: 'GBP' }, loginid: 'CRW123' }],
},
activeWallet: { accountName: 'Active Wallet', currencyConfig: { display_code: 'USD' }, loginid: 'CR123' },
hasPlatformStatus: jest.fn(),
label: 'Transfer from',
onSelect: mockOnSelect,
selectedAccount: { loginid: 'CR123' },
Expand All @@ -55,6 +56,7 @@ describe('TransferFormAccountSelection', () => {
},
activeWallet: undefined,
fromAccount: undefined,
hasPlatformStatus: jest.fn(),
label: 'Transfer to',
onSelect: mockOnSelect,
selectedAccount: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ const TransferFormAmountInput: React.FC<TProps> = ({ fieldName }) => {
const { fromAccount, fromAmount, toAccount, toAmount } = values;
const { localize } = useTranslations();

const { USDExchangeRates, activeWallet, activeWalletExchangeRates, refetchAccountLimits, refetchExchangeRates } =
useTransfer();
const {
USDExchangeRates,
activeWallet,
activeWalletExchangeRates,
hasPlatformStatus,
refetchAccountLimits,
refetchExchangeRates,
} = useTransfer();

const refetchExchangeRatesAndLimits = useCallback(() => {
refetchAccountLimits();
Expand All @@ -35,7 +41,8 @@ const TransferFormAmountInput: React.FC<TProps> = ({ fieldName }) => {
const hasFunds = Number(fromAccount?.balance) > 0;
const isFromAmountField = fieldName === 'fromAmount';
const isSameCurrency = fromAccount?.currency === toAccount?.currency;
const isAmountInputDisabled = !hasFunds || (fieldName === 'toAmount' && !toAccount);
const isAmountInputDisabled =
!hasFunds || (fieldName === 'toAmount' && !toAccount) || [fromAccount, toAccount].some(hasPlatformStatus);
const isAmountFieldActive = fieldName === values.activeAmountFieldName;
const isTimerVisible = !isFromAmountField && toAccount && !isSameCurrency && fromAmount > 0 && toAmount > 0;
const prevTimerVisible = useRef(isTimerVisible);
Expand Down
Loading

0 comments on commit 4fb5265

Please sign in to comment.