From 59e9b174a7b6010b5b2159b7168af41755dd3abe Mon Sep 17 00:00:00 2001
From: balakrishna-deriv <56330681+balakrishna-deriv@users.noreply.github.com>
Date: Tue, 21 May 2024 15:14:58 +0800
Subject: [PATCH] chore: add modules store and useclosedposition hook (#52)
---
packages/trader/src/App/app.tsx | 15 ++++----
.../AppV2/Containers/Positions/positions.tsx | 16 +++++++--
.../src/AppV2/Hooks/useClosedPositions.ts | 34 +++++++++++++++++++
packages/trader/src/AppV2/app.tsx | 15 ++++----
.../Modules/Positions/positions-store.ts | 22 ++++++++++++
.../Trading/__tests__/trade-store.spec.ts | 3 +-
.../src/Stores/Modules/Trading/trade-store.ts | 5 ++-
packages/trader/src/Stores/Modules/index.js | 8 -----
packages/trader/src/Stores/Modules/index.ts | 16 +++++++++
.../Stores/Providers/modules-providers.tsx | 14 ++++++++
packages/trader/src/Stores/base-store.ts | 6 ++--
.../trader/src/Stores/useModulesStores.tsx | 20 +++++++++++
packages/trader/src/Types/common-prop.type.ts | 15 ++++++++
13 files changed, 160 insertions(+), 29 deletions(-)
create mode 100644 packages/trader/src/AppV2/Hooks/useClosedPositions.ts
create mode 100644 packages/trader/src/Stores/Modules/Positions/positions-store.ts
delete mode 100644 packages/trader/src/Stores/Modules/index.js
create mode 100644 packages/trader/src/Stores/Modules/index.ts
create mode 100644 packages/trader/src/Stores/Providers/modules-providers.tsx
create mode 100644 packages/trader/src/Stores/useModulesStores.tsx
diff --git a/packages/trader/src/App/app.tsx b/packages/trader/src/App/app.tsx
index 87ce015eddc5..79be0e1500fc 100644
--- a/packages/trader/src/App/app.tsx
+++ b/packages/trader/src/App/app.tsx
@@ -10,6 +10,7 @@ import initStore from './init-store';
import 'Sass/app.scss';
import type { TCoreStores } from '@deriv/stores/types';
import TraderProviders from '../trader-providers';
+import ModulesProvider from 'Stores/Providers/modules-providers';
type Apptypes = {
passthrough: {
@@ -31,12 +32,14 @@ const App = ({ passthrough }: Apptypes) => {
return (
-
-
-
-
-
-
+
+
+
+
+
+
+
+
);
};
diff --git a/packages/trader/src/AppV2/Containers/Positions/positions.tsx b/packages/trader/src/AppV2/Containers/Positions/positions.tsx
index 41a82df196ae..b4c18cd68e87 100644
--- a/packages/trader/src/AppV2/Containers/Positions/positions.tsx
+++ b/packages/trader/src/AppV2/Containers/Positions/positions.tsx
@@ -2,8 +2,11 @@ import React from 'react';
import { Localize } from '@deriv/translations';
import { Tab } from '@deriv-com/quill-ui';
import { TPortfolioPosition } from '@deriv/stores/types';
+import useClosedPositions from 'AppV2/Hooks/useClosedPositions';
+import { useModulesStore } from 'Stores/useModulesStores';
import { filterPositions } from '../../Utils/positions-utils';
import PositionsContent from './positions-content';
+import { observer } from '@deriv/stores';
type TPositionsProps = {
onRedirectToTrade?: () => void;
@@ -55,11 +58,20 @@ const mockPositions = [
},
] as TPortfolioPosition[];
-const Positions = ({ onRedirectToTrade }: TPositionsProps) => {
+const Positions = observer(({ onRedirectToTrade }: TPositionsProps) => {
const [contractTypeFilter, setContractTypeFilter] = React.useState([]);
const [filteredPositions, setFilteredPositions] = React.useState(mockPositions || []);
const [noMatchesFound, setNoMatchesFound] = React.useState(false);
+ const { positions: positionsStore } = useModulesStore();
+ const { closedContractTypeFilter } = positionsStore;
+
+ const { closedPositions } = useClosedPositions({ contractTypes: closedContractTypeFilter });
+
+ // TODO: remove this line
+ // eslint-disable-next-line no-console
+ console.log('closedPositions', closedPositions);
+
const tabs = [
{
id: 'open',
@@ -111,6 +123,6 @@ const Positions = ({ onRedirectToTrade }: TPositionsProps) => {
);
-};
+});
export default Positions;
diff --git a/packages/trader/src/AppV2/Hooks/useClosedPositions.ts b/packages/trader/src/AppV2/Hooks/useClosedPositions.ts
new file mode 100644
index 000000000000..e91b3793f862
--- /dev/null
+++ b/packages/trader/src/AppV2/Hooks/useClosedPositions.ts
@@ -0,0 +1,34 @@
+import { WS } from '@deriv/shared';
+import React, { useCallback, useEffect, useRef, useState } from 'react';
+import { ProfitTable, ProfitTableResponse } from '@deriv/api-types';
+
+type TPros = {
+ contractTypes: string[];
+};
+
+const useClosedPositions = ({ contractTypes }: TPros) => {
+ const [positions, setPositions] = useState>([]);
+ const [isLoading, setLoading] = React.useState(false);
+ const positionsRef = useRef>([]);
+
+ const fetch = useCallback(async () => {
+ setLoading(true);
+ const data: ProfitTableResponse = await WS.profitTable(50, positionsRef.current.length, {
+ contract_type: contractTypes.length > 0 ? contractTypes : undefined,
+ });
+
+ setLoading(false);
+ // TODO: handle errors
+ setPositions(prevPositions => [...prevPositions, ...(data?.profit_table?.transactions ?? [])]);
+ }, [contractTypes]);
+
+ useEffect(() => {
+ setPositions([]);
+ positionsRef.current = [];
+ fetch();
+ }, [fetch, contractTypes]);
+
+ return { closedPositions: positions, isLoading, fetchMore: fetch };
+};
+
+export default useClosedPositions;
diff --git a/packages/trader/src/AppV2/app.tsx b/packages/trader/src/AppV2/app.tsx
index ba2a90e113f8..f6fadef0dd8e 100644
--- a/packages/trader/src/AppV2/app.tsx
+++ b/packages/trader/src/AppV2/app.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import type { TWebSocket } from 'Types';
import initStore from 'App/init-store';
import type { TCoreStores } from '@deriv/stores/types';
+import ModulesProvider from 'Stores/Providers/modules-providers';
import TraderProviders from '../trader-providers';
import BottomNav from './Components/BottomNav';
import Trade from './Containers/Trade';
@@ -28,12 +29,14 @@ const App = ({ passthrough }: Apptypes) => {
return (
-
-
-
- setCurrentPageIdx(0)} />
-
-
+
+
+
+
+ setCurrentPageIdx(0)} />
+
+
+
);
};
diff --git a/packages/trader/src/Stores/Modules/Positions/positions-store.ts b/packages/trader/src/Stores/Modules/Positions/positions-store.ts
new file mode 100644
index 000000000000..3786fc238f3b
--- /dev/null
+++ b/packages/trader/src/Stores/Modules/Positions/positions-store.ts
@@ -0,0 +1,22 @@
+import { makeObservable, observable, action } from 'mobx';
+import { TRootStore } from 'Types';
+import BaseStore from 'Stores/base-store';
+
+export default class PositionsStore extends BaseStore {
+ openContractTypeFilter: string[] = [];
+ closedContractTypeFilter: string[] = [];
+
+ constructor({ root_store }: { root_store: TRootStore }) {
+ super({ root_store });
+
+ makeObservable(this, {
+ openContractTypeFilter: observable,
+ closedContractTypeFilter: observable,
+ addToClosedContractTypeFilter: action.bound,
+ });
+ }
+
+ addToClosedContractTypeFilter(contractType: string) {
+ this.closedContractTypeFilter = [...this.closedContractTypeFilter, contractType];
+ }
+}
diff --git a/packages/trader/src/Stores/Modules/Trading/__tests__/trade-store.spec.ts b/packages/trader/src/Stores/Modules/Trading/__tests__/trade-store.spec.ts
index cabfca201c7d..9b0b04621e59 100644
--- a/packages/trader/src/Stores/Modules/Trading/__tests__/trade-store.spec.ts
+++ b/packages/trader/src/Stores/Modules/Trading/__tests__/trade-store.spec.ts
@@ -5,6 +5,7 @@ import { mockStore } from '@deriv/stores';
import TradeStore from '../trade-store';
import { configure } from 'mobx';
import { ContractType } from '../Helpers/contract-type';
+import { TRootStore } from 'Types';
configure({ safeDescriptors: false });
@@ -248,7 +249,7 @@ beforeAll(async () => {
common: {
server_time: moment('2024-02-26T11:59:59.488Z'),
},
- }),
+ }) as unknown as TRootStore,
});
await ContractType.buildContractTypesConfig(symbol);
mockedTradeStore.onMount();
diff --git a/packages/trader/src/Stores/Modules/Trading/trade-store.ts b/packages/trader/src/Stores/Modules/Trading/trade-store.ts
index dc793ea00544..17a5c5a9a3e8 100644
--- a/packages/trader/src/Stores/Modules/Trading/trade-store.ts
+++ b/packages/trader/src/Stores/Modules/Trading/trade-store.ts
@@ -50,11 +50,10 @@ import { action, computed, makeObservable, observable, override, reaction, runIn
import { createProposalRequests, getProposalErrorField, getProposalInfo } from './Helpers/proposal';
import { getHoveredColor } from './Helpers/barrier-utils';
import BaseStore from '../../base-store';
-import { TTextValueNumber, TTextValueStrings } from 'Types';
+import { TRootStore, TTextValueNumber, TTextValueStrings } from 'Types';
import { ChartBarrierStore } from '../SmartChart/chart-barrier-store';
import debounce from 'lodash.debounce';
import { setLimitOrderBarriers } from './Helpers/limit-orders';
-import type { TCoreStores } from '@deriv/stores/types';
import {
ActiveSymbols,
ActiveSymbolsRequest,
@@ -319,7 +318,7 @@ export default class TradeStore extends BaseStore {
is_initial_barrier_applied = false;
is_digits_widget_active = false;
should_skip_prepost_lifecycle = false;
- constructor({ root_store }: { root_store: TCoreStores }) {
+ constructor({ root_store }: { root_store: TRootStore }) {
const local_storage_properties = [
'amount',
'currency',
diff --git a/packages/trader/src/Stores/Modules/index.js b/packages/trader/src/Stores/Modules/index.js
deleted file mode 100644
index 27463b9f10eb..000000000000
--- a/packages/trader/src/Stores/Modules/index.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import TradeStore from './Trading/trade-store';
-
-export default class ModulesStore {
- constructor(root_store, core_store) {
- this.cashier = core_store.modules.cashier;
- this.trade = new TradeStore({ root_store });
- }
-}
diff --git a/packages/trader/src/Stores/Modules/index.ts b/packages/trader/src/Stores/Modules/index.ts
new file mode 100644
index 000000000000..2504e498067c
--- /dev/null
+++ b/packages/trader/src/Stores/Modules/index.ts
@@ -0,0 +1,16 @@
+import TradeStore from './Trading/trade-store';
+import PositionsStore from './Positions/positions-store';
+import { TCoreStores } from '@deriv/stores/types';
+import { TRootStore } from 'Types';
+
+export default class ModulesStore {
+ positions: PositionsStore;
+ trade: TradeStore;
+ cashier: any;
+
+ constructor(root_store: TRootStore, core_store: TCoreStores) {
+ this.cashier = core_store.modules.cashier;
+ this.trade = new TradeStore({ root_store });
+ this.positions = new PositionsStore({ root_store });
+ }
+}
diff --git a/packages/trader/src/Stores/Providers/modules-providers.tsx b/packages/trader/src/Stores/Providers/modules-providers.tsx
new file mode 100644
index 000000000000..fee7631e0fff
--- /dev/null
+++ b/packages/trader/src/Stores/Providers/modules-providers.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { StoreProvider } from '@deriv/stores';
+import { ModulesStoreProvider } from 'Stores/useModulesStores';
+import type { TCoreStores } from '@deriv/stores/types';
+
+export const ModulesProvider = ({ children, store }: React.PropsWithChildren<{ store: TCoreStores }>) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default ModulesProvider;
diff --git a/packages/trader/src/Stores/base-store.ts b/packages/trader/src/Stores/base-store.ts
index 3d666736ba27..1037acd53796 100644
--- a/packages/trader/src/Stores/base-store.ts
+++ b/packages/trader/src/Stores/base-store.ts
@@ -1,12 +1,12 @@
import { action, intercept, observable, reaction, toJS, when, makeObservable } from 'mobx';
import { isProduction, isEmptyObject, Validator } from '@deriv/shared';
-import { TCoreStores } from '@deriv/stores/types';
import { getValidationRules } from './Modules/Trading/Constants/validation-rules';
+import { TRootStore } from 'Types';
type TValidationRules = ReturnType | Record;
type TBaseStoreOptions = {
- root_store: TCoreStores;
+ root_store: TRootStore;
local_storage_properties?: string[];
session_storage_properties?: string[];
validation_rules?: TValidationRules;
@@ -38,7 +38,7 @@ export default class BaseStore {
pre_switch_account_listener: null | (() => Promise) = null;
realAccountSignupEndedDisposer: null | (() => void) = null;
real_account_signup_ended_listener: null | (() => Promise) = null;
- root_store: TCoreStores;
+ root_store: TRootStore;
session_storage_properties: string[];
store_name = '';
switchAccountDisposer: null | (() => void) = null;
diff --git a/packages/trader/src/Stores/useModulesStores.tsx b/packages/trader/src/Stores/useModulesStores.tsx
new file mode 100644
index 000000000000..3ac894968fa0
--- /dev/null
+++ b/packages/trader/src/Stores/useModulesStores.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { useStore } from '@deriv/stores';
+import ModulesStore from './Modules';
+
+const ModulesStoreContext = React.createContext(null);
+
+export const ModulesStoreProvider = ({ children }: React.PropsWithChildren) => {
+ const { modules } = useStore();
+ return {children};
+};
+
+export const useModulesStore = () => {
+ const store = React.useContext(ModulesStoreContext);
+
+ if (!store) {
+ throw new Error('useModulesStore must be used within ModulesStoreProvider');
+ }
+
+ return store;
+};
diff --git a/packages/trader/src/Types/common-prop.type.ts b/packages/trader/src/Types/common-prop.type.ts
index 1ef702385b3d..0ff83bdbd3cc 100644
--- a/packages/trader/src/Types/common-prop.type.ts
+++ b/packages/trader/src/Types/common-prop.type.ts
@@ -19,10 +19,25 @@ import {
UpdateContractRequest,
} from '@deriv/api-types';
import { TCoreStores } from '@deriv/stores/types';
+import ModulesStore from 'Stores/Modules';
import { useTraderStore } from 'Stores/useTraderStores';
import { Redirect, RouteComponentProps } from 'react-router-dom';
import { TSocketEndpointNames, TSocketResponse } from '../../../api/types';
+export type TRootStore = {
+ client: TCoreStores['client'];
+ common: TCoreStores['common'];
+ modules: ModulesStore;
+ ui: TCoreStores['ui'];
+ gtm: TCoreStores['gtm'];
+ notifications: TCoreStores['notifications'];
+ contract_replay: TCoreStores['contract_replay'];
+ contract_trade: TCoreStores['contract_trade'];
+ portfolio: TCoreStores['portfolio'];
+ chart_barrier_store: TCoreStores['chart_barrier_store'];
+ active_symbols: TCoreStores['active_symbols'];
+};
+
export type TBinaryRoutesProps = {
is_logged_in: boolean;
is_logging_in: boolean;