diff --git a/package-lock.json b/package-lock.json index e66f9f92..4d4c49e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "dependencies": { "@babel/preset-env": "^7.24.5", - "@deriv-com/api-hooks": "^0.1.24", + "@deriv-com/api-hooks": "^1.1.1", "@deriv-com/translations": "^1.2.4", "@deriv-com/ui": "^1.27.9", "@deriv-com/utils": "latest", @@ -2604,26 +2604,21 @@ } }, "node_modules/@deriv-com/api-hooks": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/@deriv-com/api-hooks/-/api-hooks-0.1.24.tgz", - "integrity": "sha512-SiZsyZlnfXWlioa7MSiZgu8N4wTEpiKzYpKhuKvQS86Ek/dyjw43iviqJkXD3n/AZX2FZA40lCwE363tURMGVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@deriv-com/api-hooks/-/api-hooks-1.1.1.tgz", + "integrity": "sha512-lM/XrjCLXF6NMuzGz5Tza1OhfuvP5/NxZ8ofykVG0wySNF4klYvTiSOvk+kJv+MLT8FY48JhdH1HMbdPKREtvA==", "dependencies": { - "@deriv-com/utils": "^0.0.22", - "@deriv/api-types": "^1.0.560", + "@deriv-com/utils": "^0.0.24", + "@deriv/api-types": "^1.0.667", "@deriv/deriv-api": "^1.0.15", - "@tanstack/react-query": "^5.37.1", + "@tanstack/react-query": "^5.40.0", "@types/js-cookie": "^3.0.6", "js-cookie": "^3.0.5" }, "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.17.2" + "@rollup/rollup-linux-x64-gnu": "^4.18.0" } }, - "node_modules/@deriv-com/api-hooks/node_modules/@deriv-com/utils": { - "version": "0.0.22", - "resolved": "https://registry.npmjs.org/@deriv-com/utils/-/utils-0.0.22.tgz", - "integrity": "sha512-9eVZTPEwfNPXhHsq0qHAGxQW0/ZwzP7gca3CfjPgI9rNvFNVcduxi9wJ3HXl3FKrT8rSpO0X8rHjJKxdOjmjog==" - }, "node_modules/@deriv-com/eslint-config-deriv": { "version": "2.1.0-beta.3", "resolved": "https://registry.npmjs.org/@deriv-com/eslint-config-deriv/-/eslint-config-deriv-2.1.0-beta.3.tgz", @@ -2692,9 +2687,9 @@ "integrity": "sha512-dK9H6GfI/DB7eRTjZS3+K9cEg3gZlCJV+zmDL27OpRHSyddrw2Z//PuMq3WZxtXTGuHt3g7TLDUP7PdvXL8DdA==" }, "node_modules/@deriv/api-types": { - "version": "1.0.659", - "resolved": "https://registry.npmjs.org/@deriv/api-types/-/api-types-1.0.659.tgz", - "integrity": "sha512-8TsTvYftDXBmzWD6SVyEi8N3DudSlB2rewilUefMn8gErsVAahTkq8xgCU6iRtbLvmKOpEj2St5otIftZ3uczw==" + "version": "1.0.801", + "resolved": "https://registry.npmjs.org/@deriv/api-types/-/api-types-1.0.801.tgz", + "integrity": "sha512-w5oNwBRTpnz0j4jYUbqyu7QgrNcW0l8hi2uWda2rNX5fDgnhDU+eWJmsyhqDMNqlWG41FiH2Ed4VBereF7YuEw==" }, "node_modules/@deriv/deriv-api": { "version": "1.0.15", diff --git a/package.json b/package.json index f18cf7e6..5d8d0988 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "dependencies": { "@babel/preset-env": "^7.24.5", - "@deriv-com/api-hooks": "^0.1.24", + "@deriv-com/api-hooks": "^1.1.1", "@deriv-com/translations": "^1.2.4", "@deriv-com/ui": "^1.27.9", "@deriv-com/utils": "latest", diff --git a/src/App.tsx b/src/App.tsx index 557b074b..6672603f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,9 +2,10 @@ import { BrowserRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; import { AppFooter, AppHeader, DerivIframe } from '@/components'; +import { useRedirectToOauth } from '@/hooks'; +import AppContent from '@/routes/AppContent'; import { initializeI18n, TranslationProvider } from '@deriv-com/translations'; import { useDevice } from '@deriv-com/ui'; -import AppContent from './routes/AppContent'; const { VITE_CROWDIN_BRANCH_NAME, VITE_PROJECT_NAME, VITE_TRANSLATIONS_CDN_URL } = import.meta.env; const i18nInstance = initializeI18n({ @@ -13,6 +14,9 @@ const i18nInstance = initializeI18n({ const App = () => { const { isDesktop } = useDevice(); + const { redirectToOauth } = useRedirectToOauth(); + + redirectToOauth(); return ( diff --git a/src/components/AppHeader/AppHeader.tsx b/src/components/AppHeader/AppHeader.tsx index 8e643571..dc4feb5c 100644 --- a/src/components/AppHeader/AppHeader.tsx +++ b/src/components/AppHeader/AppHeader.tsx @@ -1,9 +1,8 @@ -import { useEffect } from 'react'; +import { getOauthUrl } from '@/constants'; import { StandaloneCircleUserRegularIcon } from '@deriv/quill-icons'; -import { useAccountList, useAuthData } from '@deriv-com/api-hooks'; +import { useAuthData } from '@deriv-com/api-hooks'; import { useTranslations } from '@deriv-com/translations'; import { Button, Header, Text, TooltipMenuIcon, useDevice, Wrapper } from '@deriv-com/ui'; -import { LocalStorageConstants, LocalStorageUtils, URLUtils } from '@deriv-com/utils'; import { AccountSwitcher } from './AccountSwitcher'; import { AppLogo } from './AppLogo'; import { MenuItems } from './MenuItems'; @@ -14,34 +13,10 @@ import './AppHeader.scss'; // TODO: handle local storage values not updating after changing local storage values const AppHeader = () => { - const { data: accounts } = useAccountList(); const { isDesktop } = useDevice(); const { activeLoginid, logout } = useAuthData(); const { localize } = useTranslations(); - const appId = LocalStorageUtils.getValue(LocalStorageConstants.configAppId); - const serverUrl = localStorage.getItem(LocalStorageConstants.configServerURL.toString()); - const oauthUrl = - appId && serverUrl - ? `https://${serverUrl}/oauth2/authorize?app_id=${appId}&l=EN&&brand=deriv` - : URLUtils.getOauthURL(); - - useEffect(() => { - const shouldRedirectToLogin = () => { - if (typeof accounts !== 'undefined') { - const userHasNoP2PAccount = !accounts.find( - account => account.broker === 'CR' && account.currency === 'USD' - ); - const activeAccount = accounts.find(account => account.loginid === activeLoginid); - const activeAccountCurrency = activeAccount?.currency || null; - - if (userHasNoP2PAccount || activeAccountCurrency !== 'USD') { - window.open(oauthUrl, '_self'); - } - } - }; - - shouldRedirectToLogin(); - }, [accounts, activeLoginid, oauthUrl]); + const oauthUrl = getOauthUrl(); return (
diff --git a/src/components/AppHeader/HeaderConfig.tsx b/src/components/AppHeader/HeaderConfig.tsx index 43dc9041..342d6428 100644 --- a/src/components/AppHeader/HeaderConfig.tsx +++ b/src/components/AppHeader/HeaderConfig.tsx @@ -81,14 +81,14 @@ export const MenuItems: MenuItemsConfig[] = [ label: "Trader's Hub", }, { - as: 'button', - href: 'https://app.deriv.com/appstore/traders-hub', + as: 'a', + href: 'https://app.deriv.com/appstore/reports', icon: , label: 'Reports', }, { - as: 'button', - href: 'https://app.deriv.com/appstore/traders-hub', + as: 'a', + href: 'https://app.deriv.com/appstore/cashier', icon: , label: 'Cashier', }, diff --git a/src/constants/url.ts b/src/constants/url.ts index e0f58557..f50ce1a2 100644 --- a/src/constants/url.ts +++ b/src/constants/url.ts @@ -1,4 +1,4 @@ -import { URLConstants } from '@deriv-com/utils'; +import { LocalStorageConstants, LocalStorageUtils, URLConstants, URLUtils } from '@deriv-com/utils'; export const BUY_SELL_URL = '/buy-sell'; export const ORDERS_URL = '/orders'; @@ -12,3 +12,14 @@ export const ACCOUNT_LIMITS = `${URLConstants.derivAppProduction}/account/accoun export const DERIV_COM = URLConstants.derivComProduction; export const HELP_CENTRE = `${URLConstants.derivComProduction}/help-centre/`; export const RESPONSIBLE = `${URLConstants.derivComProduction}/responsible/`; + +export const getOauthUrl = () => { + const appId = LocalStorageUtils.getValue(LocalStorageConstants.configAppId); + const serverUrl = localStorage.getItem(LocalStorageConstants.configServerURL.toString()); + const oauthUrl = + appId && serverUrl + ? `https://${serverUrl}/oauth2/authorize?app_id=${appId}&l=EN&&brand=deriv` + : URLUtils.getOauthURL(); + + return oauthUrl; +}; diff --git a/src/hooks/custom-hooks/index.ts b/src/hooks/custom-hooks/index.ts index ce72bec8..49adab7e 100644 --- a/src/hooks/custom-hooks/index.ts +++ b/src/hooks/custom-hooks/index.ts @@ -12,5 +12,6 @@ export { default as useNavigatorOnline } from './useNavigatorOnline'; export { default as useNetworkStatus } from './useNetworkStatus'; export { default as usePoiPoaStatus } from './usePoiPoaStatus'; export { default as useQueryString } from './useQueryString'; +export { default as useRedirectToOauth } from './useRedirectToOauth'; export { default as useSendbird } from './useSendbird'; export { default as useSyncedTime } from './useSyncedTime'; diff --git a/src/hooks/custom-hooks/useIsAdvertiser.ts b/src/hooks/custom-hooks/useIsAdvertiser.ts index cfd49ef8..876d8238 100644 --- a/src/hooks/custom-hooks/useIsAdvertiser.ts +++ b/src/hooks/custom-hooks/useIsAdvertiser.ts @@ -12,7 +12,7 @@ const useIsAdvertiser = (): boolean => { const [isAdvertiser, setIsAdvertiser] = useState(!error && !isEmptyObject(data)); useEffect(() => { - if (error && error?.error.code === ERROR_CODES.ADVERTISER_NOT_FOUND) { + if (error && error?.code === ERROR_CODES.ADVERTISER_NOT_FOUND) { setIsAdvertiser(false); } else if (!error && !isEmptyObject(data)) { setIsAdvertiser(true); diff --git a/src/hooks/custom-hooks/useRedirectToOauth.ts b/src/hooks/custom-hooks/useRedirectToOauth.ts new file mode 100644 index 00000000..8584a5e9 --- /dev/null +++ b/src/hooks/custom-hooks/useRedirectToOauth.ts @@ -0,0 +1,27 @@ +import { useCallback, useEffect, useState } from 'react'; +import { getOauthUrl } from '@/constants'; +import { getCurrentRoute } from '@/utils'; +import { useAuthData } from '@deriv-com/api-hooks'; + +const useRedirectToOauth = () => { + const [shouldRedirect, setShouldRedirect] = useState(false); + const { isAuthorized, isAuthorizing } = useAuthData(); + const isEndpointPage = getCurrentRoute() === 'endpoint'; + + const oauthUrl = getOauthUrl(); + const redirectToOauth = useCallback(() => { + shouldRedirect && window.open(oauthUrl, '_self'); + }, [oauthUrl, shouldRedirect]); + + useEffect(() => { + if (!isEndpointPage && !isAuthorized && !isAuthorizing) { + setShouldRedirect(true); + } + }, [isAuthorized, isAuthorizing, isEndpointPage, oauthUrl]); + + return { + redirectToOauth, + }; +}; + +export default useRedirectToOauth; diff --git a/src/pages/orders/screens/OrderDetails/OrderDetails.tsx b/src/pages/orders/screens/OrderDetails/OrderDetails.tsx index ce2805fa..0d27edf2 100644 --- a/src/pages/orders/screens/OrderDetails/OrderDetails.tsx +++ b/src/pages/orders/screens/OrderDetails/OrderDetails.tsx @@ -80,7 +80,7 @@ const OrderDetails = () => { if (isLoading || (!orderInfo && !error)) return ; // TODO: replace with proper error screen once design is ready - if (error) return {error?.error?.message}; + if (error) return {error?.message}; if (isMobile) { return ( diff --git a/src/pages/orders/screens/OrderDetails/__tests__/OrderDetails.spec.tsx b/src/pages/orders/screens/OrderDetails/__tests__/OrderDetails.spec.tsx index 3d7f398d..587752e4 100644 --- a/src/pages/orders/screens/OrderDetails/__tests__/OrderDetails.spec.tsx +++ b/src/pages/orders/screens/OrderDetails/__tests__/OrderDetails.spec.tsx @@ -225,7 +225,7 @@ describe('', () => { (mockUseGet as jest.Mock).mockReturnValue({ ...mockUseGet(), data: {}, - error: { error: { message: 'error message' } }, + error: { code: 'code', message: 'error message' }, isLoading: false, }); diff --git a/src/providers/AdvertiserInfoStateProvider/AdvertiserInfoStateProvider.tsx b/src/providers/AdvertiserInfoStateProvider/AdvertiserInfoStateProvider.tsx index d11efbc9..c26beb45 100644 --- a/src/providers/AdvertiserInfoStateProvider/AdvertiserInfoStateProvider.tsx +++ b/src/providers/AdvertiserInfoStateProvider/AdvertiserInfoStateProvider.tsx @@ -1,8 +1,7 @@ import { createContext, PropsWithChildren, useContext } from 'react'; -import { TSocketError } from 'types'; type TContextValue = { - error: TSocketError<'p2p_advertiser_info'> | undefined; + error: { code: string; message: string } | undefined; isIdle: boolean; isLoading: boolean; isSubscribed: boolean; diff --git a/src/routes/AppContent/index.tsx b/src/routes/AppContent/index.tsx index d98b4c34..ac0d1fb8 100644 --- a/src/routes/AppContent/index.tsx +++ b/src/routes/AppContent/index.tsx @@ -51,7 +51,6 @@ const AppContent = () => { useEffect(() => { if (hasCreatedAdvertiser) { // Need to pass params to subscribeAdvertiserInfo to trigger the subscription. - // @ts-expect-error - passthrough is not a valid parameter subscribeAdvertiserInfo({ passthrough: { createdNickname: 'nickname' } }); } }, [hasCreatedAdvertiser, subscribeAdvertiserInfo]);