From 1437e77d18dc1c6762768a8a89f25fe94a20a032 Mon Sep 17 00:00:00 2001 From: kate-deriv <121025168+kate-deriv@users.noreply.github.com> Date: Wed, 22 May 2024 10:28:34 +0300 Subject: [PATCH] DTRA-1279 / Kate / Refactor handling open and closed positions and their filtration (#56) * refactor: move stor values to poitions content file * chore: remove code smell --- .../Positions/positions-content.tsx | 333 ++++++++++++++++-- .../AppV2/Containers/Positions/positions.tsx | 326 +---------------- .../src/AppV2/Hooks/useClosedPositions.ts | 6 +- 3 files changed, 316 insertions(+), 349 deletions(-) diff --git a/packages/trader/src/AppV2/Containers/Positions/positions-content.tsx b/packages/trader/src/AppV2/Containers/Positions/positions-content.tsx index ac2ba5c05931..e4000c61caf0 100644 --- a/packages/trader/src/AppV2/Containers/Positions/positions-content.tsx +++ b/packages/trader/src/AppV2/Containers/Positions/positions-content.tsx @@ -4,40 +4,325 @@ import { TEmptyMessageProps } from 'AppV2/Components/EmptyMessage/empty-message' import { TPortfolioPosition } from '@deriv/stores/types'; import { ContractCardList } from 'AppV2/Components/ContractCard'; import Filter from 'AppV2/Components/Filter'; -import type { TContractCardListProps } from 'AppV2/Components/ContractCard/contract-card-list'; import { Loading } from '@deriv/components'; +import { observer, useStore } from '@deriv/stores'; +import { filterPositions } from '../../Utils/positions-utils'; +import { useReportsStore } from '../../../../../reports/src/Stores/useReportsStores'; + +type TPositionsContentProps = Omit; + +// TODO: Remove after real data is available +const mockedActivePositions = [ + { + contract_info: { + account_id: 112905368, + barrier: '682.60', + barrier_count: 1, + bid_price: 6.38, + buy_price: 9, + contract_id: 242807007748, + contract_type: 'CALL', + currency: 'USD', + current_spot: 681.76, + current_spot_display_value: '681.76', + current_spot_time: 1716220628, + date_expiry: 1716221100, + date_settlement: 1716221100, + date_start: 1716220562, + display_name: 'Volatility 100 (1s) Index', + entry_spot: 682.6, + entry_spot_display_value: '682.60', + entry_tick: 682.6, + entry_tick_display_value: '682.60', + entry_tick_time: 1716220563, + expiry_time: 1716221100, + id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', + is_expired: 0, + is_forward_starting: 0, + is_intraday: 1, + is_path_dependent: 0, + is_settleable: 0, + is_sold: 0, + is_valid_to_cancel: 0, + is_valid_to_sell: 1, + longcode: + 'Win payout if Volatility 100 (1s) Index is strictly higher than entry spot at 2024-05-20 16:05:00 GMT.', + payout: 17.61, + profit: -2.62, + profit_percentage: -29.11, + purchase_time: 1716220562, + shortcode: 'CALL_1HZ100V_17.61_1716220562_1716221100F_S0P_0', + status: 'open', + transaction_ids: { + buy: 484286139408, + }, + underlying: '1HZ100V', + }, + details: + 'Win payout if Volatility 100 (1s) Index is strictly higher than entry spot at 2024-05-20 16:05:00 GMT.', + display_name: '', + id: 242807007748, + indicative: 6.38, + payout: 17.61, + purchase: 9, + reference: 484286139408, + type: 'CALL', + profit_loss: -2.62, + is_valid_to_sell: true, + status: 'profit', + barrier: 682.6, + entry_spot: 682.6, + }, + { + contract_info: { + account_id: 112905368, + barrier_count: 1, + bid_price: 8.9, + buy_price: 9.39, + cancellation: { + ask_price: 0.39, + date_expiry: 1716224183, + }, + commission: 0.03, + contract_id: 242807045608, + contract_type: 'MULTUP', + currency: 'USD', + current_spot: 681.71, + current_spot_display_value: '681.71', + current_spot_time: 1716220672, + date_expiry: 4869849599, + date_settlement: 4869849600, + date_start: 1716220583, + display_name: 'Volatility 100 (1s) Index', + entry_spot: 682.23, + entry_spot_display_value: '682.23', + entry_tick: 682.23, + entry_tick_display_value: '682.23', + entry_tick_time: 1716220584, + expiry_time: 4869849599, + id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', + is_expired: 0, + is_forward_starting: 0, + is_intraday: 0, + is_path_dependent: 1, + is_settleable: 0, + is_sold: 0, + is_valid_to_cancel: 1, + is_valid_to_sell: 0, + limit_order: { + stop_out: { + display_name: 'Stop out', + order_amount: -9, + order_date: 1716220583, + value: '614.26', + }, + }, + longcode: + "If you select 'Up', your total profit/loss will be the percentage increase in Volatility 100 (1s) Index, multiplied by 90, minus commissions.", + multiplier: 10, + profit: -0.1, + profit_percentage: -1.11, + purchase_time: 1716220583, + shortcode: 'MULTUP_1HZ100V_9.00_10_1716220583_4869849599_60m_0.00_N1', + status: 'open', + transaction_ids: { + buy: 484286215128, + }, + underlying: '1HZ100V', + validation_error: + 'The spot price has moved. We have not closed this contract because your profit is negative and deal cancellation is active. Cancel your contract to get your full stake back.', + validation_error_code: 'General', + }, + details: + "If you select 'Up', your total profit/loss will be the percentage increase in Volatility 100 (1s) Index, multiplied by 90, minus commissions.", + display_name: '', + id: 242807045608, + indicative: 8.9, + purchase: 9.39, + reference: 484286215128, + type: 'MULTUP', + contract_update: { + stop_out: { + display_name: 'Stop out', + order_amount: -9, + order_date: 1716220583, + value: '614.26', + }, + }, + profit_loss: -0.1, + is_valid_to_sell: false, + status: 'profit', + entry_spot: 682.23, + }, + { + contract_info: { + account_id: 112905368, + barrier_count: 2, + barrier_spot_distance: '0.296', + bid_price: 9.84, + buy_price: 9, + contract_id: 242807268688, + contract_type: 'ACCU', + currency: 'USD', + current_spot: 682.72, + current_spot_display_value: '682.72', + current_spot_high_barrier: '683.016', + current_spot_low_barrier: '682.424', + current_spot_time: 1716220720, + date_expiry: 1747785599, + date_settlement: 1747785600, + date_start: 1716220710, + display_name: 'Volatility 100 (1s) Index', + entry_spot: 682.58, + entry_spot_display_value: '682.58', + entry_tick: 682.58, + entry_tick_display_value: '682.58', + entry_tick_time: 1716220711, + expiry_time: 1747785599, + growth_rate: 0.01, + high_barrier: '683.046', + id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', + is_expired: 0, + is_forward_starting: 0, + is_intraday: 0, + is_path_dependent: 1, + is_settleable: 0, + is_sold: 0, + is_valid_to_cancel: 0, + is_valid_to_sell: 1, + longcode: + 'After the entry spot tick, your stake will grow continuously by 1% for every tick that the spot price remains within the ± 0.04331% from the previous spot price.', + low_barrier: '682.454', + profit: 0.84, + profit_percentage: 9.33, + purchase_time: 1716220710, + shortcode: 'ACCU_1HZ100V_9.00_0_0.01_1_0.000433139675_1716220710', + status: 'open', + tick_count: 230, + tick_passed: 9, + tick_stream: [ + { + epoch: 1716220711, + tick: 682.58, + tick_display_value: '682.58', + }, + { + epoch: 1716220712, + tick: 682.71, + tick_display_value: '682.71', + }, + { + epoch: 1716220713, + tick: 682.5, + tick_display_value: '682.50', + }, + { + epoch: 1716220714, + tick: 682.57, + tick_display_value: '682.57', + }, + { + epoch: 1716220715, + tick: 682.57, + tick_display_value: '682.57', + }, + { + epoch: 1716220716, + tick: 682.75, + tick_display_value: '682.75', + }, + { + epoch: 1716220717, + tick: 682.87, + tick_display_value: '682.87', + }, + { + epoch: 1716220718, + tick: 682.74, + tick_display_value: '682.74', + }, + { + epoch: 1716220719, + tick: 682.75, + tick_display_value: '682.75', + }, + { + epoch: 1716220720, + tick: 682.72, + tick_display_value: '682.72', + }, + ], + transaction_ids: { + buy: 484286658868, + }, + underlying: '1HZ100V', + }, + details: + 'After the entry spot tick, your stake will grow continuously by 1% for every tick that the spot price remains within the ± 0.04331% from the previous spot price.', + display_name: '', + id: 242807268688, + indicative: 9.84, + purchase: 9, + reference: 484286658868, + type: 'ACCU', + profit_loss: 0.84, + is_valid_to_sell: true, + current_tick: 9, + status: 'profit', + entry_spot: 682.58, + high_barrier: 683.046, + low_barrier: 682.454, + }, +] as TPortfolioPosition[]; + +const PositionsContent = observer(({ isClosedTab, onRedirectToTrade }: TPositionsContentProps) => { + const [contractTypeFilter, setContractTypeFilter] = React.useState([]); + const [filteredPositions, setFilteredPositions] = React.useState([]); + const [positions, setPositions] = React.useState([]); + const [noMatchesFound, setNoMatchesFound] = React.useState(false); + + const { client, portfolio } = useStore(); + const { currency } = client; + const { onClickCancel, onClickSell } = portfolio; + const { data, is_loading: isLoading, onMount } = useReportsStore().profit_table; + const closedPositions = React.useMemo(() => data.map(d => ({ contract_info: d })), [data]); + + React.useEffect(() => { + onMount(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + React.useEffect(() => { + if (!isLoading) + setPositions(isClosedTab ? (closedPositions as unknown as TPortfolioPosition[]) : mockedActivePositions); + }, [isLoading, isClosedTab, closedPositions, mockedActivePositions]); + + React.useEffect(() => { + if (contractTypeFilter.length) { + const result = filterPositions(positions, contractTypeFilter); + setNoMatchesFound(!result.length); + setFilteredPositions(result); + } else setFilteredPositions(positions); + }, [contractTypeFilter, positions]); -type TPositionsContentProps = Omit & - Pick & { - contractTypeFilter: string[] | []; - isLoading?: boolean; - noMatchesFound?: boolean; - positions?: TPortfolioPosition[]; - setContractTypeFilter: React.Dispatch>; - }; - -const PositionsContent = ({ - contractTypeFilter, - isClosedTab, - isLoading, - noMatchesFound, - onRedirectToTrade, - positions = [], - setContractTypeFilter, - ...rest -}: TPositionsContentProps) => { if (isLoading) return ; + return (
- {(!!positions.length || (!positions.length && noMatchesFound)) && ( + {(!!filteredPositions.length || (!filteredPositions.length && noMatchesFound)) && (
)}
- {positions.length ? ( - + {filteredPositions.length ? ( + ) : ( ); -}; +}); export default PositionsContent; diff --git a/packages/trader/src/AppV2/Containers/Positions/positions.tsx b/packages/trader/src/AppV2/Containers/Positions/positions.tsx index 848b39c41137..74cccd748b56 100644 --- a/packages/trader/src/AppV2/Containers/Positions/positions.tsx +++ b/packages/trader/src/AppV2/Containers/Positions/positions.tsx @@ -1,344 +1,26 @@ import React from 'react'; import { Localize } from '@deriv/translations'; import { Tab } from '@deriv-com/quill-ui'; -import { TPortfolioPosition } from '@deriv/stores/types'; -import { observer, useStore } from '@deriv/stores'; -import { filterPositions } from '../../Utils/positions-utils'; import PositionsContent from './positions-content'; -import { useReportsStore } from '../../../../../reports/src/Stores/useReportsStores'; type TPositionsProps = { onRedirectToTrade?: () => void; }; -// TODO: Remove after real data is available -const mockedActivePositions = [ - { - contract_info: { - account_id: 112905368, - barrier: '682.60', - barrier_count: 1, - bid_price: 6.38, - buy_price: 9, - contract_id: 242807007748, - contract_type: 'CALL', - currency: 'USD', - current_spot: 681.76, - current_spot_display_value: '681.76', - current_spot_time: 1716220628, - date_expiry: 1716221100, - date_settlement: 1716221100, - date_start: 1716220562, - display_name: 'Volatility 100 (1s) Index', - entry_spot: 682.6, - entry_spot_display_value: '682.60', - entry_tick: 682.6, - entry_tick_display_value: '682.60', - entry_tick_time: 1716220563, - expiry_time: 1716221100, - id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', - is_expired: 0, - is_forward_starting: 0, - is_intraday: 1, - is_path_dependent: 0, - is_settleable: 0, - is_sold: 0, - is_valid_to_cancel: 0, - is_valid_to_sell: 1, - longcode: - 'Win payout if Volatility 100 (1s) Index is strictly higher than entry spot at 2024-05-20 16:05:00 GMT.', - payout: 17.61, - profit: -2.62, - profit_percentage: -29.11, - purchase_time: 1716220562, - shortcode: 'CALL_1HZ100V_17.61_1716220562_1716221100F_S0P_0', - status: 'open', - transaction_ids: { - buy: 484286139408, - }, - underlying: '1HZ100V', - }, - details: - 'Win payout if Volatility 100 (1s) Index is strictly higher than entry spot at 2024-05-20 16:05:00 GMT.', - display_name: '', - id: 242807007748, - indicative: 6.38, - payout: 17.61, - purchase: 9, - reference: 484286139408, - type: 'CALL', - profit_loss: -2.62, - is_valid_to_sell: true, - status: 'profit', - barrier: 682.6, - entry_spot: 682.6, - }, - { - contract_info: { - account_id: 112905368, - barrier_count: 1, - bid_price: 8.9, - buy_price: 9.39, - cancellation: { - ask_price: 0.39, - date_expiry: 1716224183, - }, - commission: 0.03, - contract_id: 242807045608, - contract_type: 'MULTUP', - currency: 'USD', - current_spot: 681.71, - current_spot_display_value: '681.71', - current_spot_time: 1716220672, - date_expiry: 4869849599, - date_settlement: 4869849600, - date_start: 1716220583, - display_name: 'Volatility 100 (1s) Index', - entry_spot: 682.23, - entry_spot_display_value: '682.23', - entry_tick: 682.23, - entry_tick_display_value: '682.23', - entry_tick_time: 1716220584, - expiry_time: 4869849599, - id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', - is_expired: 0, - is_forward_starting: 0, - is_intraday: 0, - is_path_dependent: 1, - is_settleable: 0, - is_sold: 0, - is_valid_to_cancel: 1, - is_valid_to_sell: 0, - limit_order: { - stop_out: { - display_name: 'Stop out', - order_amount: -9, - order_date: 1716220583, - value: '614.26', - }, - }, - longcode: - "If you select 'Up', your total profit/loss will be the percentage increase in Volatility 100 (1s) Index, multiplied by 90, minus commissions.", - multiplier: 10, - profit: -0.1, - profit_percentage: -1.11, - purchase_time: 1716220583, - shortcode: 'MULTUP_1HZ100V_9.00_10_1716220583_4869849599_60m_0.00_N1', - status: 'open', - transaction_ids: { - buy: 484286215128, - }, - underlying: '1HZ100V', - validation_error: - 'The spot price has moved. We have not closed this contract because your profit is negative and deal cancellation is active. Cancel your contract to get your full stake back.', - validation_error_code: 'General', - }, - details: - "If you select 'Up', your total profit/loss will be the percentage increase in Volatility 100 (1s) Index, multiplied by 90, minus commissions.", - display_name: '', - id: 242807045608, - indicative: 8.9, - purchase: 9.39, - reference: 484286215128, - type: 'MULTUP', - contract_update: { - stop_out: { - display_name: 'Stop out', - order_amount: -9, - order_date: 1716220583, - value: '614.26', - }, - }, - profit_loss: -0.1, - is_valid_to_sell: false, - status: 'profit', - entry_spot: 682.23, - }, - { - contract_info: { - account_id: 112905368, - barrier_count: 2, - barrier_spot_distance: '0.296', - bid_price: 9.84, - buy_price: 9, - contract_id: 242807268688, - contract_type: 'ACCU', - currency: 'USD', - current_spot: 682.72, - current_spot_display_value: '682.72', - current_spot_high_barrier: '683.016', - current_spot_low_barrier: '682.424', - current_spot_time: 1716220720, - date_expiry: 1747785599, - date_settlement: 1747785600, - date_start: 1716220710, - display_name: 'Volatility 100 (1s) Index', - entry_spot: 682.58, - entry_spot_display_value: '682.58', - entry_tick: 682.58, - entry_tick_display_value: '682.58', - entry_tick_time: 1716220711, - expiry_time: 1747785599, - growth_rate: 0.01, - high_barrier: '683.046', - id: '917d1b48-305b-a2f4-5b9c-7fb1f2c6c145', - is_expired: 0, - is_forward_starting: 0, - is_intraday: 0, - is_path_dependent: 1, - is_settleable: 0, - is_sold: 0, - is_valid_to_cancel: 0, - is_valid_to_sell: 1, - longcode: - 'After the entry spot tick, your stake will grow continuously by 1% for every tick that the spot price remains within the ± 0.04331% from the previous spot price.', - low_barrier: '682.454', - profit: 0.84, - profit_percentage: 9.33, - purchase_time: 1716220710, - shortcode: 'ACCU_1HZ100V_9.00_0_0.01_1_0.000433139675_1716220710', - status: 'open', - tick_count: 230, - tick_passed: 9, - tick_stream: [ - { - epoch: 1716220711, - tick: 682.58, - tick_display_value: '682.58', - }, - { - epoch: 1716220712, - tick: 682.71, - tick_display_value: '682.71', - }, - { - epoch: 1716220713, - tick: 682.5, - tick_display_value: '682.50', - }, - { - epoch: 1716220714, - tick: 682.57, - tick_display_value: '682.57', - }, - { - epoch: 1716220715, - tick: 682.57, - tick_display_value: '682.57', - }, - { - epoch: 1716220716, - tick: 682.75, - tick_display_value: '682.75', - }, - { - epoch: 1716220717, - tick: 682.87, - tick_display_value: '682.87', - }, - { - epoch: 1716220718, - tick: 682.74, - tick_display_value: '682.74', - }, - { - epoch: 1716220719, - tick: 682.75, - tick_display_value: '682.75', - }, - { - epoch: 1716220720, - tick: 682.72, - tick_display_value: '682.72', - }, - ], - transaction_ids: { - buy: 484286658868, - }, - underlying: '1HZ100V', - }, - details: - 'After the entry spot tick, your stake will grow continuously by 1% for every tick that the spot price remains within the ± 0.04331% from the previous spot price.', - display_name: '', - id: 242807268688, - indicative: 9.84, - purchase: 9, - reference: 484286658868, - type: 'ACCU', - profit_loss: 0.84, - is_valid_to_sell: true, - current_tick: 9, - status: 'profit', - entry_spot: 682.58, - high_barrier: 683.046, - low_barrier: 682.454, - }, -] as TPortfolioPosition[]; - -const Positions = observer(({ onRedirectToTrade }: TPositionsProps) => { - const [contractTypeFilter, setContractTypeFilter] = React.useState([]); - const [filteredPositions, setFilteredPositions] = React.useState>>( - [] - ); - const [noMatchesFound, setNoMatchesFound] = React.useState(false); - const { client, portfolio } = useStore(); - const { currency } = client; - const { onClickCancel, onClickSell } = portfolio; - const { data, is_loading, onMount } = useReportsStore().profit_table; - const closedPositions = React.useMemo(() => data.map(d => ({ contract_info: d })), [data]); - +const Positions = ({ onRedirectToTrade }: TPositionsProps) => { const tabs = [ { id: 'open', title: , - content: ( - - ), + content: , }, { id: 'closed', title: , - content: ( - - ), + content: , }, ]; - React.useEffect(() => { - onMount(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - React.useEffect(() => { - if (contractTypeFilter.length) { - const result = filterPositions(closedPositions as unknown as TPortfolioPosition[], contractTypeFilter); - setNoMatchesFound(!result.length); - setFilteredPositions(result as unknown as TPortfolioPosition[]); - } else setFilteredPositions(closedPositions as unknown as TPortfolioPosition[]); - }, [contractTypeFilter, closedPositions]); - - React.useEffect(() => { - if (!is_loading) setFilteredPositions(closedPositions as unknown as TPortfolioPosition[]); - }, [is_loading, closedPositions]); - return (
@@ -355,6 +37,6 @@ const Positions = observer(({ onRedirectToTrade }: TPositionsProps) => {
); -}); +}; export default Positions; diff --git a/packages/trader/src/AppV2/Hooks/useClosedPositions.ts b/packages/trader/src/AppV2/Hooks/useClosedPositions.ts index 6c936a7f9b3c..a6d4b1e8da9b 100644 --- a/packages/trader/src/AppV2/Hooks/useClosedPositions.ts +++ b/packages/trader/src/AppV2/Hooks/useClosedPositions.ts @@ -11,17 +11,17 @@ type TPros = { const useClosedPositions = ({ date_from, date_to }: TPros = {}) => { const [positions, setPositions] = useState>([]); - const [isLoading, setLoading] = React.useState(false); + const [isLoading, setIsLoading] = React.useState(false); const positionsRef = useRef>([]); const fetch = useCallback(async () => { - setLoading(true); + setIsLoading(true); const data: ProfitTableResponse = await WS.profitTable(50, positionsRef.current.length, { date_from, date_to, }); - setLoading(false); + setIsLoading(false); // TODO: handle errors setPositions(prevPositions => [...prevPositions, ...(data?.profit_table?.transactions ?? [])]); }, [date_from, date_to]);