diff --git a/packages/cfd/src/Components/Routes/binary-link.jsx b/packages/cfd/src/Components/Routes/binary-link.tsx similarity index 54% rename from packages/cfd/src/Components/Routes/binary-link.jsx rename to packages/cfd/src/Components/Routes/binary-link.tsx index c92428bdea66..230642018990 100644 --- a/packages/cfd/src/Components/Routes/binary-link.jsx +++ b/packages/cfd/src/Components/Routes/binary-link.tsx @@ -1,14 +1,16 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { NavLink } from 'react-router-dom'; -import { PlatformContext } from '@deriv/shared'; import getRoutesConfig from '../../Constants/routes-config'; import { findRouteByPath, normalizePath } from './helpers'; -const BinaryLink = ({ active_class, to, children, ...props }) => { - const { is_dashboard } = React.useContext(PlatformContext); +type TBinaryLink = { + active_class: string; + to: string; +}; + +const BinaryLink = ({ active_class, to, children, ...props }: React.PropsWithChildren) => { const path = normalizePath(to); - const route = findRouteByPath(path, getRoutesConfig({ is_dashboard })); + const route = findRouteByPath(path, getRoutesConfig()); if (!route) { throw new Error(`Route not found: ${to}`); @@ -23,10 +25,4 @@ const BinaryLink = ({ active_class, to, children, ...props }) => { ); }; -BinaryLink.propTypes = { - active_class: PropTypes.string, - children: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.string]), - to: PropTypes.string, -}; - export default BinaryLink; diff --git a/packages/cfd/src/Components/Routes/binary-routes.jsx b/packages/cfd/src/Components/Routes/binary-routes.jsx deleted file mode 100644 index a75cc6de0f81..000000000000 --- a/packages/cfd/src/Components/Routes/binary-routes.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import { Switch } from 'react-router-dom'; -import { PlatformContext } from '@deriv/shared'; -import { Localize } from '@deriv/translations'; -import getRoutesConfig from '../../Constants/routes-config'; -import RouteWithSubRoutes from './route-with-sub-routes.jsx'; - -const BinaryRoutes = props => { - const { is_dashboard } = React.useContext(PlatformContext); - - return ( - { - return ( -
- -
- ); - }} - > - - {getRoutesConfig({ is_dashboard }).map(route => ( - - ))} - -
- ); -}; - -export default BinaryRoutes; diff --git a/packages/cfd/src/Components/Routes/binary-routes.tsx b/packages/cfd/src/Components/Routes/binary-routes.tsx new file mode 100644 index 000000000000..2f616d8e0c83 --- /dev/null +++ b/packages/cfd/src/Components/Routes/binary-routes.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Switch } from 'react-router-dom'; +import { Localize } from '@deriv/translations'; +import getRoutesConfig from '../../Constants/routes-config'; +import { TBinaryRoutes } from '../../types/common-prop-types'; +import RouteWithSubRoutes from './route-with-sub-routes'; + +const Loading = () => ( +
+ +
+); + +const BinaryRoutes = (props: TBinaryRoutes) => ( + }> + + {getRoutesConfig().map(route => ( + + ))} + + +); + +export default BinaryRoutes; diff --git a/packages/cfd/src/Components/Routes/helpers.js b/packages/cfd/src/Components/Routes/helpers.js deleted file mode 100644 index 8d8bcc421c1d..000000000000 --- a/packages/cfd/src/Components/Routes/helpers.js +++ /dev/null @@ -1,37 +0,0 @@ -import { matchPath } from 'react-router'; -import { routes } from '@deriv/shared'; - -export const normalizePath = path => (/^\//.test(path) ? path : `/${path || ''}`); // Default to '/' - -export const findRouteByPath = (path, routes_config) => { - let result; - - routes_config.some(route_info => { - let match_path; - try { - match_path = matchPath(path, route_info); - } catch (e) { - if (/undefined/.test(e.message)) { - return undefined; - } - } - - if (match_path) { - result = route_info; - return true; - } else if (route_info.routes) { - result = findRouteByPath(path, route_info.routes); - return result; - } - return false; - }); - - return result; -}; - -export const isRouteVisible = (route, is_logged_in) => !(route && route.is_authenticated && !is_logged_in); - -export const getPath = (route_path, params = {}) => - Object.keys(params).reduce((p, name) => p.replace(`:${name}`, params[name]), route_path); - -export const getContractPath = contract_id => getPath(routes.contract, { contract_id }); diff --git a/packages/cfd/src/Components/Routes/helpers.ts b/packages/cfd/src/Components/Routes/helpers.ts new file mode 100644 index 000000000000..5d890df0f51e --- /dev/null +++ b/packages/cfd/src/Components/Routes/helpers.ts @@ -0,0 +1,39 @@ +import { matchPath } from 'react-router'; +import { routes } from '@deriv/shared'; +import { TRouteConfig } from '../../types/common-prop-types'; + +export const normalizePath = (path: string) => (/^\//.test(path) ? path : `/${path || ''}`); // Default to '/' + +export const findRouteByPath = (path: string, routes_config: TRouteConfig[]) => { + let result: TRouteConfig | undefined; + + routes_config.some(route_info => { + let match_path; + try { + match_path = matchPath(path, route_info); + } catch (e) { + if (/undefined/.test((e as Error).message)) { + return undefined; + } + } + + if (match_path) { + result = route_info; + return true; + } else if (route_info.routes) { + result = findRouteByPath(path, route_info.routes); + return result; + } + return false; + }); + + return result; +}; + +export const isRouteVisible = (route: TRouteConfig, is_logged_in: boolean) => + !(route && route.is_authenticated && !is_logged_in); + +export const getPath = (route_path: string, params: { [x: string]: string } = {}) => + Object.keys(params).reduce((p, name) => p.replace(`:${name}`, params[name]), route_path); + +export const getContractPath = (contract_id: string) => getPath(routes.contract, { contract_id }); diff --git a/packages/cfd/src/Components/Routes/index.js b/packages/cfd/src/Components/Routes/index.js deleted file mode 100644 index ab0b7a117c33..000000000000 --- a/packages/cfd/src/Components/Routes/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import BinaryLink from './binary-link.jsx'; -import BinaryRoutes from './binary-routes.jsx'; -import RouteWithSubRoutes from './route-with-sub-routes.jsx'; - -export { BinaryLink }; -export default BinaryRoutes; -export * from './helpers'; -export { RouteWithSubRoutes }; diff --git a/packages/cfd/src/Components/Routes/index.ts b/packages/cfd/src/Components/Routes/index.ts new file mode 100644 index 000000000000..599a979c347f --- /dev/null +++ b/packages/cfd/src/Components/Routes/index.ts @@ -0,0 +1,8 @@ +import BinaryLink from './binary-link'; +import BinaryRoutes from './binary-routes'; +import RouteWithSubRoutes from './route-with-sub-routes'; + +export { BinaryLink }; +export default BinaryRoutes; +export * from './helpers'; +export { RouteWithSubRoutes }; diff --git a/packages/cfd/src/Components/Routes/route-with-sub-routes.jsx b/packages/cfd/src/Components/Routes/route-with-sub-routes.tsx similarity index 65% rename from packages/cfd/src/Components/Routes/route-with-sub-routes.jsx rename to packages/cfd/src/Components/Routes/route-with-sub-routes.tsx index e4924ce54da9..904ebc5c7f3a 100644 --- a/packages/cfd/src/Components/Routes/route-with-sub-routes.jsx +++ b/packages/cfd/src/Components/Routes/route-with-sub-routes.tsx @@ -1,14 +1,17 @@ import React from 'react'; -import { Redirect, Route } from 'react-router-dom'; +import { Redirect, Route, RouteComponentProps } from 'react-router-dom'; import { redirectToLogin, isEmptyObject, routes, removeBranchName, default_title } from '@deriv/shared'; import { getLanguage } from '@deriv/translations'; +import { TBinaryRoutes, TRoute, TRouteConfig } from '../../types/common-prop-types'; -const RouteWithSubRoutes = route => { - const renderFactory = props => { +type TRouteWithSubRoutesProps = TRouteConfig & TBinaryRoutes; + +const RouteWithSubRoutes = (route: TRouteWithSubRoutesProps) => { + const renderFactory = (props: RouteComponentProps) => { let result = null; if (route.component === Redirect) { - let to = route.to; + let to = route.to as string; // This if clause has been added just to remove '/index' from url in localhost env. if (route.path === routes.index) { @@ -19,20 +22,25 @@ const RouteWithSubRoutes = route => { } else if (route.is_authenticated && !route.is_logged_in && !route.is_logging_in) { redirectToLogin(route.is_logged_in, getLanguage()); } else { - const default_subroute = (route.routes ?? []).reduce( + const default_subroute = (route.routes ?? []).reduce( (acc, cur) => ({ ...acc, - ...cur.subroutes.find(subroute => subroute.default), + ...cur.subroutes?.find(subroute => subroute.default), }), {} ); - const has_default_subroute = !isEmptyObject(default_subroute); + + const isNotEmpty = (obj: object | TRoute): obj is TRoute => !isEmptyObject(obj); + const has_default_subroute = isNotEmpty(default_subroute); + const pathname = removeBranchName(location.pathname); + const RouteComponent = route.component as React.ElementType; + result = ( {has_default_subroute && pathname === route.path && } - + ); } diff --git a/packages/cfd/src/Constants/routes-config.tsx b/packages/cfd/src/Constants/routes-config.tsx index e33fb61d646f..283968a0b090 100644 --- a/packages/cfd/src/Constants/routes-config.tsx +++ b/packages/cfd/src/Constants/routes-config.tsx @@ -1,18 +1,9 @@ import React from 'react'; -import CFD from '../Containers'; import { routes } from '@deriv/shared'; import { localize } from '@deriv/translations'; - -export type TRoute = { - path?: string; - component?: (props: any) => React.ReactNode; - getTitle: () => string; -}; - -export type TRouteConfig = TRoute & { - is_authenticated?: boolean; - routes?: TRoute[]; -}; +import CFD from '../Containers'; +import { TCFDDashboardProps } from '../Containers/cfd-dashboard'; +import { TRouteConfig } from '../types/common-prop-types'; // Error Routes const Page404 = React.lazy(() => import(/* webpackChunkName: "404" */ '../Modules/Page404')); @@ -22,15 +13,13 @@ const initRoutesConfig = (): TRouteConfig[] => { return [ { path: routes.dxtrade, - // eslint-disable-next-line react/display-name - component: props => , + component: (props: TCFDDashboardProps) => , getTitle: () => localize('Deriv X'), is_authenticated: false, }, { path: routes.mt5, - // eslint-disable-next-line react/display-name - component: props => , + component: (props: TCFDDashboardProps) => , getTitle: () => localize('MT5'), is_authenticated: false, }, diff --git a/packages/cfd/src/types/common-prop-types.ts b/packages/cfd/src/types/common-prop-types.ts new file mode 100644 index 000000000000..6f904b59d1c0 --- /dev/null +++ b/packages/cfd/src/types/common-prop-types.ts @@ -0,0 +1,21 @@ +import { Redirect } from 'react-router-dom'; + +export type TRoute = { + exact?: boolean; + path: string; + default?: boolean; + to?: string; + component?: ((props?: any) => JSX.Element) | typeof Redirect | React.LazyExoticComponent<() => JSX.Element>; + getTitle?: () => string; + subroutes?: TRoute[]; +}; + +export type TRouteConfig = TRoute & { + is_authenticated?: boolean; + routes?: TRoute[]; +}; + +export type TBinaryRoutes = { + is_logged_in: boolean; + is_logging_in: boolean; +};