diff --git a/src/components/error-component/error-component.tsx b/src/components/error-component/error-component.tsx index 88d71527..6459afd7 100644 --- a/src/components/error-component/error-component.tsx +++ b/src/components/error-component/error-component.tsx @@ -23,15 +23,12 @@ const ErrorComponent = ({ should_clear_error_on_click, setError, redirect_to = standalone_routes.trade, - should_show_refresh = true, should_redirect = true, }: Partial) => { - const refresh_message = should_show_refresh ? localize('Please refresh this page to continue.') : ''; - return ( window.location.reload())} diff --git a/src/components/layout/header/account-switcher.tsx b/src/components/layout/header/account-switcher.tsx index f548c486..dd6cc7d8 100644 --- a/src/components/layout/header/account-switcher.tsx +++ b/src/components/layout/header/account-switcher.tsx @@ -1,303 +1,86 @@ import React, { useEffect } from 'react'; import { lazy, Suspense, useMemo } from 'react'; -import classNames from 'classnames'; -import clsx from 'clsx'; import { observer } from 'mobx-react-lite'; import { CurrencyIcon } from '@/components/currency/currency-icon'; -import RectangleSkeleton from '@/components/loader/rectangle-skeleton'; -import { getDecimalPlaces, standalone_routes } from '@/components/shared'; +import { addComma, getDecimalPlaces } from '@/components/shared'; import Popover from '@/components/shared_ui/popover'; import { api_base } from '@/external/bot-skeleton'; -import useActiveAccount from '@/hooks/api/account/useActiveAccount'; import { useOauth2 } from '@/hooks/auth/useOauth2'; import { useApiBase } from '@/hooks/useApiBase'; import { useStore } from '@/hooks/useStore'; import { waitForDomElement } from '@/utils/dom-observer'; -import { LegacyDerivIcon, LegacyLogout1pxIcon } from '@deriv/quill-icons/Legacy'; -import { Localize, localize } from '@deriv-com/translations'; -import { AccountSwitcher as UIAccountSwitcher, Button, Divider, Loader, Text, useDevice } from '@deriv-com/ui'; +import { localize } from '@deriv-com/translations'; +import { AccountSwitcher as UIAccountSwitcher, Loader, useDevice } from '@deriv-com/ui'; +import DemoAccounts from './common/demo-accounts'; +import RealAccounts from './common/real-accounts'; +import { TAccountSwitcher, TAccountSwitcherProps, TModifiedAccount } from './common/types'; +import { LOW_RISK_COUNTRIES } from './utils'; import './account-switcher.scss'; const AccountInfoWallets = lazy(() => import('./wallets/account-info-wallets')); -type TModifiedAccount = ReturnType['accountList'][number] & { - balance: string; - currencyLabel: string; - icon: React.ReactNode; - isVirtual: boolean; - isActive: boolean; - loginid: number; - currency: string; -}; -type TAccountSwitcherProps = { - isVirtual?: boolean; - modifiedAccountList: TModifiedAccount[]; - switchAccount: (loginId: number) => void; - modifiedCRAccountList?: TModifiedAccount[]; - modifiedMFAccountList?: TModifiedAccount[]; - activeLoginId?: string; -}; - -type TAccountSwitcher = { - activeAccount: ReturnType['data']; - is_dialog_on: boolean; - toggleDialog: () => void; -}; - const tabs_labels = { demo: localize('Demo'), real: localize('Real'), }; -const no_account = { - currency: ' ', - currencyLabel: 'Options & Multipliers', - is_virtual: 1, - loginid: '', - is_disabled: false, - balance: '', - icon: , - isActive: false, - isVirtual: true, -}; - -const NoEuAccounts = ({ isVirtual, tabs_labels }) => { - return ( - -
- {}} /> - -
-
- ); -}; - -const RenderAccountItems = observer( - ({ - isVirtual, - modifiedAccountList, - modifiedCRAccountList, - modifiedMFAccountList, - switchAccount, - activeLoginId, - }: TAccountSwitcherProps) => { - const { client } = useStore(); - - const show_manage_button = client?.loginid?.includes('CR') || client?.loginid?.includes('MF'); - - const account_switcher_title_non_eu = - modifiedMFAccountList?.length === 0 ? localize('Deriv accounts') : localize('Non-Eu Deriv accounts'); - const account_switcher_title_eu = modifiedMFAccountList - ? localize('Eu Deriv accounts') - : localize('Deriv accounts'); - const { oAuthLogout } = useOauth2({ handleLogout: async () => client.logout(), client }); - - useEffect(() => { - // Update the max-height from the accordion content set from deriv-com/ui - const parent_container = document.getElementsByClassName('account-switcher-panel')?.[0] as HTMLDivElement; - if (!isVirtual && parent_container) { - parent_container.style.maxHeight = '70vh'; - waitForDomElement('.deriv-accordion__content', parent_container)?.then((accordionElement: unknown) => { - const element = accordionElement as HTMLDivElement; - if (element) { - element.style.maxHeight = '70vh'; - } - }); - } - }, [isVirtual]); - - if (isVirtual) { - return ( - <> - - {modifiedAccountList - ?.filter(account => account.is_virtual) - .map(account => ( - - { - if (!account.is_disabled) switchAccount(account.loginid); - }} - onResetBalance={ - isVirtual && activeLoginId === account.loginid - ? () => { - api_base?.api?.send({ - topup_virtual: 1, - }); - } - : undefined - } - /> - - ))} - - -
- - {localize(`Looking for CFD accounts? Go to Trader's Hub`)} - - - - {client.is_logging_out ? ( -
- -
- ) : ( -
- - {localize('Log out')} - - -
- )} -
-
- - ); +const RenderAccountItems = ({ + isVirtual, + modifiedCRAccountList, + modifiedMFAccountList, + modifiedVRTCRAccountList, + switchAccount, + activeLoginId, +}: TAccountSwitcherProps) => { + const { client } = useStore(); + const { oAuthLogout } = useOauth2({ handleLogout: async () => client.logout(), client }); + const is_low_risk_country = LOW_RISK_COUNTRIES().includes(client.account_settings?.country_code ?? ''); + const is_virtual = !!isVirtual; + + useEffect(() => { + // Update the max-height from the accordion content set from deriv-com/ui + const parent_container = document.getElementsByClassName('account-switcher-panel')?.[0] as HTMLDivElement; + if (!isVirtual && parent_container) { + parent_container.style.maxHeight = '70vh'; + waitForDomElement('.deriv-accordion__content', parent_container)?.then((accordionElement: unknown) => { + const element = accordionElement as HTMLDivElement; + if (element) { + element.style.maxHeight = '70vh'; + } + }); } + }, [isVirtual]); + if (is_virtual) { return ( <> - {!isVirtual && modifiedCRAccountList?.length > 0 ? ( - - {modifiedCRAccountList.map(account => ( - - { - if (!account.is_disabled) switchAccount(account.loginid); - }} - /> - - ))} - - ) : ( - - )} - {!isVirtual && modifiedMFAccountList?.length > 0 && ( - - {modifiedMFAccountList.map(account => ( - - { - if (!account.is_disabled) switchAccount(account.loginid); - }} - /> - - ))} - - )} - -
- - {localize(`Looking for CFD accounts? Go to Trader's Hub`)} - - -
- {show_manage_button && ( - - )} - - {client.is_logging_out ? ( -
- -
- ) : ( -
{ - await oAuthLogout(); - }} - > - - {localize('Log out')} - - -
- )} -
-
-
+ ); + } else { + return ( + + ); } -); +}; const AccountSwitcher = observer(({ activeAccount }: TAccountSwitcher) => { const { isDesktop } = useDevice(); @@ -312,10 +95,11 @@ const AccountSwitcher = observer(({ activeAccount }: TAccountSwitcher) => { return accountList?.map(account => { return { ...account, - balance: + balance: addComma( client.all_accounts_balance?.accounts?.[account?.loginid]?.balance?.toFixed( getDecimalPlaces(account.currency) - ) ?? '0', + ) ?? '0' + ), currencyLabel: account?.is_virtual ? tabs_labels.demo : (client.website_status?.currencies_config?.[account?.currency]?.name ?? account?.currency), @@ -336,11 +120,15 @@ const AccountSwitcher = observer(({ activeAccount }: TAccountSwitcher) => { activeAccount?.loginid, ]); const modifiedCRAccountList = useMemo(() => { - return modifiedAccountList?.filter(account => account?.loginid?.includes('CR')); + return modifiedAccountList?.filter(account => account?.loginid?.includes('CR')) ?? []; }, [modifiedAccountList]); const modifiedMFAccountList = useMemo(() => { - return modifiedAccountList?.filter(account => account?.loginid?.includes('MF')); + return modifiedAccountList?.filter(account => account?.loginid?.includes('MF')) ?? []; + }, [modifiedAccountList]); + + const modifiedVRTCRAccountList = useMemo(() => { + return modifiedAccountList?.filter(account => account?.loginid?.includes('VRT')) ?? []; }, [modifiedAccountList]); const switchAccount = async (loginId: number) => { @@ -380,7 +168,6 @@ const AccountSwitcher = observer(({ activeAccount }: TAccountSwitcher) => { > { { + const show_manage_button = loginid?.includes('CR') || loginid?.includes('MF'); + return ( +
+ + {localize(`Looking for CFD accounts? Go to Trader's Hub`)} + + +
+ {show_manage_button && ( + + )} + + {is_logging_out ? ( +
+ +
+ ) : ( +
+ + {localize('Log out')} + + +
+ )} +
+
+
+ ); +}; + +export default AccountSwitcherFooter; diff --git a/src/components/layout/header/common/demo-accounts.tsx b/src/components/layout/header/common/demo-accounts.tsx new file mode 100644 index 00000000..94904381 --- /dev/null +++ b/src/components/layout/header/common/demo-accounts.tsx @@ -0,0 +1,60 @@ +import clsx from 'clsx'; +import { api_base } from '@/external/bot-skeleton'; +import { localize } from '@deriv-com/translations'; +import { AccountSwitcher as UIAccountSwitcher } from '@deriv-com/ui'; +import AccountSwitcherFooter from './account-swticher-footer'; +import { TDemoAccounts } from './types'; +import { AccountSwitcherDivider, convertCommaValue } from './utils'; + +const DemoAccounts = ({ + tabs_labels, + modifiedVRTCRAccountList, + switchAccount, + isVirtual, + activeLoginId, + oAuthLogout, + is_logging_out, +}: TDemoAccounts) => { + return ( + <> + + {modifiedVRTCRAccountList && + modifiedVRTCRAccountList.map(account => ( + + { + if (!account.is_disabled) switchAccount(account.loginid); + }} + onResetBalance={ + isVirtual && + activeLoginId === account.loginid && + convertCommaValue(account.balance) !== 10000 + ? () => { + api_base?.api?.send({ + topup_virtual: 1, + }); + } + : undefined + } + /> + + ))} + + + + + ); +}; + +export default DemoAccounts; diff --git a/src/components/layout/header/common/eu-accounts.tsx b/src/components/layout/header/common/eu-accounts.tsx new file mode 100644 index 00000000..e5b63421 --- /dev/null +++ b/src/components/layout/header/common/eu-accounts.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import clsx from 'clsx'; +import { localize } from '@deriv-com/translations'; +import { AccountSwitcher as UIAccountSwitcher } from '@deriv-com/ui'; +import { TEuAccounts } from './types'; + +const EuAccounts = ({ + isVirtual, + tabs_labels, + modifiedMFAccountList, + switchAccount, + is_low_risk_country, +}: TEuAccounts) => { + const account_switcher_title_eu = + modifiedMFAccountList?.length === 0 || !is_low_risk_country + ? localize('Deriv accounts') + : localize('Eu Deriv accounts'); + return ( + + {modifiedMFAccountList.map(account => { + account.currencyLabel = localize('Multipliers'); + return ( + + { + if (!account.is_disabled) switchAccount(account.loginid); + }} + /> + + ); + })} + + ); +}; + +export default EuAccounts; diff --git a/src/components/layout/header/common/no-non-eu-accounts.tsx b/src/components/layout/header/common/no-non-eu-accounts.tsx new file mode 100644 index 00000000..415c0a5b --- /dev/null +++ b/src/components/layout/header/common/no-non-eu-accounts.tsx @@ -0,0 +1,33 @@ +import { standalone_routes } from '@/components/shared'; +import { Localize, localize } from '@deriv-com/translations'; +import { AccountSwitcher as UIAccountSwitcher, Button } from '@deriv-com/ui'; +import { TNoNonEuAccounts } from './types'; +import { AccountSwitcherDivider, no_account } from './utils'; + +const NoNonEuAccounts = ({ isVirtual, tabs_labels, is_low_risk_country }: TNoNonEuAccounts) => { + if (!is_low_risk_country) { + return null; + } + return ( + +
+ {}} /> + + +
+
+ ); +}; + +export default NoNonEuAccounts; diff --git a/src/components/layout/header/common/non-eu-accounts.tsx b/src/components/layout/header/common/non-eu-accounts.tsx new file mode 100644 index 00000000..7b5f6c6a --- /dev/null +++ b/src/components/layout/header/common/non-eu-accounts.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import clsx from 'clsx'; +import { localize } from '@deriv-com/translations'; +import { AccountSwitcher as UIAccountSwitcher } from '@deriv-com/ui'; +import { TNonEUAccounts } from './types'; + +const NonEUAccounts = ({ + isVirtual, + tabs_labels, + modifiedCRAccountList, + modifiedMFAccountList, + is_low_risk_country, + switchAccount, +}: TNonEUAccounts) => { + if (!is_low_risk_country && modifiedCRAccountList && modifiedCRAccountList?.length === 0) { + return null; + } + + const account_switcher_title_non_eu = + modifiedMFAccountList?.length === 0 ? localize('Deriv accounts') : localize('Non-Eu Deriv account'); + return ( + <> + + {modifiedCRAccountList.map(account => ( + + { + if (!account.is_disabled) switchAccount(account.loginid); + }} + /> + + ))} + + + ); +}; + +export default NonEUAccounts; diff --git a/src/components/layout/header/common/real-accounts.tsx b/src/components/layout/header/common/real-accounts.tsx new file mode 100644 index 00000000..eea87d1b --- /dev/null +++ b/src/components/layout/header/common/real-accounts.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import AccountSwitcherFooter from './account-swticher-footer'; +import EuAccounts from './eu-accounts'; +import NoNonEuAccounts from './no-non-eu-accounts'; +import NonEUAccounts from './non-eu-accounts'; +import { TRealAccounts } from './types'; +import { AccountSwitcherDivider } from './utils'; + +const RealAccounts = ({ + modifiedCRAccountList, + modifiedMFAccountList, + switchAccount, + isVirtual, + tabs_labels, + is_low_risk_country, + oAuthLogout, + loginid, + is_logging_out, +}: TRealAccounts) => { + const hasNonEuAccounts = modifiedCRAccountList && modifiedCRAccountList?.length > 0; + const hasEuAccounts = modifiedMFAccountList && modifiedMFAccountList?.length > 0; + return ( + <> + {hasNonEuAccounts ? ( + <> + + + + ) : ( + <> + + + + )} + {hasEuAccounts && ( + <> + + + + )} + + + ); +}; + +export default RealAccounts; diff --git a/src/components/layout/header/common/types.tsx b/src/components/layout/header/common/types.tsx new file mode 100644 index 00000000..152c0c1f --- /dev/null +++ b/src/components/layout/header/common/types.tsx @@ -0,0 +1,72 @@ +import useActiveAccount from '@/hooks/api/account/useActiveAccount'; +import { useApiBase } from '@/hooks/useApiBase'; + +export type TModifiedAccount = ReturnType['accountList'][number] & { + balance: string; + currencyLabel: string; + icon: React.ReactNode; + isVirtual: boolean; + isActive: boolean; + loginid: number; + currency: string; +}; +export type TAccountSwitcherProps = { + isVirtual?: boolean; + switchAccount: (loginId: number) => void; + modifiedCRAccountList?: TModifiedAccount[]; + modifiedMFAccountList?: TModifiedAccount[]; + modifiedVRTCRAccountList?: TModifiedAccount[]; + activeLoginId?: string; +}; + +export type TAccountSwitcher = { + activeAccount: ReturnType['data']; +}; + +export type TDemoAccounts = { + tabs_labels: { + demo: string; + }; + modifiedVRTCRAccountList?: TModifiedAccount[]; + switchAccount: (loginId: number) => void; + isVirtual: boolean; + activeLoginId?: string; + oAuthLogout: () => void; + is_logging_out: boolean; +}; + +export type TNoNonEuAccounts = { + isVirtual: boolean; + tabs_labels: { + demo: string; + real: string; + }; + is_low_risk_country: boolean; +}; +export type TRealAccounts = TNoNonEuAccounts & { + modifiedCRAccountList: TModifiedAccount[]; + modifiedMFAccountList: TModifiedAccount[]; + switchAccount: (loginId: number) => void; + oAuthLogout: () => void; + loginid?: string; + is_logging_out: boolean; +}; +export type TEuAccounts = TNoNonEuAccounts & { + modifiedMFAccountList: TModifiedAccount[]; + switchAccount: (loginId: number) => void; + isVirtual?: boolean; + is_low_risk_country?: boolean; +}; + +export type TNonEUAccounts = TNoNonEuAccounts & { + isVirtual?: boolean; + modifiedCRAccountList: TModifiedAccount[]; + modifiedMFAccountList?: TModifiedAccount[]; + switchAccount: (loginId: number) => void; +}; + +export type TAccountSwitcherFooter = { + oAuthLogout: () => void; + loginid?: string; + is_logging_out: boolean; +}; diff --git a/src/components/layout/header/common/utils.tsx b/src/components/layout/header/common/utils.tsx new file mode 100644 index 00000000..c533b290 --- /dev/null +++ b/src/components/layout/header/common/utils.tsx @@ -0,0 +1,20 @@ +import { LegacyDerivIcon } from '@deriv/quill-icons'; +import { Divider } from '@deriv-com/ui'; + +export const no_account = { + currency: ' ', + currencyLabel: 'Options & Multipliers', + is_virtual: 1, + loginid: '', + is_disabled: false, + balance: '', + icon: , + isActive: false, + isVirtual: true, +}; + +export const convertCommaValue = (str: string) => { + return Number(str.replace(/,/g, '')); +}; + +export const AccountSwitcherDivider = () => ; diff --git a/src/components/layout/header/header.scss b/src/components/layout/header/header.scss index 50c4bb9f..5ef84d91 100644 --- a/src/components/layout/header/header.scss +++ b/src/components/layout/header/header.scss @@ -19,11 +19,31 @@ .account-switcher { &__item { + .deriv-account-switcher-item { + padding: 0.6rem 1.6rem; + + &__detail { + .deriv-account-switcher-item__currency { + margin-bottom: 2px; + font-size: 1.4rem; + } + } + } + &--disabled { opacity: 0.32; } } + &__separator:after { + background-color: var(--general-section-2); + content: ''; + height: 4px; + position: absolute; + width: 100%; + z-index: 1; + } + &-footer { background: var(--general-main-1); @@ -41,6 +61,7 @@ .manage-button { background: none; border: 1px solid var(--button-secondary-default); + margin-left: 0.8rem; &:hover { background-color: unset !important; @@ -50,7 +71,7 @@ color: var(--text-prominent); font-size: var(--text-size-xs); cursor: pointer; - font-weight: 400; + font-weight: 700; } } } @@ -65,6 +86,11 @@ top: 0; z-index: 1; background: var(--general-main-1); + + .derivs-text__size--md { + font-size: 14px; + line-height: 18px; + } } .deriv-account-switcher { @@ -96,6 +122,18 @@ .deriv-account-switcher__balance + svg > path { fill: var(--text-general); } + + &:hover { + background-color: unset; + } + } + + &__currency { + margin-bottom: 2px; + } + + &__icon { + margin-right: 7px; } &__balance { @@ -104,7 +142,7 @@ &__list { &.account-switcher-panel { - padding: 2rem 0.8rem 1rem; + padding: 0.4rem 0.8rem 0; .account-switcher-panel__no-eu-accounts { display: flex; @@ -124,9 +162,8 @@ } } - .deriv-account-switcher-item:hover, - .deriv-account-switcher-item--active { - background-color: unset; + .deriv-account-switcher-item { + background: none; } } } @@ -137,13 +174,15 @@ } &__text { - margin-top: 1rem; + margin-top: 0; } } } &__title { - padding: 0 16px 12px; + height: 4rem; + margin: 0 auto; + padding: 1.2rem 1.6rem; } &__container--mobile { @@ -154,6 +193,14 @@ max-height: 80vh; overflow: auto; background: var(--general-main-1); + background-color: var(--general-main-2); + border-radius: 4px; + box-shadow: 0 8px 16px 0 var(--shadow-menu) !important; + position: absolute; + transition: + transform 0.3s ease, + opacity 0.25s linear; + width: 320px; } &__logout { @@ -177,6 +224,7 @@ } &__tradershub-link { + padding: 1.2rem 2.5rem 0.6rem 0.8rem; background: var(--general-main-1); } @@ -218,3 +266,7 @@ .manage-funds-button { margin-inline-end: 1.6rem; } + +.deriv-accordion--underline { + border-bottom: none; +} diff --git a/src/components/page-error/page-error.scss b/src/components/page-error/page-error.scss index c5c2a8cb..5fd104a7 100644 --- a/src/components/page-error/page-error.scss +++ b/src/components/page-error/page-error.scss @@ -47,7 +47,7 @@ &__message { // @include typeface(--title-center-normal-black, none); - max-width: 600px; + max-width: 500px; margin: 1.6rem 0 2.4rem; &-paragraph { @@ -84,6 +84,16 @@ &-wrapper { display: flex; justify-content: center; + + button { + height: 4rem; + min-width: 6.4rem; + + span { + font-size: 1.4rem; + font-weight: 500; + } + } } @include mobile-or-tablet-screen { diff --git a/src/components/page-error/page-error.tsx b/src/components/page-error/page-error.tsx index 31b97308..3bda7b64 100644 --- a/src/components/page-error/page-error.tsx +++ b/src/components/page-error/page-error.tsx @@ -38,6 +38,7 @@ const PageError = ({ const onClickHandler = () => { if (should_clear_error_on_click) { setError?.(false, null); + window.location.assign('https://app.deriv.com'); // TODO: NEED TO REMOVE & FIX THIS TO REDIRECT TO THE CORRECT URL } else { buttonOnClick?.(); } @@ -122,7 +123,7 @@ const PageError = ({ redirect_urls?.map?.((url, index) => (