Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WALL] george / WALL-4857 / Broken Server maintenance badge for MT5 Demo account on Transfer page #17238

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading