From a431f4c29cae907d1288a6e32f0a1b19417712b7 Mon Sep 17 00:00:00 2001 From: Jim Daniels Wasswa <104334373+jim-deriv@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:03:29 +0800 Subject: [PATCH] Jim | Hamza/88557/replace-connect-with-use-store-trader-parent (#8270) * chore: add useTraderStores * chore: add trader-providers * refactor: replace MobxContentProvider with TraderProviders * chore: update trader to trade * refactor: replace connect in Trader package v1.0 (#76) * refactor: contract-replay, contract-drawer and contract-drawer-card to use useStore (#77) * Jim/93585/replace connect with usestore in market countdown timer market unavailable trade modals unsupported contract modal (#79) * refactor: remove connect from market-countdown-timer * refactor: remove connect from market-unavailable * refactor: remove connect from trade-modals * refactor: move is_visible prop to market-unavailable * refactor: remove connect from unsupported-contract-modal * Hamza/93474/replace connect with use trader store (#78) * refactor: replace connect in Trader package v1.0 * refactor: replace connect with useTraderStore v1.2 * refactor: replace connect with useTraderStore v1.2.1 * refactor: replace connect with useTraderStore v1.2.2 * refactor: replace connect with useTraderStore v1.2.3 * Hamza/93474/replace connect with use trader store (#80) * refactor: replace connect in Trader package v1.0 * refactor: replace connect with useTraderStore v1.2 * refactor: replace connect with useTraderStore v1.2.1 * refactor: replace connect with useTraderStore v1.2.2 * refactor: replace connect with useTraderStore v1.2.3 * refactor: replace connect with useTraderStore v1.3 * refactor: replace connect with useTraderStore v1.4 * Jim/93604/replace connect with use store in positions drawer positions modal card toggle positions mobile time picker populate header (#81) * refactor: remove connect from positions-drawer * refactor: remove connect from positions-modal-card * refactor: remove connect from toggle-positions-mobile * refactor: remove connect from time-picker * refactor: remove connect from populate-header * Jim/93667/replace connect with use store in trade header extensions trade settings extensions progress slider stream routes (#83) * refactor: remove connect from positions-drawer * refactor: remove connect from positions-modal-card * refactor: remove connect from toggle-positions-mobile * refactor: remove connect from time-picker * refactor: remove connect from populate-header * refactor: remove connect from trade-footer-extensions * refactor: migrate trade-header-extensions to ts and remove connect from it * refactor: migrate trade-settings-extensions to ts and remove connect from it * refactor: remove connect from progress-slider-stream and routes * chore: update mocstore with new fields * Hamza/93474/replace connect with use trader store (#82) * refactor: replace connect in Trader package v1.0 * refactor: replace connect with useTraderStore v1.2 * refactor: replace connect with useTraderStore v1.2.1 * refactor: replace connect with useTraderStore v1.2.2 * refactor: replace connect with useTraderStore v1.2.3 * refactor: replace connect with useTraderStore v1.3 * refactor: replace connect with useTraderStore v1.4 * refactor: replace connect with useTraderStore v1.5 * refactor: replace connect with useTraderStore v1.5.1 * refactor: replace connect with useTraderStore v1.5.2 * refactor: replace connect with useTraderStore v1.5.3 test failing fixed * refactor: replace connect with useTraderStore v1.5.4 * Jim/88556/replace connect with use store in settings chart accumulators stats contract replay widget contract and toolbar widgets (#84) * chore: removeconnectsettings-chart/accumulators-stats/contract-replay-widget/contracttoolbar-widgets * refactor: remove connect from accumulators-stats.spec * refactor: replace connect in top-widgets_cancel-deal-mobile_risk-management-info_mobile-widget * Hamza/93474/replace connect with use trader store (#85) * refactor: replace connect in Trader package v1.0 * refactor: replace connect with useTraderStore v1.2 * refactor: replace connect with useTraderStore v1.2.1 * refactor: replace connect with useTraderStore v1.2.2 * refactor: replace connect with useTraderStore v1.2.3 * refactor: replace connect with useTraderStore v1.3 * refactor: replace connect with useTraderStore v1.4 * refactor: replace connect with useTraderStore v1.5 * refactor: replace connect with useTraderStore v1.5.1 * refactor: replace connect with useTraderStore v1.5.2 * refactor: replace connect with useTraderStore v1.5.3 test failing fixed * refactor: replace connect with useTraderStore v1.5.4 * refactor: replace the connect with useStore v1.6 * fix: reverted the duration-wrapper * fix: the duration-wrapper * refactor: replace connect in top-widgets_cancel-deal-mobile_risk-management-info_mobile-widget (#86) * refactor: restore component structure to its original form * refactor: remove MobxContentProvider * refactor: replace connect in strike, vanilla-trade-type, screen-small, chart-widgets, and test * Jim/93866/replace_connect_with_usestore_in_strike_vanilla-trade-type_screen-small_chart-widgets_and_test (#87) * refactor: replace connect in top-widgets_cancel-deal-mobile_risk-management-info_mobile-widget * refactor: restore component structure to its original form * refactor: remove MobxContentProvider * refactor: replace connect in strike, vanilla-trade-type, screen-small, chart-widgets, and test * Hamza/93474/replace connect with use trader store (#88) * refactor: replace connect in Trader package v1.0 * refactor: replace connect with useTraderStore v1.2 * refactor: replace connect with useTraderStore v1.2.1 * refactor: replace connect with useTraderStore v1.2.2 * refactor: replace connect with useTraderStore v1.2.3 * refactor: replace connect with useTraderStore v1.3 * refactor: replace connect with useTraderStore v1.4 * refactor: replace connect with useTraderStore v1.5 * refactor: replace connect with useTraderStore v1.5.1 * refactor: replace connect with useTraderStore v1.5.2 * refactor: replace connect with useTraderStore v1.5.3 test failing fixed * refactor: replace connect with useTraderStore v1.5.4 * refactor: replace the connect with useStore v1.6 * fix: reverted the duration-wrapper * fix: the duration-wrapper * fix: contract not bought error config missing from props * refactor: remove connect function definition and connectwithcontractupdates * Jim/93908/remove-connect-and-connect-with-contract-updates-definitions from trader (#89) * refactor: replace connect in top-widgets_cancel-deal-mobile_risk-management-info_mobile-widget * refactor: restore component structure to its original form * refactor: remove MobxContentProvider * refactor: replace connect in strike, vanilla-trade-type, screen-small, chart-widgets, and test * refactor: remove connect function definition and connectwithcontractupdates * refactor: address whitespace comments, type exportsclear * chore: remove unused invalid import * chore: add type keyword on import statement * chore: add whitespace * refactor: remove passthrough.root_store * chore: restore props * chore: remove sonarcloud bug * refactor: wrap allowequalsmobile in a div to make it collapsible --------- Co-authored-by: Muhammad Hamza <120543468+hamza-deriv@users.noreply.github.com> --- .../src/components/u-i-loader/ui-loader.tsx | 4 +- packages/stores/src/mockStore.ts | 3 + packages/stores/types.ts | 9 + .../ContractDrawer/contract-drawer-card.jsx | 318 ++++---- .../ContractDrawer/contract-drawer.jsx | 280 ++++--- .../market-unavailable.jsx | 67 +- .../unsupported-contract-modal.jsx | 49 +- .../PositionsDrawer/positions-drawer.jsx | 112 ++- .../PositionsDrawer/positions-modal-card.jsx | 731 +++++++++--------- .../toggle-positions-mobile.jsx | 235 +++--- .../Elements/market-countdown-timer.jsx | 13 +- .../Form/TimePicker/time-picker.jsx | 188 +++-- .../App/Containers/Modals/trade-modals.jsx | 60 +- .../progress-slider-stream.jsx | 17 +- .../src/App/Containers/Routes/routes.jsx | 46 +- .../SettingsModal/settings-chart.jsx | 76 +- .../src/App/Containers/populate-header.jsx | 62 +- .../Containers/trade-footer-extensions.jsx | 30 +- ...nsions.jsx => trade-header-extensions.tsx} | 58 +- ...ions.jsx => trade-settings-extensions.tsx} | 32 +- packages/trader/src/App/app.tsx | 42 +- .../__tests__/accumulators-stats.spec.js | 56 +- .../AccumulatorsStats/accumulators-stats.jsx | 18 +- .../Containers/contract-replay-widget.jsx | 61 +- .../Contract/Containers/contract-replay.jsx | 275 +++---- .../Modules/Contract/Containers/contract.jsx | 36 +- .../SmartChart/Components/control-widgets.jsx | 41 +- .../SmartChart/Components/toolbar-widgets.jsx | 20 +- .../SmartChart/Components/top-widgets.jsx | 14 +- .../Multiplier/cancel-deal-mobile.jsx | 211 +++-- .../Multiplier/risk-management-info.jsx | 37 +- .../Components/Elements/mobile-widget.jsx | 53 +- .../Form/DatePicker/trading-date-picker.jsx | 60 +- .../Form/Purchase/cancel-deal-info.jsx | 13 +- .../Form/TimePicker/trading-time-picker.jsx | 42 +- .../Accumulator/__tests__/accumulator.spec.js | 32 +- .../accumulators-info-display.spec.js | 24 +- .../TradeParams/Accumulator/accumulator.jsx | 37 +- .../accumulators-amount-mobile.jsx | 34 +- .../Accumulator/accumulators-info-display.jsx | 22 +- .../Duration/advanced-duration.jsx | 230 +++--- .../TradeParams/Duration/duration-mobile.jsx | 589 +++++++------- .../TradeParams/Duration/duration-wrapper.jsx | 90 ++- .../TradeParams/Duration/simple-duration.jsx | 125 ++- .../TradeParams/Multiplier/cancel-deal.jsx | 51 +- .../Multiplier/expiration-modal.jsx | 17 +- .../TradeParams/Multiplier/expiration.jsx | 17 +- .../Form/TradeParams/Multiplier/info.jsx | 203 +++-- .../TradeParams/Multiplier/multiplier.jsx | 22 +- .../Form/TradeParams/Multiplier/stop-loss.jsx | 65 +- .../TradeParams/Multiplier/take-profit.jsx | 65 +- .../Form/TradeParams/Multiplier/widgets.jsx | 41 +- .../Form/TradeParams/amount-mobile.jsx | 372 +++++---- .../Components/Form/TradeParams/amount.jsx | 100 +-- .../Components/Form/TradeParams/barrier.jsx | 59 +- .../Form/TradeParams/last-digit.jsx | 13 +- .../Components/Form/TradeParams/strike.jsx | 44 +- .../Form/TradeParams/vanilla-trade-types.jsx | 17 +- .../Trading/Components/Form/screen-small.jsx | 81 +- .../Multiplier/multiplier-amount-modal.jsx | 41 +- .../Multiplier/multiplier-options.jsx | 19 +- .../Multiplier/risk-management-dialog.jsx | 40 +- .../Trading/Containers/allow-equals.jsx | 17 +- .../Trading/Containers/chart-widgets.jsx | 59 +- .../Trading/Containers/contract-type.jsx | 52 +- .../Modules/Trading/Containers/purchase.jsx | 103 +-- .../Containers/radio-group-options-modal.jsx | 33 +- .../src/Modules/Trading/Containers/test.jsx | 27 +- .../Trading/Containers/toast-popup.jsx | 19 +- .../Containers/trade-params-mobile.jsx | 316 ++++---- .../Trading/Containers/trade-params.jsx | 14 +- .../src/Modules/Trading/Containers/trade.jsx | 234 ++---- .../Modules/Trading/Helpers/multiplier.js | 13 - packages/trader/src/Stores/connect.js | 31 - .../trader/src/Stores/useTraderStores.tsx | 22 + packages/trader/src/trader-providers.tsx | 14 + 76 files changed, 2987 insertions(+), 3786 deletions(-) rename packages/trader/src/App/Containers/{trade-header-extensions.jsx => trade-header-extensions.tsx} (55%) rename packages/trader/src/App/Containers/{trade-settings-extensions.jsx => trade-settings-extensions.tsx} (68%) delete mode 100644 packages/trader/src/Stores/connect.js create mode 100644 packages/trader/src/Stores/useTraderStores.tsx create mode 100644 packages/trader/src/trader-providers.tsx diff --git a/packages/components/src/components/u-i-loader/ui-loader.tsx b/packages/components/src/components/u-i-loader/ui-loader.tsx index 34ce92b6b06a..beb8f24586a6 100644 --- a/packages/components/src/components/u-i-loader/ui-loader.tsx +++ b/packages/components/src/components/u-i-loader/ui-loader.tsx @@ -1,10 +1,12 @@ import React from 'react'; import classNames from 'classnames'; +import Loadable from 'react-loadable'; type TUILoader = { className?: string; classNameBlock?: string; -}; +} & Loadable.LoadingComponentProps; + const UILoader = ({ className, classNameBlock }: TUILoader) => { const block_class = classNames(classNameBlock, 'block-ui'); const loading_class = classNames('block-ui__loading', className); diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts index fdc85c41b3ec..5a4ae83af7a2 100644 --- a/packages/stores/src/mockStore.ts +++ b/packages/stores/src/mockStore.ts @@ -136,6 +136,7 @@ const mock = (): TStores & { is_mock: boolean } => { is_trading_experience_incomplete: false, is_virtual: false, is_withdrawal_lock: false, + is_populating_account_list: false, landing_company_shortcode: '', local_currency_config: { currency: '', @@ -262,6 +263,8 @@ const mock = (): TStores & { is_mock: boolean } => { is_real_acc_signup_on: false, is_need_real_account_for_cashier_modal_visible: false, toggleNeedRealAccountForCashierModal: jest.fn(), + populateHeaderExtensions: jest.fn(), + populateSettingsExtensions: jest.fn(), setShouldShowCooldownModal: jest.fn(), }, traders_hub: { diff --git a/packages/stores/types.ts b/packages/stores/types.ts index 8c1584c0acdc..81c6c886a067 100644 --- a/packages/stores/types.ts +++ b/packages/stores/types.ts @@ -12,6 +12,12 @@ import type { Moment } from 'moment'; import type { RouteComponentProps } from 'react-router'; import type { ExchangeRatesStore, FeatureFlagsStore } from './src/stores'; +type TPopulateSettingsExtensionsMenuItem = { + icon: string; + label: string; + value: (props: T) => JSX.Element; +}; + type TAccount = NonNullable[0] & { balance?: number; }; @@ -165,6 +171,7 @@ type TClientStore = { is_virtual: boolean; is_withdrawal_lock: boolean; landing_company_shortcode: string; + is_populating_account_list: boolean; local_currency_config: { currency: string; decimal_places?: number; @@ -296,6 +303,8 @@ type TUiStore = { is_real_acc_signup_on: boolean; is_need_real_account_for_cashier_modal_visible: boolean; toggleNeedRealAccountForCashierModal: () => void; + populateHeaderExtensions: (header_items: JSX.Element | null) => void; + populateSettingsExtensions: (menu_items: Array | null) => void; setShouldShowCooldownModal: (value: boolean) => void; }; diff --git a/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer-card.jsx b/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer-card.jsx index 294ddb4ecb87..6f7c2ecd4fe9 100644 --- a/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer-card.jsx +++ b/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer-card.jsx @@ -4,196 +4,172 @@ import React from 'react'; import { DesktopWrapper, MobileWrapper, Collapsible, ContractCard, useHover } from '@deriv/components'; import { isCryptoContract, isDesktop, getEndTime, getSymbolDisplayName } from '@deriv/shared'; import { getCardLabels, getContractTypeDisplay } from 'Constants/contract'; -import { connect } from 'Stores/connect'; import { getMarketInformation } from 'Utils/Helpers/market-underlying'; import { SwipeableContractDrawer } from './swipeable-components.jsx'; import MarketClosedContractOverlay from './market-closed-contract-overlay.jsx'; -import { connectWithContractUpdate } from 'Stores/Modules/Trading/Helpers/multiplier'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; -const ContractDrawerCard = ({ - active_symbols, - addToast, - contract_info, - contract_update, - currency, - current_focus, - getContractById, - is_accumulator, - is_market_closed, - is_mobile, - is_multiplier, - is_vanilla, - is_sell_requested, - is_collapsed, - onClickCancel, - onClickSell, - onSwipedUp, - onSwipedDown, - removeToast, - result, - setCurrentFocus, - server_time, - should_show_cancellation_warning, - status, - toggleCancellationWarning, - toggleContractAuditDrawer, -}) => { - const [hover_ref, should_hide_closed_overlay] = useHover(); +const ContractDrawerCard = observer( + ({ + contract_info, + contract_update, + currency, + is_accumulator, + is_market_closed, + is_mobile, + is_multiplier, + is_vanilla, + is_sell_requested, + is_collapsed, + onClickCancel, + onClickSell, + onSwipedUp, + onSwipedDown, + result, + server_time, + status, + toggleContractAuditDrawer, + }) => { + const { ui, contract_trade } = useStore(); + const { active_symbols } = useTraderStore(); + const { + addToast, + current_focus, + removeToast, + should_show_cancellation_warning, + setCurrentFocus, + toggleCancellationWarning, + } = ui; + const { getContractById } = contract_trade; + const [hover_ref, should_hide_closed_overlay] = useHover(); - const { profit, underlying: symbol } = contract_info; - const is_sold = !!getEndTime(contract_info); - const display_name = getSymbolDisplayName(active_symbols, getMarketInformation(contract_info.shortcode).underlying); + const { profit, underlying: symbol } = contract_info; + const is_sold = !!getEndTime(contract_info); + const display_name = getSymbolDisplayName( + active_symbols, + getMarketInformation(contract_info.shortcode).underlying + ); - const is_crypto = isCryptoContract(contract_info.underlying); - const has_progress_slider = !is_multiplier || (is_crypto && is_multiplier); + const is_crypto = isCryptoContract(contract_info.underlying); + const has_progress_slider = !is_multiplier || (is_crypto && is_multiplier); - const card_header = ( - - ); + const card_header = ( + + ); - const card_body = ( - - ); + const card_body = ( + + ); - const card_footer = ( - - ); + const card_footer = ( + + ); - const contract_el = ( - - {card_header} - {card_body} - - ); + const contract_el = ( + + {card_header} + {card_body} + + ); - const contract_card = ( - -
0 && !result, - 'dc-contract-card--red': is_mobile && !is_multiplier && profit < 0 && !result, - 'contract-card__market-closed--disabled': is_market_closed && should_hide_closed_overlay, - })} - ref={hover_ref} + const contract_card = ( + - {is_market_closed && !getEndTime(contract_info) && ( -
- -
- )} - {contract_el} - {card_footer} -
-
- ); - - const has_swipeable_drawer = is_sold || is_multiplier || is_accumulator || is_vanilla; - - return ( - - {contract_card} - - 0 && !result, + 'dc-contract-card--red': is_mobile && !is_multiplier && profit < 0 && !result, + 'contract-card__market-closed--disabled': is_market_closed && should_hide_closed_overlay, + })} + ref={hover_ref} > - {has_swipeable_drawer && ( - + {is_market_closed && !getEndTime(contract_info) && ( +
+ +
)} - {contract_card} -
-
-
- ); -}; + {contract_el} + {card_footer} + + + ); + + const has_swipeable_drawer = is_sold || is_multiplier || is_accumulator || is_vanilla; + + return ( + + {contract_card} + + + {has_swipeable_drawer && ( + + )} + {contract_card} + + + + ); + } +); ContractDrawerCard.propTypes = { - active_symbols: PropTypes.array, - addToast: PropTypes.func, - contract_info: PropTypes.object, - contract_update: PropTypes.object, currency: PropTypes.string, - current_focus: PropTypes.string, - getContractById: PropTypes.func, is_accumulator: PropTypes.bool, is_collapsed: PropTypes.bool, - is_market_closed: PropTypes.bool, - is_mobile: PropTypes.bool, - is_multiplier: PropTypes.bool, - is_vanilla: PropTypes.bool, - is_sell_requested: PropTypes.bool, onClickCancel: PropTypes.func, onClickSell: PropTypes.func, - onSwipedDown: PropTypes.func, - onSwipedUp: PropTypes.func, - status: PropTypes.string, - removeToast: PropTypes.func, - result: PropTypes.any, - server_time: PropTypes.object, - setCurrentFocus: PropTypes.func, - should_show_cancellation_warning: PropTypes.bool, - toggleCancellationWarning: PropTypes.func, - toggleContractAuditDrawer: PropTypes.func, }; - -export default connect(({ modules, ui, contract_trade }) => ({ - active_symbols: modules.trade.active_symbols, - addToast: ui.addToast, - current_focus: ui.current_focus, - getContractById: contract_trade.getContractById, - removeToast: ui.removeToast, - should_show_cancellation_warning: ui.should_show_cancellation_warning, - setCurrentFocus: ui.setCurrentFocus, - toggleCancellationWarning: ui.toggleCancellationWarning, -}))(ContractDrawerCard); +export default ContractDrawerCard; diff --git a/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer.jsx b/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer.jsx index 11620824a1d2..daaad6f0f55e 100644 --- a/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer.jsx +++ b/packages/trader/src/App/Components/Elements/ContractDrawer/contract-drawer.jsx @@ -14,33 +14,87 @@ import { } from '@deriv/shared'; import ContractAudit from 'App/Components/Elements/ContractAudit'; import { PositionsCardLoader } from 'App/Components/Elements/ContentLoader'; -import { connect } from 'Stores/connect'; import ContractDrawerCard from './contract-drawer-card.jsx'; import { SwipeableContractAudit } from './swipeable-components.jsx'; +import { observer, useStore } from '@deriv/stores'; -const ContractDrawer = ({ - contract_info, - contract_update, - contract_update_history, - is_accumulator, - is_mobile, - is_sell_requested, - is_dark_theme, - is_market_closed, - is_multiplier, - is_vanilla, - onClickCancel, - onClickSell, - server_time, - status, - toggleHistoryTab, -}) => { - const { currency, exit_tick_display_value, is_sold } = contract_info; - const contract_drawer_ref = React.useRef(); - const contract_drawer_card_ref = React.useRef(); - const [should_show_contract_audit, setShouldShowContractAudit] = React.useState(false); +const ContractDrawer = observer( + ({ + contract_info, + contract_update, + contract_update_history, + is_accumulator, + is_sell_requested, + is_dark_theme, + is_market_closed, + is_multiplier, + is_vanilla, + onClickCancel, + onClickSell, + status, + toggleHistoryTab, + }) => { + const { common, ui } = useStore(); + const { server_time } = common; + const { is_mobile } = ui; + const { currency, exit_tick_display_value, is_sold } = contract_info; + const contract_drawer_ref = React.useRef(); + const contract_drawer_card_ref = React.useRef(); + const [should_show_contract_audit, setShouldShowContractAudit] = React.useState(false); + + const getBodyContent = () => { + const exit_spot = + isUserSold(contract_info) && !is_multiplier && !is_accumulator ? '-' : exit_tick_display_value; + + const contract_audit = ( + + ); + + return ( + + setShouldShowContractAudit(true)} + onSwipedDown={() => setShouldShowContractAudit(false)} + server_time={server_time} + status={status} + toggleContractAuditDrawer={() => setShouldShowContractAudit(!should_show_contract_audit)} + /> + {contract_audit} + + ); + }; + + if (!contract_info) return null; + + // For non-binary contract, the status is always null, so we check for is_expired in contract_info + const fallback_result = contract_info.status || contract_info.is_expired; - const getBodyContent = () => { const exit_spot = isUserSold(contract_info) && !is_multiplier && !is_accumulator ? '-' : exit_tick_display_value; @@ -62,142 +116,74 @@ const ContractDrawer = ({ /> ); - return ( - - setShouldShowContractAudit(true)} - onSwipedDown={() => setShouldShowContractAudit(false)} - server_time={server_time} - status={status} - toggleContractAuditDrawer={() => setShouldShowContractAudit(!should_show_contract_audit)} - /> - {contract_audit} - - ); - }; - - if (!contract_info) return null; - - // For non-binary contract, the status is always null, so we check for is_expired in contract_info - const fallback_result = contract_info.status || contract_info.is_expired; - - const exit_spot = isUserSold(contract_info) && !is_multiplier && !is_accumulator ? '-' : exit_tick_display_value; - - const contract_audit = ( - - ); - - const body_content = fallback_result ? ( - getBodyContent() - ) : ( -
- -
- ); - - const contract_drawer = ( - -
-
- {body_content} -
- {should_show_contract_audit && ( - -
- - {contract_audit} - -
-
- )} + const body_content = fallback_result ? ( + getBodyContent() + ) : ( +
+
- - ); + ); - return ( - - {contract_drawer} - + const contract_drawer = ( +
- - {contract_drawer} - +
+ {body_content} +
+ {should_show_contract_audit && ( + +
+ + {contract_audit} + +
+
+ )}
-
-
- ); -}; + + ); + + return ( + + {contract_drawer} + +
+ + {contract_drawer} + +
+
+
+ ); + } +); ContractDrawer.propTypes = { - contract_info: PropTypes.object, - contract_update: PropTypes.object, - contract_update_history: PropTypes.array, is_accumulator: PropTypes.bool, - is_chart_loading: PropTypes.bool, - is_dark_theme: PropTypes.bool, - is_market_closed: PropTypes.bool, - is_mobile: PropTypes.bool, is_multiplier: PropTypes.bool, is_vanilla: PropTypes.bool, - is_history_tab_active: PropTypes.bool, - is_sell_requested: PropTypes.bool, - onClickCancel: PropTypes.func, - onClickContractUpdate: PropTypes.func, - onClickSell: PropTypes.func, - server_time: PropTypes.object, - status: PropTypes.string, toggleHistoryTab: PropTypes.func, }; -export default withRouter( - connect(({ common, ui }) => ({ - server_time: common.server_time, - is_mobile: ui.is_mobile, - }))(ContractDrawer) -); +export default withRouter(ContractDrawer); diff --git a/packages/trader/src/App/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.jsx b/packages/trader/src/App/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.jsx index 393581f4c099..7fbe8ba71f49 100644 --- a/packages/trader/src/App/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.jsx +++ b/packages/trader/src/App/Components/Elements/Modals/MarketUnavailableModal/market-unavailable.jsx @@ -3,47 +3,44 @@ import React from 'react'; import { Dialog } from '@deriv/components'; import { getPlatformSettings } from '@deriv/shared'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; -const MarketUnavailableModal = ({ disableApp, enableApp, is_loading, is_visible, onCancel, onConfirm }) => ( - - { + const { ui } = useStore(); + const { disableApp, enableApp, is_loading, has_only_forward_starting_contracts: is_visible } = ui; + + return ( + - -); + })} + onConfirm={onConfirm} + onCancel={onCancel} + is_mobile_full_width={false} + is_visible={is_visible} + disableApp={disableApp} + enableApp={enableApp} + is_loading={is_loading} + > + + + ); +}); MarketUnavailableModal.propTypes = { - disableApp: PropTypes.func, - enableApp: PropTypes.func, - is_loading: PropTypes.bool, - is_visible: PropTypes.bool, onCancel: PropTypes.func, onConfirm: PropTypes.func, }; -export default connect(({ ui }) => ({ - disableApp: ui.disableApp, - enableApp: ui.enableApp, - is_loading: ui.is_loading, -}))(MarketUnavailableModal); +export default MarketUnavailableModal; diff --git a/packages/trader/src/App/Components/Elements/Modals/UnsupportedContractModal/unsupported-contract-modal.jsx b/packages/trader/src/App/Components/Elements/Modals/UnsupportedContractModal/unsupported-contract-modal.jsx index 4958fdce118c..3cd1b28434ff 100644 --- a/packages/trader/src/App/Components/Elements/Modals/UnsupportedContractModal/unsupported-contract-modal.jsx +++ b/packages/trader/src/App/Components/Elements/Modals/UnsupportedContractModal/unsupported-contract-modal.jsx @@ -2,37 +2,34 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Dialog } from '@deriv/components'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import { website_name } from '@deriv/shared'; +import { observer, useStore } from '@deriv/stores'; -const UnsupportedContractModal = ({ disableApp, enableApp, is_loading, is_visible, onConfirm, onClose }) => ( - - - -); +const UnsupportedContractModal = observer(({ onConfirm, onClose }) => { + const { ui } = useStore(); + const { disableApp, enableApp, is_loading, is_unsupported_contract_modal_visible: is_visible } = ui; + + return ( + + + + ); +}); UnsupportedContractModal.propTypes = { - disableApp: PropTypes.func, - enableApp: PropTypes.func, - is_loading: PropTypes.bool, - is_visible: PropTypes.bool, onClose: PropTypes.func, onConfirm: PropTypes.func, }; -export default connect(({ ui }) => ({ - disableApp: ui.disableApp, - enableApp: ui.enableApp, - is_loading: ui.is_loading, -}))(UnsupportedContractModal); +export default UnsupportedContractModal; diff --git a/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-drawer.jsx b/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-drawer.jsx index 355de07f1470..669b36df7498 100644 --- a/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-drawer.jsx +++ b/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-drawer.jsx @@ -1,5 +1,4 @@ import classNames from 'classnames'; -import { PropTypes as MobxPropTypes } from 'mobx-react'; import PropTypes from 'prop-types'; import React from 'react'; import { NavLink } from 'react-router-dom'; @@ -8,8 +7,9 @@ import { Icon, DataList, Text, PositionsDrawerCard } from '@deriv/components'; import { routes, useNewRowTransition } from '@deriv/shared'; import { localize } from '@deriv/translations'; import EmptyPortfolioMessage from '../EmptyPortfolioMessage'; -import { connect } from 'Stores/connect'; import { filterByContractType } from './helpers'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; const PositionsDrawerCardItem = ({ row: portfolio_position, @@ -56,17 +56,33 @@ const PositionsDrawerCardItem = ({ ); }; -const PositionsDrawer = ({ - all_positions, - error, - is_positions_drawer_on, - onHoverPosition, - symbol, - toggleDrawer, - trade_contract_type, - onMount, - ...props -}) => { +const PositionsDrawer = observer(({ ...props }) => { + const { symbol, contract_type: trade_contract_type } = useTraderStore(); + const { client, common, contract_trade, portfolio, ui } = useStore(); + const { currency } = client; + const { server_time } = common; + const { getContractById } = contract_trade; + const { + all_positions, + error, + onHoverPosition, + onMount, + onClickCancel, + onClickSell, + removePositionById: onClickRemove, + } = portfolio; + const { + is_mobile, + is_positions_drawer_on, + togglePositionsDrawer: toggleDrawer, + addToast, + current_focus, + removeToast, + setCurrentFocus, + should_show_cancellation_warning, + toggleCancellationWarning, + toggleUnsupportedContractModal, + } = ui; const drawer_ref = React.useRef(null); const list_ref = React.useRef(null); const scrollbar_ref = React.useRef(null); @@ -91,7 +107,26 @@ const PositionsDrawer = ({ ( - + )} keyMapper={row => row.id} row_gap={8} @@ -140,57 +175,12 @@ const PositionsDrawer = ({
); -}; +}); PositionsDrawer.propTypes = { - all_positions: MobxPropTypes.arrayOrObservableArray, children: PropTypes.node, - error: PropTypes.string, - is_mobile: PropTypes.bool, - is_positions_drawer_on: PropTypes.bool, onChangeContractUpdate: PropTypes.func, onClickContractUpdate: PropTypes.func, - onHoverPosition: PropTypes.func, - onMount: PropTypes.func, - symbol: PropTypes.string, - toggleDrawer: PropTypes.func, - currency: PropTypes.string, - server_time: PropTypes.object, - addToast: PropTypes.func, - current_focus: PropTypes.string, - onClickCancel: PropTypes.func, - onClickSell: PropTypes.func, - onClickRemove: PropTypes.func, - getContractById: PropTypes.func, - removeToast: PropTypes.func, - setCurrentFocus: PropTypes.func, - should_show_cancellation_warning: PropTypes.bool, - toggleCancellationWarning: PropTypes.func, - toggleUnsupportedContractModal: PropTypes.func, - trade_contract_type: PropTypes.string, }; -export default connect(({ modules, ui, client, common, portfolio, contract_trade }) => ({ - all_positions: portfolio.all_positions, - error: portfolio.error, - onHoverPosition: portfolio.onHoverPosition, - onMount: portfolio.onMount, - symbol: modules.trade.symbol, - trade_contract_type: modules.trade.contract_type, - is_mobile: ui.is_mobile, - is_positions_drawer_on: ui.is_positions_drawer_on, - toggleDrawer: ui.togglePositionsDrawer, - currency: client.currency, - server_time: common.server_time, - addToast: ui.addToast, - current_focus: ui.current_focus, - onClickCancel: portfolio.onClickCancel, - onClickSell: portfolio.onClickSell, - onClickRemove: portfolio.removePositionById, - getContractById: contract_trade.getContractById, - removeToast: ui.removeToast, - setCurrentFocus: ui.setCurrentFocus, - should_show_cancellation_warning: ui.should_show_cancellation_warning, - toggleCancellationWarning: ui.toggleCancellationWarning, - toggleUnsupportedContractModal: ui.toggleUnsupportedContractModal, -}))(PositionsDrawer); +export default PositionsDrawer; diff --git a/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-modal-card.jsx b/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-modal-card.jsx index a1a935447ba9..29e1edb72785 100644 --- a/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-modal-card.jsx +++ b/packages/trader/src/App/Components/Elements/PositionsDrawer/positions-modal-card.jsx @@ -20,423 +20,425 @@ import { } from '@deriv/shared'; import { localize } from '@deriv/translations'; import { BinaryLink } from 'App/Components/Routes'; -import { connect } from 'Stores/connect'; -import { connectWithContractUpdate } from 'Stores/Modules/Trading/Helpers/multiplier'; import { PositionsCardLoader } from 'App/Components/Elements/ContentLoader'; import { getContractTypeDisplay, getCardLabels } from 'Constants/contract'; import { getMarketInformation } from 'Utils/Helpers/market-underlying'; import ResultMobile from './result-mobile.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const PositionsModalCard = ({ - active_symbols, - addToast, - className, - contract_info, - contract_update, - currency, - current_focus, - current_tick, - getContractById, - id, - indicative, - is_loading, - is_mobile, - is_sell_requested, - is_unsupported, - onClickSell, - profit_loss, - onClickCancel, - removeToast, - result, - sell_price, - server_time, - setCurrentFocus, - should_show_cancellation_warning, - status, - toggleCancellationWarning, - togglePositions, - toggleUnsupportedContractModal, - type, -}) => { - const loader_el = ( -
- -
- ); - const is_multiplier = isMultiplierContract(contract_info.contract_type); - const is_accumulator = isAccumulatorContract(contract_info.contract_type); - const is_vanilla = isVanillaContract(contract_info.contract_type); - const is_crypto = isCryptoContract(contract_info.underlying); - const has_progress_slider = !is_multiplier || (is_crypto && is_multiplier); - const has_ended = !!getEndTime(contract_info); - const fallback_result = profit_loss >= 0 ? 'won' : 'lost'; - const total_profit = getTotalProfit(contract_info); +const PositionsModalCard = observer( + ({ + className, + contract_info, + contract_update, + currency, + current_tick, + id, + indicative, + is_loading, + is_sell_requested, + is_unsupported, + onClickSell, + profit_loss, + onClickCancel, + result, + sell_price, + status, + togglePositions, + toggleUnsupportedContractModal, + type, + }) => { + const { ui, common, contract_trade } = useStore(); + const { active_symbols } = useTraderStore(); + const { server_time } = common; + const { getContractById } = contract_trade; + const { + addToast, + current_focus, + is_mobile, + removeToast, + setCurrentFocus, + should_show_cancellation_warning, + toggleCancellationWarning, + } = ui; + const loader_el = ( +
+ +
+ ); + const is_multiplier = isMultiplierContract(contract_info.contract_type); + const is_accumulator = isAccumulatorContract(contract_info.contract_type); + const is_vanilla = isVanillaContract(contract_info.contract_type); + const is_crypto = isCryptoContract(contract_info.underlying); + const has_progress_slider = !is_multiplier || (is_crypto && is_multiplier); + const has_ended = !!getEndTime(contract_info); + const fallback_result = profit_loss >= 0 ? 'won' : 'lost'; + const total_profit = getTotalProfit(contract_info); - const should_show_sell = hasContractEntered(contract_info) && isOpen(contract_info); - const display_name = getSymbolDisplayName(active_symbols, getMarketInformation(contract_info.shortcode).underlying); + const should_show_sell = hasContractEntered(contract_info) && isOpen(contract_info); + const display_name = getSymbolDisplayName( + active_symbols, + getMarketInformation(contract_info.shortcode).underlying + ); - const contract_options_el = ( - -
-
- - - {contract_info.display_name} - -
-
- -
- -
- +
+
+ + + {contract_info.display_name} +
- -
- -
-
-
- {result ? localize('Profit/Loss:') : localize('Potential profit/loss:')} +
+
-
- {!result ? localize('Indicative price:') : localize('Payout:')} -
-
0, - })} - > - +
+ +
+ +
+ +
+
- {status === 'profit' && } - {status === 'loss' && } + {result ? localize('Profit/Loss:') : localize('Potential profit/loss:')}
-
-
-
+ {!result ? localize('Indicative price:') : localize('Payout:')} +
+
0, })} > - {status === 'profit' && } - {status === 'loss' && } + +
+ {status === 'profit' && } + {status === 'loss' && } +
+
+
+ +
+ {status === 'profit' && } + {status === 'loss' && } +
-
-
-
- - {localize('Purchase price:')} - - - - -
-
- - {localize('Potential payout:')} - - - {contract_info.payout ? ( - - ) : ( - -i - )} - +
+
+ + {localize('Purchase price:')} + + + + +
+
+ + {localize('Potential payout:')} + + + {contract_info.payout ? ( + + ) : ( + -i + )} + +
+ + {result || !!contract_info.is_sold ? ( + + ) : ( + + )}
+ + ); - {result || !!contract_info.is_sold ? ( - - ) : ( - + 0 && !result, + 'dc-contract-card--red': !is_multiplier && profit_loss < 0 && !result, + })} + to={{ + pathname: `/contract/${contract_info.contract_id}`, + }} + > + - )} -
- - ); - - const contract_vanilla_el = ( - - 0 && !result, - 'dc-contract-card--red': !is_multiplier && profit_loss < 0 && !result, - })} - to={{ - pathname: `/contract/${contract_info.contract_id}`, - }} - > - - - -
-
-
- - {localize('Buy price:')} - - - - -
-
- - {localize('Contract value:')} - - - - + + +
+
+
+ + {localize('Buy price:')} + + + + +
+
+ + {localize('Contract value:')} + + + + +
-
-
-
- - {localize('Entry spot:')} - - - - -
-
- - {localize('Strike:')} - - - - +
+
+ + {localize('Entry spot:')} + + + + +
+
+ + {localize('Strike:')} + + + + +
-
- {result || !!contract_info.is_sold ? ( - - ) : ( - - )} -
-
-
{getCardLabels().TOTAL_PROFIT_LOSS}
-
0, - })} - > - + {result || !!contract_info.is_sold ? ( + + ) : ( + + )} +
+
+
{getCardLabels().TOTAL_PROFIT_LOSS}
0, })} > - {status === 'profit' && } - {status === 'loss' && } + +
+ {status === 'profit' && } + {status === 'loss' && } +
-
- + + ); + + const custom_card_header = ( + - - ); - - const custom_card_header = ( - - ); + ); - const custom_card_body = ( - - ); - - const custom_card_footer = ( - - ); - - const custom_contract_el = ( - - - {custom_card_header} - {custom_card_body} - {custom_card_footer} - - - ); + is_positions + is_sold={!!contract_info.is_sold} + has_progress_slider={is_mobile && has_progress_slider && !has_ended} + removeToast={removeToast} + server_time={server_time} + setCurrentFocus={setCurrentFocus} + should_show_cancellation_warning={should_show_cancellation_warning} + status={status} + toggleCancellationWarning={toggleCancellationWarning} + /> + ); - const options_el = is_vanilla ? contract_vanilla_el : contract_options_el; - const contract_el = is_multiplier || is_accumulator ? custom_contract_el : options_el; + const custom_card_footer = ( + + ); - return ( -
- {is_unsupported ? ( -
toggleUnsupportedContractModal(true)} + const custom_contract_el = ( + + - {contract_info.underlying ? contract_el : loader_el} -
- ) : ( - - + + ); + + const options_el = is_vanilla ? contract_vanilla_el : contract_options_el; + const contract_el = is_multiplier || is_accumulator ? custom_contract_el : options_el; + + return ( +
+ {is_unsupported ? ( +
toggleUnsupportedContractModal(true)} > {contract_info.underlying ? contract_el : loader_el} - - - )} -
- ); -}; +
+ ) : ( + + + {contract_info.underlying ? contract_el : loader_el} + + + )} +
+ ); + } +); PositionsModalCard.propTypes = { - active_symbols: PropTypes.array, - addToast: PropTypes.func, className: PropTypes.string, contract_info: PropTypes.object, contract_update: PropTypes.object, currency: PropTypes.string, - current_focus: PropTypes.string, current_tick: PropTypes.number, duration: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), duration_unit: PropTypes.string, exit_spot: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - getContractById: PropTypes.func, id: PropTypes.number, indicative: PropTypes.number, is_loading: PropTypes.bool, - is_mobile: PropTypes.bool, is_sell_requested: PropTypes.bool, is_unsupported: PropTypes.bool, is_valid_to_sell: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]), @@ -444,30 +446,13 @@ PositionsModalCard.propTypes = { onClickSell: PropTypes.func, onClickCancel: PropTypes.func, profit_loss: PropTypes.number, - removeToast: PropTypes.func, result: PropTypes.string, sell_price: PropTypes.number, sell_time: PropTypes.number, - server_time: PropTypes.object, - setCurrentFocus: PropTypes.func, - should_show_cancellation_warning: PropTypes.bool, status: PropTypes.string, - toggleCancellationWarning: PropTypes.func, togglePositions: PropTypes.func, toggleUnsupportedContractModal: PropTypes.func, type: PropTypes.string, }; -export default connect(({ common, ui, contract_trade, modules }) => ({ - active_symbols: modules.trade.active_symbols, - addToast: ui.addToast, - current_focus: ui.current_focus, - getContractById: contract_trade.getContractById, - is_mobile: ui.is_mobile, - removeToast: ui.removeToast, - server_time: common.server_time, - setCurrentFocus: ui.setCurrentFocus, - should_show_cancellation_warning: ui.should_show_cancellation_warning, - toggleCancellationWarning: ui.toggleCancellationWarning, - updateLimitOrder: contract_trade.updateLimitOrder, -}))(PositionsModalCard); +export default PositionsModalCard; diff --git a/packages/trader/src/App/Components/Elements/TogglePositions/toggle-positions-mobile.jsx b/packages/trader/src/App/Components/Elements/TogglePositions/toggle-positions-mobile.jsx index 8e462cf5fe35..ceaa48693b70 100644 --- a/packages/trader/src/App/Components/Elements/TogglePositions/toggle-positions-mobile.jsx +++ b/packages/trader/src/App/Components/Elements/TogglePositions/toggle-positions-mobile.jsx @@ -7,131 +7,126 @@ import { NavLink } from 'react-router-dom'; import EmptyPortfolioMessage from '../EmptyPortfolioMessage'; import PositionsModalCard from 'App/Components/Elements/PositionsDrawer/positions-modal-card.jsx'; import { filterByContractType } from 'App/Components/Elements/PositionsDrawer/helpers'; -import { connect } from 'Stores/connect'; import TogglePositions from './toggle-positions.jsx'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; -const TogglePositionsMobile = ({ - active_positions_count, - all_positions, - currency, - disableApp, - enableApp, - error, - is_empty, - is_positions_drawer_on, - onClickSell, - onClickRemove, - onClickCancel, - symbol, - togglePositionsDrawer, - toggleUnsupportedContractModal, - trade_contract_type, -}) => { - let filtered_positions = []; +const TogglePositionsMobile = observer( + ({ + active_positions_count, + all_positions, + currency, + disableApp, + enableApp, + error, + is_empty, + onClickSell, + onClickCancel, + toggleUnsupportedContractModal, + }) => { + const { portfolio, ui } = useStore(); + const { symbol, contract_type: trade_contract_type } = useTraderStore(); + const { removePositionById: onClickRemove } = portfolio; + const { togglePositionsDrawer, is_positions_drawer_on } = ui; + let filtered_positions = []; - const closeModal = () => { - filtered_positions.slice(0, 5).map(position => { - const { contract_info } = position; - if (contract_info?.is_sold) { - onClickRemove(contract_info.contract_id); - } - }); - togglePositionsDrawer(); - }; + const closeModal = () => { + filtered_positions.slice(0, 5).map(position => { + const { contract_info } = position; + if (contract_info?.is_sold) { + onClickRemove(contract_info.contract_id); + } + }); + togglePositionsDrawer(); + }; - filtered_positions = all_positions.filter( - p => - p.contract_info && - symbol === p.contract_info.underlying && - filterByContractType(p.contract_info, trade_contract_type) - ); + filtered_positions = all_positions.filter( + p => + p.contract_info && + symbol === p.contract_info.underlying && + filterByContractType(p.contract_info, trade_contract_type) + ); - // Show only 5 most recent open contracts - const body_content = ( - - - {filtered_positions.slice(0, 5).map(portfolio_position => ( - - + + {filtered_positions.slice(0, 5).map(portfolio_position => ( + - - ))} - - - ); - - return ( - - - - -
- - - {localize('Recent positions')} - -
- -
-
-
- {is_empty || error ? : body_content} -
-
- - - {localize('Go to Reports')} + + + ))} + + + ); + + return ( + + + + +
+ + + {localize('Recent positions')} - -
-
-
-
- ); -}; -// TODO: Needs to be connected to store due to issue with trade-header-extensions not updating all_positions prop -// Fixes issue with positions not updated in positions modal -export default connect(({ modules, ui, portfolio }) => ({ - symbol: modules.trade.symbol, - trade_contract_type: modules.trade.contract_type, - onClickRemove: portfolio.removePositionById, - togglePositionsDrawer: ui.togglePositionsDrawer, - is_positions_drawer_on: ui.is_positions_drawer_on, -}))(TogglePositionsMobile); +
+ +
+
+
+ {is_empty || error ? : body_content} +
+
+ + + {localize('Go to Reports')} + + +
+
+
+
+ ); + } +); + +export default TogglePositionsMobile; diff --git a/packages/trader/src/App/Components/Elements/market-countdown-timer.jsx b/packages/trader/src/App/Components/Elements/market-countdown-timer.jsx index 21fe0b757be3..833af29df84f 100644 --- a/packages/trader/src/App/Components/Elements/market-countdown-timer.jsx +++ b/packages/trader/src/App/Components/Elements/market-countdown-timer.jsx @@ -5,7 +5,8 @@ import moment from 'moment'; import { Text } from '@deriv/components'; import { useIsMounted, WS, convertTimeFormat, isMarketClosed } from '@deriv/shared'; import { Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; // check market in coming 7 days const days_to_check_before_exit = 7; @@ -43,7 +44,8 @@ const calculateTimeLeft = remaining_time_to_open => { : {}; }; -const MarketCountdownTimer = ({ active_symbols, is_main_page, setIsTimerLoading, onMarketOpen, symbol }) => { +const MarketCountdownTimer = observer(({ is_main_page, setIsTimerLoading, onMarketOpen, symbol }) => { + const { active_symbols } = useTraderStore(); const isMounted = useIsMounted(); const [when_market_opens, setWhenMarketOpens] = React.useState({}); const [time_left, setTimeLeft] = React.useState(calculateTimeLeft(when_market_opens?.remaining_time_to_open)); @@ -195,16 +197,13 @@ const MarketCountdownTimer = ({ active_symbols, is_main_page, setIsTimerLoading,
); -}; +}); MarketCountdownTimer.propTypes = { - active_symbols: PropTypes.array, is_main_page: PropTypes.bool, setIsTimerLoading: PropTypes.func, onMarketOpen: PropTypes.func, symbol: PropTypes.string.isRequired, }; -export default connect(({ modules }) => ({ - active_symbols: modules.trade.active_symbols, -}))(MarketCountdownTimer); +export default MarketCountdownTimer; diff --git a/packages/trader/src/App/Components/Form/TimePicker/time-picker.jsx b/packages/trader/src/App/Components/Form/TimePicker/time-picker.jsx index 3a9f38707fbc..5e38be3e7836 100644 --- a/packages/trader/src/App/Components/Form/TimePicker/time-picker.jsx +++ b/packages/trader/src/App/Components/Form/TimePicker/time-picker.jsx @@ -1,115 +1,115 @@ import classNames from 'classnames'; -import { observer } from 'mobx-react'; import PropTypes from 'prop-types'; import React from 'react'; import { CSSTransition } from 'react-transition-group'; import { Icon, InputField } from '@deriv/components'; -import { connect } from 'Stores/connect'; import Dialog from './dialog.jsx'; +import { observer, useStore } from '@deriv/stores'; const class_prefix = 'time-picker'; -const TimePicker = ({ - current_focus, - end_times, - is_nativepicker, - name, - onChange, - padding, - placeholder, - selected_time, - setCurrentFocus, - start_times, - validation_errors, -}) => { - const [is_open, setIsOpen] = React.useState(false); - const [wrapper_ref, setWrapperRef] = React.useState(null); +const TimePicker = observer( + ({ + end_times, + is_nativepicker, + name, + onChange, + padding, + placeholder, + selected_time, + start_times, + validation_errors, + }) => { + const { ui } = useStore(); + const { current_focus, setCurrentFocus } = ui; + const [is_open, setIsOpen] = React.useState(false); + const [wrapper_ref, setWrapperRef] = React.useState(null); - React.useEffect(() => { - document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }); + React.useEffect(() => { + document.addEventListener('mousedown', handleClickOutside); + return () => document.removeEventListener('mousedown', handleClickOutside); + }); - const toggleDropDown = () => { - setIsOpen(!is_open); - }; + const toggleDropDown = () => { + setIsOpen(!is_open); + }; - const handleChange = arg => { - // To handle nativepicker; - const value = typeof arg === 'object' ? arg.target.selected_time : arg; + const handleChange = arg => { + // To handle nativepicker; + const value = typeof arg === 'object' ? arg.target.selected_time : arg; - if (value !== selected_time) { - onChange({ target: { name, value } }); - } - }; + if (value !== selected_time) { + onChange({ target: { name, value } }); + } + }; - const saveRef = node => { - if (!node) return; - setWrapperRef(node); - }; + const saveRef = node => { + if (!node) return; + setWrapperRef(node); + }; - const handleClickOutside = event => { - if (!wrapper_ref?.contains(event.target) && is_open) { - setIsOpen(false); - } - }; + const handleClickOutside = event => { + if (!wrapper_ref?.contains(event.target) && is_open) { + setIsOpen(false); + } + }; - return ( -
- {is_nativepicker ? ( - - ) : ( - - + {is_nativepicker ? ( + - - - + - - - )} -
- ); -}; + + + + + + )} +
+ ); + } +); TimePicker.propTypes = { - current_focus: PropTypes.string, end_times: PropTypes.array, is_clearable: PropTypes.bool, is_nativepicker: PropTypes.bool, @@ -118,14 +118,8 @@ TimePicker.propTypes = { padding: PropTypes.string, placeholder: PropTypes.string, selected_time: PropTypes.string, - setCurrentFocus: PropTypes.func, start_times: PropTypes.array, validation_errors: PropTypes.array, }; -export default observer( - connect(({ ui }) => ({ - current_focus: ui.current_focus, - setCurrentFocus: ui.setCurrentFocus, - }))(TimePicker) -); +export default TimePicker; diff --git a/packages/trader/src/App/Containers/Modals/trade-modals.jsx b/packages/trader/src/App/Containers/Modals/trade-modals.jsx index 494e95485b37..fee15a59ea4b 100644 --- a/packages/trader/src/App/Containers/Modals/trade-modals.jsx +++ b/packages/trader/src/App/Containers/Modals/trade-modals.jsx @@ -1,25 +1,22 @@ import React from 'react'; import { getUrlSmartTrader, urlFor } from '@deriv/shared'; - -import { connect } from 'Stores/connect'; import UnsupportedContractModal from 'App/Components/Elements/Modals/UnsupportedContractModal'; import MarketUnavailableModal from 'App/Components/Elements/Modals/MarketUnavailableModal'; import ServicesErrorModal from 'App/Components/Elements/Modals/ServicesErrorModal'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const TradeModals = ({ - clearPurchaseInfo, - is_unsupported_contract_modal_visible, - is_market_unavailable_visible, - is_services_error_visible, - is_virtual, - is_logged_in, - toggleUnsupportedContractModal, - setHasOnlyForwardingContracts, - resetPreviousSymbol, - toggleServicesErrorModal, - resetPurchase, - services_error, -}) => { +const TradeModals = observer(() => { + const { ui, client, common } = useStore(); + const { resetPreviousSymbol, clearPurchaseInfo, requestProposal: resetPurchase } = useTraderStore(); + const { is_virtual, is_logged_in } = client; + const { services_error } = common; + const { + is_services_error_visible, + setHasOnlyForwardingContracts, + toggleServicesErrorModal, + toggleUnsupportedContractModal, + } = ui; const resetToPreviousMarket = () => { setHasOnlyForwardingContracts(false); resetPreviousSymbol(); @@ -54,17 +51,9 @@ const TradeModals = ({ return ( - + - + ); -}; +}); -export default connect(({ ui, modules, common, client }) => ({ - is_market_unavailable_visible: ui.has_only_forward_starting_contracts, - is_services_error_visible: ui.is_services_error_visible, - is_unsupported_contract_modal_visible: ui.is_unsupported_contract_modal_visible, - is_virtual: client.is_virtual, - is_logged_in: client.is_logged_in, - proposal_info: modules.trade.proposal_info, - purchase_info: modules.trade.purchase_info, - resetPreviousSymbol: modules.trade.resetPreviousSymbol, - clearPurchaseInfo: modules.trade.clearPurchaseInfo, - resetPurchase: modules.trade.requestProposal, - services_error: common.services_error, - setHasOnlyForwardingContracts: ui.setHasOnlyForwardingContracts, - toggleServicesErrorModal: ui.toggleServicesErrorModal, - toggleUnsupportedContractModal: ui.toggleUnsupportedContractModal, -}))(TradeModals); +export default TradeModals; diff --git a/packages/trader/src/App/Containers/ProgressSliderStream/progress-slider-stream.jsx b/packages/trader/src/App/Containers/ProgressSliderStream/progress-slider-stream.jsx index ad46df3b3359..487cbc036604 100644 --- a/packages/trader/src/App/Containers/ProgressSliderStream/progress-slider-stream.jsx +++ b/packages/trader/src/App/Containers/ProgressSliderStream/progress-slider-stream.jsx @@ -2,10 +2,14 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ProgressSlider } from '@deriv/components'; import { getCurrentTick } from '@deriv/shared'; -import { connect } from 'Stores/connect'; import { getCardLabels } from 'Constants/contract'; +import { observer, useStore } from '@deriv/stores'; + +const ProgressSliderStream = observer(({ contract_info }) => { + const { common, portfolio } = useStore(); + const { server_time } = common; + const { is_loading } = portfolio; -const ProgressSliderStream = ({ contract_info, is_loading, server_time }) => { if (!contract_info) { return
; } @@ -22,15 +26,10 @@ const ProgressSliderStream = ({ contract_info, is_loading, server_time }) => { ticks_count={contract_info.tick_count} /> ); -}; +}); ProgressSliderStream.propTypes = { contract_info: PropTypes.object, - is_loading: PropTypes.bool, - server_time: PropTypes.object, }; -export default connect(({ common, portfolio }) => ({ - is_loading: portfolio.is_loading, - server_time: common.server_time, -}))(ProgressSliderStream); +export default ProgressSliderStream; diff --git a/packages/trader/src/App/Containers/Routes/routes.jsx b/packages/trader/src/App/Containers/Routes/routes.jsx index b6059af441a5..5a37e794281a 100644 --- a/packages/trader/src/App/Containers/Routes/routes.jsx +++ b/packages/trader/src/App/Containers/Routes/routes.jsx @@ -1,4 +1,3 @@ -import { PropTypes as MobxPropTypes } from 'mobx-react'; import PropTypes from 'prop-types'; import React from 'react'; import { withRouter, matchPath } from 'react-router'; @@ -7,7 +6,8 @@ import { UILoader } from '@deriv/components'; import { routes } from '@deriv/shared'; import BinaryRoutes from 'App/Components/Routes'; import getRoutesConfig from 'App/Constants/routes-config'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; const checkRoutingMatch = (route_list, path) => { return route_list.some(route => !!matchPath(path, { path: route, exact: true })); @@ -36,17 +36,14 @@ const Error = Loadable({ }, }); -const Routes = ({ - onUnmountPortfolio, - error, - has_error, - history, - is_logged_in, - is_logging_in, - passthrough, - setPromptHandler, - setTradeMountingPolicy, -}) => { +const Routes = observer(({ history, passthrough }) => { + const { client, common, ui, portfolio } = useStore(); + const { setSkipPrePostLifecycle: setTradeMountingPolicy } = useTraderStore(); + const { error, has_error } = common; + const { onUnmount: onUnmountPortfolio } = portfolio; + const { is_logged_in, is_logging_in } = client; + const { setPromptHandler } = ui; + React.useEffect(() => { if (setPromptHandler) { setPromptHandler(true, (route_to, action) => { @@ -101,30 +98,11 @@ const Routes = ({ if (has_error) return ; return ; -}; +}); Routes.propTypes = { - error: MobxPropTypes.objectOrObservableObject, - has_error: PropTypes.bool, history: PropTypes.object, - is_logged_in: PropTypes.bool, - is_logging_in: PropTypes.bool, - onUnmountPortfolio: PropTypes.func, passthrough: PropTypes.object, - setPromptHandler: PropTypes.func, - setTradeMountingPolicy: PropTypes.func, }; -// need to wrap withRouter around connect -// to prevent updates on from being blocked -export default withRouter( - connect(({ client, common, modules, ui, portfolio }) => ({ - onUnmountPortfolio: portfolio.onUnmount, - error: common.error, - has_error: common.has_error, - is_logged_in: client.is_logged_in, - is_logging_in: client.is_logging_in, - setPromptHandler: ui.setPromptHandler, - setTradeMountingPolicy: modules.trade.setSkipPrePostLifecycle, - }))(Routes) -); +export default withRouter(Routes); diff --git a/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx b/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx index e96833dfee71..255fb5e7205d 100644 --- a/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx +++ b/packages/trader/src/App/Containers/SettingsModal/settings-chart.jsx @@ -1,9 +1,8 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { Checkbox } from '@deriv/components'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import MediaItem, { MediaHeading, MediaIcon, MediaDescription } from 'App/Components/Elements/Media'; +import { observer, useStore } from '@deriv/stores'; // TODO: enable asset information // import OHLCDisabledLightIcon from 'Assets/SvgComponents/settings/OHLC-disabled.svg'; @@ -16,42 +15,41 @@ import IntervalDurationEnabledDarkIcon from 'Assets/SvgComponents/settings/dark/ import IntervalDurationDisabledLightIcon from 'Assets/SvgComponents/settings/interval-disabled.svg'; import IntervalDurationEnabledLightIcon from 'Assets/SvgComponents/settings/interval-enabled.svg'; -const ChartSettings = ({ is_countdown_visible, is_dark_mode, setCountdown }) => ( -
- - - - - - -
- { - setCountdown(e.target.checked); - }} - /> -
-
-
-
-); +const ChartSettings = observer(() => { + const { ui } = useStore(); + const { + is_chart_countdown_visible: is_countdown_visible, + is_dark_mode_on: is_dark_mode, + setChartCountdown: setCountdown, + } = ui; -ChartSettings.propTypes = { - is_countdown_visible: PropTypes.bool, - is_dark_mode: PropTypes.bool, - setCountdown: PropTypes.func, -}; + return ( +
+ + + + + + +
+ { + setCountdown(e.target.checked); + }} + /> +
+
+
+
+ ); +}); -export default connect(({ ui }) => ({ - is_countdown_visible: ui.is_chart_countdown_visible, - is_dark_mode: ui.is_dark_mode_on, - setCountdown: ui.setChartCountdown, -}))(ChartSettings); +export default ChartSettings; diff --git a/packages/trader/src/App/Containers/populate-header.jsx b/packages/trader/src/App/Containers/populate-header.jsx index 365522a17575..1690f023037a 100644 --- a/packages/trader/src/App/Containers/populate-header.jsx +++ b/packages/trader/src/App/Containers/populate-header.jsx @@ -1,23 +1,23 @@ import React from 'react'; import TogglePositionsMobile from 'App/Components/Elements/TogglePositions/toggle-positions-mobile.jsx'; import { filterByContractType } from 'App/Components/Elements/PositionsDrawer/helpers'; -import { connect } from 'Stores/connect'; -import { PropTypes as MobxPropTypes } from 'mobx-react'; -import PropTypes from 'prop-types'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; + +const PopulateHeader = observer(() => { + const { portfolio, ui, client } = useStore(); + const { symbol, contract_type: trade_contract_type } = useTraderStore(); + const { currency: positions_currency } = client; + const { disableApp, enableApp } = ui; + const { + active_positions_count, + all_positions: positions, + error: positions_error, + onClickSell: onPositionsSell, + removePositionById: onPositionsRemove, + onClickCancel: onPositionsCancel, + } = portfolio; -const PopulateHeader = ({ - active_positions_count, - positions, - positions_currency, - disableApp, - enableApp, - positions_error, - onPositionsSell, - onPositionsRemove, - onPositionsCancel, - symbol, - trade_contract_type, -}) => { const symbol_positions = positions.filter( p => p.contract_info && @@ -39,32 +39,6 @@ const PopulateHeader = ({ onClickCancel={onPositionsCancel} /> ); -}; - -PopulateHeader.propTypes = { - active_positions_count: PropTypes.number, - positions: MobxPropTypes.arrayOrObservableArray, - positions_currency: PropTypes.string, - disableApp: PropTypes.func, - enableApp: PropTypes.func, - positions_error: PropTypes.string, - onPositionsSell: PropTypes.func, - onPositionsRemove: PropTypes.func, - onPositionsCancel: PropTypes.func, - symbol: PropTypes.string, - trade_contract_type: PropTypes.string, -}; +}); -export default connect(({ client, modules, ui, portfolio }) => ({ - active_positions_count: portfolio.active_positions_count, - positions: portfolio.all_positions, - positions_currency: client.currency, - disableApp: ui.disableApp, - enableApp: ui.enableApp, - positions_error: portfolio.error, - onPositionsSell: portfolio.onClickSell, - onPositionsRemove: portfolio.removePositionById, - onPositionsCancel: portfolio.onClickCancel, - symbol: modules.trade.symbol, - trade_contract_type: modules.trade.contract_type, -}))(PopulateHeader); +export default PopulateHeader; diff --git a/packages/trader/src/App/Containers/trade-footer-extensions.jsx b/packages/trader/src/App/Containers/trade-footer-extensions.jsx index cf3ace658170..702950f5ebca 100644 --- a/packages/trader/src/App/Containers/trade-footer-extensions.jsx +++ b/packages/trader/src/App/Containers/trade-footer-extensions.jsx @@ -3,16 +3,13 @@ import React from 'react'; import { withRouter } from 'react-router-dom'; import { routes } from '@deriv/shared'; import TogglePositions from 'App/Components/Elements/TogglePositions'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; -const TradeFooterExtensions = ({ - active_positions_count, - is_logged_in, - is_positions_drawer_on, - location, - populateFooterExtensions, - togglePositionsDrawer, -}) => { +const TradeFooterExtensions = observer(() => { + const { client, portfolio, ui } = useStore(); + const { is_logged_in } = client; + const { active_positions_count } = portfolio; + const { is_positions_drawer_on, populateFooterExtensions, togglePositionsDrawer } = ui; React.useEffect(() => populateFooter()); // eslint-disable-next-line react-hooks/exhaustive-deps React.useEffect(() => () => populateFooterExtensions([]), []); @@ -41,21 +38,10 @@ const TradeFooterExtensions = ({ }; return null; -}; +}); TradeFooterExtensions.propTypes = { - active_positions_count: PropTypes.number, - is_logged_in: PropTypes.bool, - is_positions_drawer_on: PropTypes.bool, location: PropTypes.object, - populateFooterExtensions: PropTypes.func, - togglePositionsDrawer: PropTypes.func, }; -export default connect(({ client, ui, portfolio }) => ({ - active_positions_count: portfolio.active_positions_count, - is_logged_in: client.is_logged_in, - is_positions_drawer_on: ui.is_positions_drawer_on, - populateFooterExtensions: ui.populateFooterExtensions, - togglePositionsDrawer: ui.togglePositionsDrawer, -}))(withRouter(TradeFooterExtensions)); +export default withRouter(TradeFooterExtensions); diff --git a/packages/trader/src/App/Containers/trade-header-extensions.jsx b/packages/trader/src/App/Containers/trade-header-extensions.tsx similarity index 55% rename from packages/trader/src/App/Containers/trade-header-extensions.jsx rename to packages/trader/src/App/Containers/trade-header-extensions.tsx index 023c69f1bd6f..f3aeb1f025f2 100644 --- a/packages/trader/src/App/Containers/trade-header-extensions.jsx +++ b/packages/trader/src/App/Containers/trade-header-extensions.tsx @@ -1,31 +1,34 @@ import React from 'react'; -import PropTypes from 'prop-types'; import { when } from 'mobx'; import { MobileWrapper } from '@deriv/components'; import { isMobile, routes, WS } from '@deriv/shared'; -import { connect, MobxContentProvider } from 'Stores/connect'; import PopulateHeader from './populate-header'; +import { observer, useStore } from '@deriv/stores'; +import TraderProviders from '../../trader-providers'; +import { TCoreStores } from '@deriv/stores/types'; + +type TradeHeaderExtensionsProps = { + store: TCoreStores; +}; + +const TradeHeaderExtensions = observer(({ store }: TradeHeaderExtensionsProps) => { + const { client, modules, ui, portfolio } = useStore(); + const { populateHeaderExtensions } = ui; + const { onMount: onMountPositions } = portfolio; + const { is_logged_in, is_populating_account_list } = client; + const { onMountCommon: onMountCashier, setAccountSwitchListener } = modules.cashier.general_store; -const TradeHeaderExtensions = ({ - populateHeaderExtensions, - store, - is_logged_in, - is_populating_account_list, - onMountPositions, - onMountCashier, - setAccountSwitchListener, -}) => { const show_positions_toggle = location.pathname !== routes.mt5; const show_component = is_logged_in && show_positions_toggle; const populateHeaderfunction = React.useCallback(() => { - const header_items = show_component && ( + const header_items = show_component ? ( - + - + - ); + ) : null; populateHeaderExtensions(header_items); }, [populateHeaderExtensions, store, show_positions_toggle, is_populating_account_list]); @@ -45,7 +48,9 @@ const TradeHeaderExtensions = ({ populateHeaderfunction(); }; - waitForLogin(); + waitForLogin().catch(() => { + // Do nothing: This is to remove the bug reported by SonarCloud about not having a catch statement here. + }); return () => populateHeaderExtensions(null); }, [ @@ -63,23 +68,6 @@ const TradeHeaderExtensions = ({ }); return null; -}; - -TradeHeaderExtensions.propTypes = { - populateHeaderExtensions: PropTypes.func, - store: PropTypes.object, - is_logged_in: PropTypes.bool, - is_populating_account_list: PropTypes.bool, - onMountPositions: PropTypes.func, - onMountCashier: PropTypes.func, - setAccountSwitchListener: PropTypes.func, -}; +}); -export default connect(({ client, modules, ui, portfolio }) => ({ - populateHeaderExtensions: ui.populateHeaderExtensions, - is_logged_in: client.is_logged_in, - is_populating_account_list: client.is_populating_account_list, - onMountPositions: portfolio.onMount, - onMountCashier: modules.cashier.general_store.onMountCommon, - setAccountSwitchListener: modules.cashier.general_store.setAccountSwitchListener, -}))(TradeHeaderExtensions); +export default TradeHeaderExtensions; diff --git a/packages/trader/src/App/Containers/trade-settings-extensions.jsx b/packages/trader/src/App/Containers/trade-settings-extensions.tsx similarity index 68% rename from packages/trader/src/App/Containers/trade-settings-extensions.jsx rename to packages/trader/src/App/Containers/trade-settings-extensions.tsx index 01572245934f..29fea57d1a68 100644 --- a/packages/trader/src/App/Containers/trade-settings-extensions.jsx +++ b/packages/trader/src/App/Containers/trade-settings-extensions.tsx @@ -1,9 +1,14 @@ -import PropTypes from 'prop-types'; import React from 'react'; import Loadable from 'react-loadable'; import { UILoader } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { connect, MobxContentProvider } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import TraderProviders from '../../trader-providers'; +import type { TCoreStores } from '@deriv/stores/types'; + +type TTradeSettingsExtensionsProps = { + store: TCoreStores; +}; const ChartSettingContainer = Loadable({ loader: () => @@ -19,15 +24,17 @@ const ChartSettingContainer = Loadable({ // loading: UILoader, // }); -const renderItemValue = (props, store) => ( - +const renderItemValue = (props: T, store: TCoreStores) => ( + - + ); -const TradeSettingsExtensions = ({ populateSettingsExtensions, store }) => { +const TradeSettingsExtensions = observer(({ store }: TTradeSettingsExtensionsProps) => { + const { ui } = useStore(); + const { populateSettingsExtensions } = ui; const populateSettings = () => { - const menu_items = [ + const menu_items: Parameters[0] = [ { icon: 'IcChart', label: localize('Charts'), @@ -49,13 +56,6 @@ const TradeSettingsExtensions = ({ populateSettingsExtensions, store }) => { React.useEffect(() => populateSettings()); return null; -}; - -TradeSettingsExtensions.propTypes = { - populateSettingsExtensions: PropTypes.func, - store: PropTypes.object, -}; +}); -export default connect(({ ui }) => ({ - populateSettingsExtensions: ui.populateSettingsExtensions, -}))(TradeSettingsExtensions); +export default TradeSettingsExtensions; diff --git a/packages/trader/src/App/app.tsx b/packages/trader/src/App/app.tsx index 5b091e7c2283..e1c53b91a711 100644 --- a/packages/trader/src/App/app.tsx +++ b/packages/trader/src/App/app.tsx @@ -1,20 +1,19 @@ -import PropTypes from 'prop-types'; import React from 'react'; import Loadable from 'react-loadable'; -import { StoreProvider } from '@deriv/stores'; import Routes from 'App/Containers/Routes/routes.jsx'; -import TradeHeaderExtensions from 'App/Containers/trade-header-extensions.jsx'; +import TradeHeaderExtensions from 'App/Containers/trade-header-extensions'; import TradeFooterExtensions from 'App/Containers/trade-footer-extensions.jsx'; -import TradeSettingsExtensions from 'App/Containers/trade-settings-extensions.jsx'; +import TradeSettingsExtensions from 'App/Containers/trade-settings-extensions'; import { NetworkStatusToastErrorPopup } from 'Modules/Trading/Containers/toast-popup.jsx'; -import { MobxContentProvider } from 'Stores/connect'; -import initStore from './init-store.js'; // eslint-disable-line import/extensions +import initStore from './init-store'; import 'Sass/app.scss'; +import type { TCoreStores } from '@deriv/stores/types'; +import TraderProviders from '../trader-providers'; type Apptypes = { passthrough: { - root_store: any; - WS: any; + root_store: TCoreStores; + WS: unknown; }; }; @@ -24,30 +23,21 @@ const TradeModals = Loadable({ }); const App = ({ passthrough }: Apptypes) => { - const [root_store] = React.useState(initStore(passthrough.root_store, passthrough.WS)); + const root_store = initStore(passthrough.root_store, passthrough.WS); React.useEffect(() => { return () => root_store.ui.setPromptHandler(false); }, [root_store]); return ( - - - - - - - - - - + + + + + + + + ); }; -App.propTypes = { - passthrough: PropTypes.shape({ - root_store: PropTypes.object, - WS: PropTypes.object, - }), -}; - export default App; diff --git a/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/__tests__/accumulators-stats.spec.js b/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/__tests__/accumulators-stats.spec.js index 81fa7005b911..2788d8435905 100644 --- a/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/__tests__/accumulators-stats.spec.js +++ b/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/__tests__/accumulators-stats.spec.js @@ -2,19 +2,21 @@ import React from 'react'; import { fireEvent, render, screen, within } from '@testing-library/react'; import { isDesktop, isMobile } from '@deriv/shared'; import AccumulatorsStats, { ROW_SIZES } from '../accumulators-stats'; +import { TraderProviders } from '../../../../../trader-providers'; +import { mockStore } from '@deriv/stores'; const mock_connect_props = { - ticks_history_stats: { - ticks_stayed_in: [1, 65, 1234, 675, 234, 10, 658, 134, 5, 2394, 100, 6, 90, 9, 344, 81, 695, 14, 345, 2222], - last_tick_epoch: 1005, + modules: { + trade: { + ticks_history_stats: { + ticks_stayed_in: [ + 1, 65, 1234, 675, 234, 10, 658, 134, 5, 2394, 100, 6, 90, 9, 344, 81, 695, 14, 345, 2222, + ], + last_tick_epoch: 1005, + }, + }, }, }; - -jest.mock('Stores/connect.js', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => props => Component({ ...props, ...mock_connect_props }), -})); jest.mock('@deriv/shared', () => ({ ...jest.requireActual('@deriv/shared'), isDesktop: jest.fn(), @@ -32,32 +34,55 @@ describe('AccumulatorsStats', () => { }); it('should render as expandable', () => { - const { container } = render(); + const { container } = render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(container.querySelector('.accordion-toggle-arrow')).toBeInTheDocument(); }); it('should render as non-expandable', () => { - const { container } = render(); + const { container } = render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(container.querySelector('.accordion-toggle-arrow')).not.toBeInTheDocument(); }); it('should show manual after info icon is clicked', () => { const { container } = render(, { container: document.body.appendChild(modal_root_el), + wrapper: ({ children }) => ( + {children} + ), }); fireEvent.click(container.querySelector('.info')); expect(screen.getByTestId('dt_accumulators_stats_manual_video')).toBeInTheDocument(); }); it('should render partial history values (tick counters) when initially collapsed in desktop', () => { - render(); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getAllByTestId('dt_accu_stats_history_counter').length).toEqual(ROW_SIZES.DESKTOP_COLLAPSED); }); it('should render partial history values (tick counters) when initially collapsed in mobile', () => { isMobile.mockReturnValue(true); isDesktop.mockReturnValue(false); - render(); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getAllByTestId('dt_accu_stats_history_counter').length).toEqual(ROW_SIZES.MOBILE_COLLAPSED); }); it('should expand in desktop when accordion_toggle_arrow is clicked', () => { - const { container } = render(); + const { container } = render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getAllByTestId('dt_accu_stats_history_counter').length).toEqual(ROW_SIZES.DESKTOP_COLLAPSED); fireEvent.click(container.querySelector('.accordion-toggle-arrow')); @@ -70,6 +95,9 @@ describe('AccumulatorsStats', () => { isDesktop.mockReturnValue(false); const { container } = render(, { container: document.body.appendChild(modal_root_el), + wrapper: ({ children }) => ( + {children} + ), }); expect(screen.getAllByTestId('dt_accu_stats_history_counter').length).toEqual(ROW_SIZES.MOBILE_COLLAPSED); diff --git a/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/accumulators-stats.jsx b/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/accumulators-stats.jsx index 2bbb63bad707..656994ad23bc 100644 --- a/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/accumulators-stats.jsx +++ b/packages/trader/src/Modules/Contract/Components/AccumulatorsStats/accumulators-stats.jsx @@ -4,11 +4,12 @@ import PropTypes from 'prop-types'; import { DesktopWrapper, Icon, MobileDialog, MobileWrapper, Text } from '@deriv/components'; import { isDesktop, isMobile } from '@deriv/shared'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import ExpandedTicksHistory from './expanded-ticks-history'; import TicksHistoryCounter from './ticks-history-counter'; import { AccumulatorsStatsManualModal } from './accumulators-stats-manual-modal'; import 'Sass/app/modules/contract/accumulators-stats.scss'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; export const ROW_SIZES = { DESKTOP_COLLAPSED: 10, @@ -17,7 +18,11 @@ export const ROW_SIZES = { MOBILE_EXPANDED: 5, }; -const AccumulatorsStats = ({ is_dark_theme, is_expandable = true, ticks_history_stats = {} }) => { +const AccumulatorsStats = observer(({ is_expandable = true }) => { + const { ui } = useStore(); + const { ticks_history_stats = {} } = useTraderStore(); + const { is_dark_mode_on: is_dark_theme } = ui; + const [is_collapsed, setIsCollapsed] = React.useState(true); const [is_manual_open, setIsManualOpen] = React.useState(false); const widget_title = localize('Stats'); @@ -86,15 +91,10 @@ const AccumulatorsStats = ({ is_dark_theme, is_expandable = true, ticks_history_ )}
); -}; +}); AccumulatorsStats.propTypes = { - is_dark_theme: PropTypes.bool, is_expandable: PropTypes.bool, - ticks_history_stats: PropTypes.object, }; -export default connect(({ modules, ui }) => ({ - is_dark_theme: ui.is_dark_mode_on, - ticks_history_stats: modules.trade.ticks_history_stats, -}))(AccumulatorsStats); +export default AccumulatorsStats; diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx index 9fb697e8cc3c..a264cc08533b 100644 --- a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx +++ b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx @@ -1,39 +1,42 @@ import React from 'react'; import Digits from 'Modules/Contract/Components/Digits'; import InfoBox from 'Modules/Contract/Components/InfoBox'; -import { connect } from 'Stores/connect'; import BottomWidgets from '../../SmartChart/Components/bottom-widgets.jsx'; import TopWidgets from '../../SmartChart/Components/top-widgets.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -export const DigitsWidget = connect(({ contract_replay }) => ({ - contract_info: contract_replay.contract_store.contract_info, - digits_info: contract_replay.contract_store.digits_info, - display_status: contract_replay.contract_store.display_status, - is_digit_contract: contract_replay.contract_store.is_digit_contract, - is_ended: contract_replay.contract_store.is_ended, -}))(({ is_digit_contract, is_ended, contract_info, digits_info, display_status }) => ( - -)); +export const DigitsWidget = observer(() => { + const { contract_replay } = useStore(); + const { contract_store } = contract_replay; + const { contract_info, digits_info, display_status, is_digit_contract, is_ended } = contract_store; -export const InfoBoxWidget = connect(({ contract_replay, modules }) => ({ - contract_info: contract_replay.contract_store.contract_info, - error_message: contract_replay.error_message, - removeError: contract_replay.removeErrorMessage, - is_vanilla: modules.trade.is_vanilla, -}))(({ contract_info, error_message, removeError, is_vanilla }) => ( - -)); + return ( + + ); +}); + +export const InfoBoxWidget = observer(() => { + const { contract_replay } = useStore(); + const { is_vanilla } = useTraderStore(); + const { contract_store, removeErrorMessage: removeError, error_message } = contract_replay; + const { contract_info } = contract_store; + + return ( + + ); +}); // Chart widgets passed into SmartCharts export const ChartTopWidgets = () => } is_title_enabled={false} />; diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx index 2144de2614bc..daac8ae993e1 100644 --- a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx +++ b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx @@ -28,32 +28,31 @@ import ChartLoader from 'App/Components/Elements/chart-loader.jsx'; import ContractDrawer from 'App/Components/Elements/ContractDrawer'; import UnsupportedContractModal from 'App/Components/Elements/Modals/UnsupportedContractModal'; import { SmartChart } from 'Modules/SmartChart'; -import { connect } from 'Stores/connect'; import { ChartBottomWidgets, ChartTopWidgets, DigitsWidget, InfoBoxWidget } from './contract-replay-widget.jsx'; import ChartMarker from 'Modules/SmartChart/Components/Markers/marker.jsx'; import allMarkers from 'Modules/SmartChart/Components/all-markers.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const ContractReplay = observer(({ contract_id }) => { + const { common, contract_replay, ui } = useStore(); + const { contract_store } = contract_replay; + const { + is_market_closed, + is_sell_requested, + is_valid_to_cancel, + onClickCancel, + onClickSell, + onMount, + onUnmount, + indicative_status, + is_chart_loading, + is_forward_starting, + } = contract_replay; + const { contract_info, contract_update, contract_update_history, is_digit_contract } = contract_store; + const { routeBackInApp } = common; + const { is_dark_mode_on: is_dark_theme, notification_messages_ui: NotificationMessages, toggleHistoryTab } = ui; -const ContractReplay = ({ - contract_id, - contract_info, - contract_update, - contract_update_history, - is_chart_loading, - is_dark_theme, - is_digit_contract, - is_forward_starting, - is_market_closed, - is_sell_requested, - is_valid_to_cancel, - onClickCancel, - NotificationMessages, - onClickSell, - indicative_status, - toggleHistoryTab, - routeBackInApp, - onMount, - onUnmount, -}) => { const [is_visible, setIsVisible] = React.useState(false); const history = useHistory(); @@ -176,119 +175,112 @@ const ContractReplay = ({ ); -}; +}); ContractReplay.propTypes = { contract_id: PropTypes.number, - contract_info: PropTypes.object, - contract_update: PropTypes.object, - contract_update_history: PropTypes.array, - indicative_status: PropTypes.string, - is_chart_loading: PropTypes.bool, - is_dark_theme: PropTypes.bool, - is_digit_contract: PropTypes.bool, - is_forward_starting: PropTypes.bool, - is_market_closed: PropTypes.bool, - is_sell_requested: PropTypes.bool, - is_valid_to_cancel: PropTypes.bool, - NotificationMessages: PropTypes.func, - onClickCancel: PropTypes.func, - onClickSell: PropTypes.func, - onMount: PropTypes.func, - onUnmount: PropTypes.func, - routeBackInApp: PropTypes.func, - routes: PropTypes.arrayOf(PropTypes.object), - toggleHistoryTab: PropTypes.func, }; -export default connect(({ common, contract_replay, ui }) => { - const local_contract_replay = contract_replay; - const contract_store = local_contract_replay.contract_store; - return { - routeBackInApp: common.routeBackInApp, - contract_info: contract_store.contract_info, - contract_update: contract_store.contract_update, - contract_update_history: contract_store.contract_update_history, - is_digit_contract: contract_store.is_digit_contract, - is_market_closed: local_contract_replay.is_market_closed, - is_sell_requested: local_contract_replay.is_sell_requested, - is_valid_to_cancel: local_contract_replay.is_valid_to_cancel, - onClickCancel: local_contract_replay.onClickCancel, - onClickSell: local_contract_replay.onClickSell, - onMount: local_contract_replay.onMount, - onUnmount: local_contract_replay.onUnmount, - indicative_status: local_contract_replay.indicative_status, - is_chart_loading: local_contract_replay.is_chart_loading, - is_forward_starting: local_contract_replay.is_forward_starting, - is_dark_theme: ui.is_dark_mode_on, - NotificationMessages: ui.notification_messages_ui, - toggleHistoryTab: ui.toggleHistoryTab, - }; -})(ContractReplay); +export default ContractReplay; // CHART ----------------------------------------- -const Chart = props => { - const AccumulatorsShadedBarriers = allMarkers[props.accumulators_barriers_marker?.type]; +const ReplayChart = observer(({ is_accumulator_contract }) => { + const trade = useTraderStore(); + const { contract_replay, common, ui } = useStore(); + const { contract_store, chart_state, chartStateChange, margin } = contract_replay; + const { + contract_config, + marker: accumulators_barriers_marker, + is_digit_contract, + barriers_array, + markers_array, + contract_info, + } = contract_store; + const { underlying: symbol, audit_details } = contract_info; + const allow_scroll_to_epoch = chart_state === 'READY' || chart_state === 'SCROLL_TO_LEFT'; + const { app_routing_history, current_language, is_socket_opened } = common; + const { is_dark_mode_on: is_dark_theme, is_chart_layout_default, is_chart_countdown_visible } = ui; + const { end_epoch, chart_type, start_epoch, granularity } = contract_config; + /** + * TODO: remove forcing light theme once DBot supports dark theme + * DBot does not support for dark theme since till now, + * as a result, if any user come to report detail pages + * from DBot, we should force it to have light theme + */ + const from_platform = getPlatformRedirect(app_routing_history); + const should_force_light_theme = from_platform.name === 'DBot'; + const settings = { + language: current_language.toLowerCase(), + theme: is_dark_theme && !should_force_light_theme ? 'dark' : 'light', + position: is_chart_layout_default ? 'bottom' : 'left', + countdown: is_chart_countdown_visible, + assetInformation: false, // ui.is_chart_asset_info_visible, + isHighestLowestMarkerEnabled: false, // TODO: Pending UI + }; + const scroll_to_epoch = allow_scroll_to_epoch ? contract_config.scroll_to_epoch : undefined; + const all_ticks = audit_details ? audit_details.all_ticks : []; + const { wsForget, wsSubscribe, wsSendRequest, wsForgetStream } = trade; + + const AccumulatorsShadedBarriers = allMarkers[accumulators_barriers_marker?.type]; const isBottomWidgetVisible = () => { - return isDesktop() && props.is_digit_contract; + return isDesktop() && is_digit_contract; }; const getChartYAxisMargin = () => { - const margin = { + const chart_margin = { top: isMobile() ? 96 : 148, bottom: isBottomWidgetVisible() ? 128 : 112, }; if (isMobile()) { - margin.bottom = 48; + chart_margin.bottom = 48; } - return margin; + return chart_margin; }; - const prev_start_epoch = usePrevious(props.start_epoch); + const prev_start_epoch = usePrevious(start_epoch); return ( - {props.markers_array.map(marker => ( + {markers_array.map(marker => ( { is_bottom_widget_visible={isBottomWidgetVisible()} /> ))} - {props.is_accumulator_contract && props.markers_array && ( + {is_accumulator_contract && markers_array && ( )} ); -}; +}); -Chart.propTypes = { - accumulators_barriers_marker: PropTypes.object, - barriers_array: PropTypes.array, - BottomWidgets: PropTypes.node, - chartStateChange: PropTypes.func, - chart_type: PropTypes.string, - end_epoch: PropTypes.number, - granularity: PropTypes.number, - InfoBox: PropTypes.node, +ReplayChart.propTypes = { is_accumulator_contract: PropTypes.bool, - is_dark_theme: PropTypes.bool, - is_digit_contract: PropTypes.bool, - is_mobile: PropTypes.bool, - is_socket_opened: PropTypes.bool, - is_static_chart: PropTypes.bool, - margin: PropTypes.number, - markers_array: PropTypes.array, - replay_controls: PropTypes.object, - scroll_to_epoch: PropTypes.number, - settings: PropTypes.object, - start_epoch: PropTypes.number, - symbol: PropTypes.string, - contract_info: PropTypes.object, - all_ticks: PropTypes.array, - wsForget: PropTypes.func, - wsForgetStream: PropTypes.func, - wsSendRequest: PropTypes.func, - wsSubscribe: PropTypes.func, - shouldFetchTickHistory: PropTypes.bool, }; - -const ReplayChart = connect(({ modules, ui, common, contract_replay }) => { - const trade = modules.trade; - const contract_store = contract_replay.contract_store; - const contract_config = contract_store.contract_config; - const allow_scroll_to_epoch = - contract_replay.chart_state === 'READY' || contract_replay.chart_state === 'SCROLL_TO_LEFT'; - /** - * TODO: remove forcing light theme once DBot supports dark theme - * DBot does not support for dark theme since till now, - * as a result, if any user come to report detail pages - * from DBot, we should force it to have light theme - */ - const from_platform = getPlatformRedirect(common.app_routing_history); - const should_force_light_theme = from_platform.name === 'DBot'; - - const settings = { - language: common.current_language.toLowerCase(), - theme: ui.is_dark_mode_on && !should_force_light_theme ? 'dark' : 'light', - position: ui.is_chart_layout_default ? 'bottom' : 'left', - countdown: ui.is_chart_countdown_visible, - assetInformation: false, // ui.is_chart_asset_info_visible, - isHighestLowestMarkerEnabled: false, // TODO: Pending UI - }; - - return { - accumulators_barriers_marker: contract_store.marker, - end_epoch: contract_config.end_epoch, - chart_type: contract_config.chart_type, - start_epoch: contract_config.start_epoch, - granularity: contract_config.granularity, - scroll_to_epoch: allow_scroll_to_epoch ? contract_config.scroll_to_epoch : undefined, - settings, - is_mobile: ui.is_mobile, - is_socket_opened: common.is_socket_opened, - is_digit_contract: contract_store.is_digit_contract, - chartStateChange: contract_replay.chartStateChange, - margin: contract_replay.margin, - is_static_chart: contract_replay.is_static_chart, - barriers_array: contract_store.barriers_array, - markers_array: contract_store.markers_array, - symbol: contract_store.contract_info.underlying, - contract_info: contract_store.contract_info, - all_ticks: contract_store.contract_info.audit_details - ? contract_store.contract_info.audit_details.all_ticks - : [], - wsForget: trade.wsForget, - wsSubscribe: trade.wsSubscribe, - wsSendRequest: trade.wsSendRequest, - wsForgetStream: trade.wsForgetStream, - }; -})(Chart); diff --git a/packages/trader/src/Modules/Contract/Containers/contract.jsx b/packages/trader/src/Modules/Contract/Containers/contract.jsx index 45c096f8c110..420cfe0d21d2 100644 --- a/packages/trader/src/Modules/Contract/Containers/contract.jsx +++ b/packages/trader/src/Modules/Contract/Containers/contract.jsx @@ -5,12 +5,21 @@ import { CSSTransition } from 'react-transition-group'; import { routes } from '@deriv/shared'; import ErrorComponent from 'App/Components/Elements/Errors'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import ContractReplay from './contract-replay.jsx'; +import { observer, useStore } from '@deriv/stores'; const dialog_errors = ['GetProposalFailure', 'ContractValidationError']; -const Contract = ({ error_code, error_message, match, history, has_error, onMount, onUnmount, removeErrorMessage }) => { +const Contract = observer(({ match, history }) => { + const { contract_replay } = useStore(); + const { + removeErrorMessage, + error_message, + error_code, + has_error, + removeAccountSwitcherListener: onUnmount, + setAccountSwitcherListener: onMount, + } = contract_replay; React.useEffect(() => { onMount(+match.params.contract_id, history); @@ -52,30 +61,11 @@ const Contract = ({ error_code, error_message, match, history, has_error, onMoun )} ); -}; +}); Contract.propTypes = { - error_message: PropTypes.string, - error_code: PropTypes.string, - has_error: PropTypes.bool, history: PropTypes.object, - is_mobile: PropTypes.bool, match: PropTypes.object, - onMount: PropTypes.func, - onUnmount: PropTypes.func, - removeErrorMessage: PropTypes.func, - symbol: PropTypes.string, }; -export default withRouter( - connect(({ ui, contract_replay }) => ({ - error_message: contract_replay.error_message, - error_code: contract_replay.error_code, - has_error: contract_replay.has_error, - onMount: contract_replay.setAccountSwitcherListener, - onUnmount: contract_replay.removeAccountSwitcherListener, - removeErrorMessage: contract_replay.removeErrorMessage, - symbol: contract_replay.contract_info.underlying, - is_mobile: ui.is_mobile, - }))(Contract) -); +export default withRouter(Contract); diff --git a/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx index 182d8d7384df..e62772683ec4 100644 --- a/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/control-widgets.jsx @@ -1,27 +1,28 @@ -import PropTypes from 'prop-types'; import React from 'react'; +import { observer, useStore } from '@deriv/stores'; import { DesktopWrapper } from '@deriv/components'; import { ChartMode, DrawTools, Share, StudyLegend, Views } from 'Modules/SmartChart'; -const ControlWidgets = ({ updateChartType, updateGranularity }) => ( - - - updateChartType(type)} - onGranularity={granularity => updateGranularity(granularity)} - /> - - - - - - -); +const ControlWidgets = observer(() => { + const { + contract_trade: { updateChartType, updateGranularity }, + } = useStore(); -ControlWidgets.propTypes = { - updateChartType: PropTypes.func, - updateGranularity: PropTypes.func, -}; + return ( + + + updateChartType(type)} + onGranularity={granularity => updateGranularity(granularity)} + /> + + + + + + + ); +}); export default ControlWidgets; diff --git a/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx index f98fa5684f6d..f16888081bbf 100644 --- a/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/toolbar-widgets.jsx @@ -3,15 +3,17 @@ import React from 'react'; import { isDesktop, isMobile } from '@deriv/shared'; import { ChartMode, DrawTools, Share, StudyLegend, Views, ToolbarWidget } from 'Modules/SmartChart'; -const ToolbarWidgets = ({ position, updateChartType, updateGranularity }) => ( - - - {isDesktop() && } - {isDesktop() && } - {isDesktop() && } - {isDesktop() && } - -); +const ToolbarWidgets = ({ position, updateChartType, updateGranularity }) => { + return ( + + + {isDesktop() && } + {isDesktop() && } + {isDesktop() && } + {isDesktop() && } + + ); +}; ToolbarWidgets.propTypes = { position: PropTypes.string, diff --git a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx index 9a7840505bab..1f6425d37b61 100644 --- a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx +++ b/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx @@ -4,11 +4,14 @@ import ReactDOM from 'react-dom'; import { DesktopWrapper, MobileWrapper, Text } from '@deriv/components'; import { localize } from '@deriv/translations'; import { isEnded, isAccumulatorContract, isDigitContract } from '@deriv/shared'; -import { connect } from 'Stores/connect'; import { ChartTitle } from 'Modules/SmartChart'; import BuyToastNotification from './buy-toast-notification'; +import { observer, useStore } from '@deriv/stores'; + +const RecentTradeInfo = observer(() => { + const { contract_trade } = useStore(); + const { granularity, markers_array } = contract_trade; -const TradeInfo = ({ markers_array, granularity }) => { const latest_tick_contract = markers_array[markers_array.length - 1]; if ( !latest_tick_contract || @@ -27,12 +30,7 @@ const TradeInfo = ({ markers_array, granularity }) => { {localize('Tick')} {current_tick}/{tick_count} ); -}; - -const RecentTradeInfo = connect(({ contract_trade }) => ({ - granularity: contract_trade.granularity, - markers_array: contract_trade.markers_array, -}))(TradeInfo); +}); const TopWidgets = ({ InfoBox, diff --git a/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/cancel-deal-mobile.jsx b/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/cancel-deal-mobile.jsx index aec1e6044a68..8dd50213d65e 100644 --- a/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/cancel-deal-mobile.jsx +++ b/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/cancel-deal-mobile.jsx @@ -1,124 +1,107 @@ import React from 'react'; import { Checkbox, RadioGroup, Dialog, Popover, Text } from '@deriv/components'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import { onToggleCancellation, onChangeCancellationDuration } from 'Stores/Modules/Trading/Helpers/multiplier'; import Fieldset from 'App/Components/Form/fieldset.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const DealCancellationWarning = ({ - disableApp, - enableApp, - is_visible, - onConfirm, - onCancel, - should_show_cancellation_warning, - toggleCancellationWarning, -}) => ( - - - - - toggleCancellationWarning()} - name={'should_show_cancellation_warning'} - label={localize("Don't show this again")} - /> - -); - -const DealCancellationWarningDialog = connect(({ ui }) => ({ - disableApp: ui.disableApp, - enableApp: ui.enableApp, - is_loading: ui.is_loading, - should_show_cancellation_warning: ui.should_show_cancellation_warning, - toggleCancellationWarning: ui.toggleCancellationWarning, -}))(DealCancellationWarning); - -const CancelDeal = ({ - has_cancellation, - has_take_profit, - has_stop_loss, - onChangeMultiple, - cancellation_duration, - cancellation_range_list, - should_show_cancellation_warning, -}) => { - const [is_deal_cancel_warning_visible, setDealCancelWarningVisibility] = React.useState(false); - - const canToggleDealCancel = () => { - const should_show_popover = (has_take_profit || has_stop_loss) && should_show_cancellation_warning; - if (should_show_popover) setDealCancelWarningVisibility(should_show_popover); - return !should_show_popover; - }; - +const DealCancellationWarningDialog = observer(({ is_visible, onConfirm, onCancel }) => { + const { ui } = useStore(); + const { disableApp, enableApp, should_show_cancellation_warning, toggleCancellationWarning } = ui; return ( - - setDealCancelWarningVisibility(false)} - onConfirm={() => { - setDealCancelWarningVisibility(false); - onToggleCancellation({ has_cancellation, onChangeMultiple }); - }} + + + + + toggleCancellationWarning()} + name={'should_show_cancellation_warning'} + label={localize("Don't show this again")} /> -
-
- { - if (canToggleDealCancel()) { - onToggleCancellation({ has_cancellation, onChangeMultiple }); - } - }} - name='has_cancellation' - label={localize('Deal cancellation')} - defaultChecked={has_cancellation} - /> - -
- {has_cancellation && ( - - onChangeCancellationDuration({ event, onChangeMultiple })} - > - {cancellation_range_list.map(({ text, value }) => ( - - ))} - - - )} -
-
+ ); -}; +}); + +const CancelDeal = observer( + ({ has_cancellation, has_take_profit, has_stop_loss, onChangeMultiple, cancellation_duration }) => { + const { ui } = useStore(); + const { should_show_cancellation_warning } = ui; + const { cancellation_range_list } = useTraderStore(); + const [is_deal_cancel_warning_visible, setDealCancelWarningVisibility] = React.useState(false); + + const canToggleDealCancel = () => { + const should_show_popover = (has_take_profit || has_stop_loss) && should_show_cancellation_warning; + if (should_show_popover) setDealCancelWarningVisibility(should_show_popover); + return !should_show_popover; + }; + + return ( + + setDealCancelWarningVisibility(false)} + onConfirm={() => { + setDealCancelWarningVisibility(false); + onToggleCancellation({ has_cancellation, onChangeMultiple }); + }} + /> +
+
+ { + if (canToggleDealCancel()) { + onToggleCancellation({ has_cancellation, onChangeMultiple }); + } + }} + name='has_cancellation' + label={localize('Deal cancellation')} + defaultChecked={has_cancellation} + /> + +
+ {has_cancellation && ( + + onChangeCancellationDuration({ event, onChangeMultiple })} + > + {cancellation_range_list.map(({ text, value }) => ( + + ))} + + + )} +
+
+ ); + } +); -export default connect(({ ui, modules }) => ({ - cancellation_range_list: modules.trade.cancellation_range_list, - should_show_cancellation_warning: ui.should_show_cancellation_warning, -}))(CancelDeal); +export default CancelDeal; diff --git a/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/risk-management-info.jsx b/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/risk-management-info.jsx index bc7b6b77cccd..08befd4c6659 100644 --- a/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/risk-management-info.jsx +++ b/packages/trader/src/Modules/Trading/Components/Elements/Multiplier/risk-management-info.jsx @@ -1,19 +1,21 @@ import React from 'react'; import { Money } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import RiskManagementDialog from 'Modules/Trading/Containers/Multiplier/risk-management-dialog.jsx'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const RiskManagementInfo = ({ - currency, - stop_loss, - take_profit, - has_take_profit, - has_stop_loss, - cancellation_duration, - cancellation_range_list, - has_cancellation, -}) => { +const RiskManagementInfo = observer(() => { + const { + currency, + stop_loss, + take_profit, + has_take_profit, + has_stop_loss, + cancellation_duration, + cancellation_range_list, + has_cancellation, + } = useTraderStore(); const [is_dialog_open, setDialogOpen] = React.useState(false); const has_risk_management = has_take_profit || has_stop_loss || has_cancellation; const toggleDialog = () => { @@ -63,15 +65,6 @@ const RiskManagementInfo = ({
); -}; +}); -export default connect(({ modules }) => ({ - currency: modules.trade.currency, - stop_loss: modules.trade.stop_loss, - has_stop_loss: modules.trade.has_stop_loss, - take_profit: modules.trade.take_profit, - has_take_profit: modules.trade.has_take_profit, - cancellation_duration: modules.trade.cancellation_duration, - cancellation_range_list: modules.trade.cancellation_range_list, - has_cancellation: modules.trade.has_cancellation, -}))(RiskManagementInfo); +export default RiskManagementInfo; diff --git a/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx b/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx index e681154c7e5c..0d336ef5589f 100644 --- a/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx +++ b/packages/trader/src/Modules/Trading/Components/Elements/mobile-widget.jsx @@ -1,27 +1,29 @@ import React from 'react'; import { Money } from '@deriv/components'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import { getExpiryType, getDurationMinMaxValues, getLocalizedBasis } from '@deriv/shared'; import { MultiplierAmountWidget } from 'Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx'; import TradeParamsModal from '../../Containers/trade-params-mobile.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const MobileWidget = observer(({ toggleDigitsWidget, is_collapsed }) => { + const { ui } = useStore(); + const { onChangeUiStore } = ui; + const trade_store = useTraderStore(); + const { + amount, + basis, + currency, + duration, + duration_min_max, + duration_unit, + form_components, + is_multiplier, + last_digit, + onChange, + } = trade_store; -const MobileWidget = ({ - amount, - basis, - currency, - duration, - duration_min_max, - duration_unit, - form_components, - is_collapsed, - is_multiplier, - last_digit, - onChange, - onChangeUiStore, - toggleDigitsWidget, - trade_store, -}) => { const [is_open, setIsOpen] = React.useState(false); React.useEffect(() => { @@ -104,19 +106,6 @@ const MobileWidget = ({ )}
); -}; +}); -export default connect(({ modules, ui }) => ({ - amount: modules.trade.amount, - basis: modules.trade.basis, - currency: modules.trade.currency, - duration: modules.trade.duration, - duration_min_max: modules.trade.duration_min_max, - duration_unit: modules.trade.duration_unit, - form_components: modules.trade.form_components, - is_multiplier: modules.trade.is_multiplier, - last_digit: modules.trade.last_digit, - onChange: modules.trade.onChange, - onChangeUiStore: ui.onChangeUiStore, - trade_store: modules.trade, -}))(MobileWidget); +export default MobileWidget; diff --git a/packages/trader/src/Modules/Trading/Components/Form/DatePicker/trading-date-picker.jsx b/packages/trader/src/Modules/Trading/Components/Form/DatePicker/trading-date-picker.jsx index 169b6cff8144..2d55815ca80b 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/DatePicker/trading-date-picker.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/DatePicker/trading-date-picker.jsx @@ -1,29 +1,28 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; -import { PropTypes as MobxPropTypes } from 'mobx-react'; import React from 'react'; import { DatePicker, Tooltip } from '@deriv/components'; import { isTimeValid, setTime, toMoment, useIsMounted, hasIntradayDurationUnit } from '@deriv/shared'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import { ContractType } from 'Stores/Modules/Trading/Helpers/contract-type'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const TradingDatePicker = observer(({ id, is_24_hours_contract, mode, name }) => { + const { common } = useStore(); + const { server_time } = common; + const { + duration: current_duration, + duration_min_max, + duration_units_list, + expiry_type, + onChange, + start_date, + start_time, + symbol, + validation_errors, + } = useTraderStore(); -const TradingDatePicker = ({ - duration: current_duration, - duration_min_max, - duration_units_list, - expiry_type, - id, - is_24_hours_contract, - mode, - name, - onChange, - server_time, - start_date, - start_time, - symbol, - validation_errors, -}) => { const isMounted = useIsMounted(); const [disabled_days, setDisabledDays] = React.useState([]); @@ -173,34 +172,13 @@ const TradingDatePicker = ({
); -}; +}); TradingDatePicker.propTypes = { - duration: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - duration_min_max: PropTypes.object, - duration_units_list: MobxPropTypes.arrayOrObservableArray, - expiry_type: PropTypes.string, id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), is_24_hours_contract: PropTypes.bool, mode: PropTypes.string, name: PropTypes.string, - onChange: PropTypes.func, - server_time: PropTypes.object, - start_date: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - start_time: PropTypes.string, - symbol: PropTypes.string, - validation_errors: PropTypes.object, }; -export default connect(({ modules, common }) => ({ - duration: modules.trade.duration, - duration_min_max: modules.trade.duration_min_max, - duration_units_list: modules.trade.duration_units_list, - expiry_type: modules.trade.expiry_type, - onChange: modules.trade.onChange, - server_time: common.server_time, - start_date: modules.trade.start_date, - start_time: modules.trade.start_time, - symbol: modules.trade.symbol, - validation_errors: modules.trade.validation_errors, -}))(TradingDatePicker); +export default TradingDatePicker; diff --git a/packages/trader/src/Modules/Trading/Components/Form/Purchase/cancel-deal-info.jsx b/packages/trader/src/Modules/Trading/Components/Form/Purchase/cancel-deal-info.jsx index b0338c0c65b7..cca795272fd7 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/Purchase/cancel-deal-info.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/Purchase/cancel-deal-info.jsx @@ -3,9 +3,11 @@ import React from 'react'; import { Money } from '@deriv/components'; import { isDesktop, isMobile, getDecimalPlaces } from '@deriv/shared'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const CancelDealInfo = ({ currency, has_cancellation, proposal_info }) => { +const CancelDealInfo = observer(({ proposal_info }) => { + const { currency, has_cancellation } = useTraderStore(); const { id, cancellation, has_error } = proposal_info; const error = has_error || !id; const [is_row_layout, setIsRowLayout] = React.useState(false); @@ -50,9 +52,6 @@ const CancelDealInfo = ({ currency, has_cancellation, proposal_info }) => { )}
); -}; +}); -export default connect(({ modules }) => ({ - has_cancellation: modules.trade.has_cancellation, - currency: modules.trade.currency, -}))(CancelDealInfo); +export default CancelDealInfo; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TimePicker/trading-time-picker.jsx b/packages/trader/src/Modules/Trading/Components/Form/TimePicker/trading-time-picker.jsx index 433f9ff6cf63..c51705aee27a 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TimePicker/trading-time-picker.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TimePicker/trading-time-picker.jsx @@ -1,19 +1,15 @@ -import PropTypes from 'prop-types'; import React from 'react'; -import { connect } from 'Stores/connect'; import { setTime, toMoment } from '@deriv/shared'; import TimePicker from 'App/Components/Form/TimePicker'; import { getSelectedTime, getBoundaries } from 'Stores/Modules/Trading/Helpers/end-time'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const TradingTimePicker = ({ - expiry_date, - expiry_time, - market_close_times, - market_open_times, - onChange, - server_time, - is_market_closed, -}) => { +const TradingTimePicker = observer(() => { + const { common } = useStore(); + const { server_time } = common; + const { expiry_date, expiry_time, market_open_times, market_close_times, onChange, is_market_closed } = + useTraderStore(); const moment_expiry_date = toMoment(expiry_date); const market_open_datetimes = market_open_times.map(open_time => setTime(moment_expiry_date.clone(), open_time)); const market_close_datetimes = market_close_times.map(close_time => @@ -48,26 +44,6 @@ const TradingTimePicker = ({ selected_time={selected_time} /> ); -}; +}); -TradingTimePicker.propTypes = { - expiry_date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - expiry_time: PropTypes.string, - is_market_closed: PropTypes.bool, - market_close_times: PropTypes.array, - market_open_times: PropTypes.array, - name: PropTypes.string, - onChange: PropTypes.func, - server_time: PropTypes.object, -}; - -export default connect(({ modules, common }) => ({ - duration_units_list: modules.trade.duration_units_list, - expiry_time: modules.trade.expiry_time, - expiry_date: modules.trade.expiry_date, - market_close_times: modules.trade.market_close_times, - market_open_times: modules.trade.market_open_times, - onChange: modules.trade.onChange, - server_time: common.server_time, - is_market_closed: modules.trade.is_market_closed, -}))(TradingTimePicker); +export default TradingTimePicker; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulator.spec.js b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulator.spec.js index 82a6a1b15443..dbdd1c541d23 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulator.spec.js +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulator.spec.js @@ -1,22 +1,26 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import Accumulator from '../accumulator'; +import { mockStore } from '@deriv/stores'; +import TraderProviders from '../../../../../../../trader-providers'; const mock_connect_props = { - accumulator_range_list: [0.01, 0.02, 0.03, 0.04, 0.05], - onChange: jest.fn(), - growth_rate: 0.01, + modules: { + trade: { + accumulator_range_list: [0.01, 0.02, 0.03, 0.04, 0.05], + onChange: jest.fn(), + growth_rate: 0.01, + }, + }, }; -jest.mock('Stores/connect.js', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => props => Component({ ...props, ...mock_connect_props }), -})); - describe('Accumulator', () => { it('should render with the initially selected 1% growth_rate', () => { - render(); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getByText('Accumulate')).toBeInTheDocument(); expect(screen.getByText('1%')).toBeInTheDocument(); expect(screen.getByText('2%')).toBeInTheDocument(); @@ -27,8 +31,12 @@ describe('Accumulator', () => { }); it('3% growth_rate should be selected when 0.03 is a currently selected and stored growth_rate value', () => { - mock_connect_props.growth_rate = 0.03; - render(); + mock_connect_props.modules.trade.growth_rate = 0.03; + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getByText('3%').getAttribute('class')).toContain('--selected'); expect(screen.getByText('1%').getAttribute('class')).not.toContain('--selected'); }); diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulators-info-display.spec.js b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulators-info-display.spec.js index ccdf0272f957..323ce2276a8f 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulators-info-display.spec.js +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/__tests__/accumulators-info-display.spec.js @@ -1,22 +1,26 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import AccumulatorsInfoDisplay from '../accumulators-info-display'; +import { mockStore } from '@deriv/stores'; +import TraderProviders from '../../../../../../../trader-providers'; const mock_connect_props = { - currency: 'USD', - maximum_payout: 10000, - maximum_ticks: 250, + modules: { + trade: { + currency: 'USD', + maximum_payout: 10000, + maximum_ticks: 250, + }, + }, }; -jest.mock('Stores/connect.js', () => ({ - __esModule: true, - default: 'mockedDefaultExport', - connect: () => Component => props => Component({ ...props, ...mock_connect_props }), -})); - describe('AccumulatorsInfoDisplay', () => { it('should render correct Maximum payout and Maximum ticks', () => { - render(); + render(, { + wrapper: ({ children }) => ( + {children} + ), + }); expect(screen.getByRole('group')).toHaveClass('trade-container__fieldset accu-info-display'); expect(screen.getByText(/maximum payout/i)).toBeInTheDocument(); expect(screen.getByText('10,000.00 USD')).toBeInTheDocument(); diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulator.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulator.jsx index 3c5de546fb66..41fa888784f7 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulator.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulator.jsx @@ -1,21 +1,16 @@ -import { PropTypes as MobxPropTypes } from 'mobx-react'; -import PropTypes from 'prop-types'; import React from 'react'; import { localize } from '@deriv/translations'; import NumberSelector from 'App/Components/Form/number-selector.jsx'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; import { getGrowthRatePercentage, getTickSizeBarrierPercentage, isEmptyObject } from '@deriv/shared'; import classNames from 'classnames'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const Accumulator = observer(() => { + const { accumulator_range_list, growth_rate, is_accumulator, onChange, tick_size_barrier, proposal_info } = + useTraderStore(); -const Accumulator = ({ - accumulator_range_list, - growth_rate, - is_accumulator, - onChange, - tick_size_barrier, - proposal_info, -}) => { // splitting accumulator_range_list into rows containing 5 values each: const arr_arr_numbers = accumulator_range_list.reduce((acc, _el, index) => { if (index % 5 === 0) { @@ -49,22 +44,6 @@ const Accumulator = ({ /> ); -}; - -Accumulator.propTypes = { - accumulator_range_list: MobxPropTypes.arrayOrObservableArray, - growth_rate: PropTypes.number, - is_accumulator: PropTypes.boolean, - onChange: PropTypes.func, - proposal_info: PropTypes.object, - tick_size_barrier: PropTypes.number, -}; +}); -export default connect(({ modules }) => ({ - is_accumulator: modules.trade.is_accumulator, - accumulator_range_list: modules.trade.accumulator_range_list, - growth_rate: modules.trade.growth_rate, - onChange: modules.trade.onChange, - proposal_info: modules.trade.proposal_info, - tick_size_barrier: modules.trade.tick_size_barrier, -}))(Accumulator); +export default Accumulator; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-amount-mobile.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-amount-mobile.jsx index ee4088749e82..9d4242c8e5c1 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-amount-mobile.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-amount-mobile.jsx @@ -3,19 +3,16 @@ import React from 'react'; import classNames from 'classnames'; import { AMOUNT_MAX_LENGTH, getDecimalPlaces } from '@deriv/shared'; import { MobileWrapper } from '@deriv/components'; -import { connect } from 'Stores/connect'; import { localize } from '@deriv/translations'; import LabeledQuantityInputMobile from '../../LabeledQuantityInputMobile'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const AccumulatorsAmountMobile = ({ - amount, - currency, - current_focus, - is_nativepicker, - is_single_currency, - onChange, - setCurrentFocus, -}) => { +const AccumulatorsAmountMobile = observer(({ is_nativepicker }) => { + const { ui, client } = useStore(); + const { current_focus, setCurrentFocus } = ui; + const { is_single_currency } = client; + const { amount, currency, onChange } = useTraderStore(); return ( <> @@ -46,23 +43,10 @@ const AccumulatorsAmountMobile = ({ ); -}; +}); AccumulatorsAmountMobile.propTypes = { - amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - currency: PropTypes.string, - current_focus: PropTypes.string, is_nativepicker: PropTypes.bool, - is_single_currency: PropTypes.bool, - onChange: PropTypes.func, - setCurrentFocus: PropTypes.func, }; -export default connect(({ modules, client, ui }) => ({ - amount: modules.trade.amount, - currency: modules.trade.currency, - current_focus: ui.current_focus, - is_single_currency: client.is_single_currency, - onChange: modules.trade.onChange, - setCurrentFocus: ui.setCurrentFocus, -}))(AccumulatorsAmountMobile); +export default AccumulatorsAmountMobile; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-info-display.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-info-display.jsx index 534b36179a72..341a9f0d9a97 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-info-display.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-info-display.jsx @@ -1,12 +1,14 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { localize } from '@deriv/translations'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; import { Money, Text } from '@deriv/components'; import classNames from 'classnames'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const AccumulatorsInfoDisplay = observer(() => { + const { currency, maximum_payout, maximum_ticks } = useTraderStore(); -const AccumulatorsInfoDisplay = ({ currency, maximum_payout, maximum_ticks }) => { const content = [ { label: localize('Maximum payout'), @@ -32,16 +34,6 @@ const AccumulatorsInfoDisplay = ({ currency, maximum_payout, maximum_ticks }) => ))} ); -}; - -AccumulatorsInfoDisplay.propTypes = { - currency: PropTypes.string, - maximum_payout: PropTypes.number, - maximum_ticks: PropTypes.number, -}; +}); -export default connect(({ modules }) => ({ - currency: modules.trade.currency, - maximum_payout: modules.trade.maximum_payout, - maximum_ticks: modules.trade.maximum_ticks, -}))(AccumulatorsInfoDisplay); +export default AccumulatorsInfoDisplay; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/advanced-duration.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/advanced-duration.jsx index a747b4b501d5..1fea7a11d937 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/advanced-duration.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/advanced-duration.jsx @@ -5,133 +5,134 @@ import React from 'react'; import { Dropdown, ButtonToggle, InputField } from '@deriv/components'; import { toMoment, hasIntradayDurationUnit } from '@deriv/shared'; import RangeSlider from 'App/Components/Form/RangeSlider'; -import { connect } from 'Stores/connect'; import TradingDatePicker from '../../DatePicker'; import TradingTimePicker from '../../TimePicker'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const AdvancedDuration = ({ - advanced_duration_unit, - advanced_expiry_type, - duration_units_list, - duration_t, - contract_expiry_type, - changeDurationUnit, - current_focus, - getDurationFromUnit, - expiry_date, - expiry_list, - expiry_type, - number_input_props, - onChange, - onChangeUiStore, - server_time, - setCurrentFocus, - shared_input_props, - start_date, - validation_errors, -}) => { - let is_24_hours_contract = false; +const AdvancedDuration = observer( + ({ + advanced_duration_unit, + advanced_expiry_type, + duration_units_list, + duration_t, + changeDurationUnit, + getDurationFromUnit, + expiry_date, + expiry_list, + expiry_type, + number_input_props, + onChange, + onChangeUiStore, + server_time, + shared_input_props, + start_date, + }) => { + const { ui } = useStore(); + const { current_focus, setCurrentFocus } = ui; + const { contract_expiry_type, validation_errors } = useTraderStore(); - if (expiry_type === 'endtime') { - const has_intraday_duration_unit = hasIntradayDurationUnit(duration_units_list); - is_24_hours_contract = - (!!start_date || toMoment(expiry_date || server_time).isSame(toMoment(server_time), 'day')) && - has_intraday_duration_unit; - } + let is_24_hours_contract = false; - const endtime_container_class = classNames('endtime-container', { - 'has-time': is_24_hours_contract, - }); + if (expiry_type === 'endtime') { + const has_intraday_duration_unit = hasIntradayDurationUnit(duration_units_list); + is_24_hours_contract = + (!!start_date || toMoment(expiry_date || server_time).isSame(toMoment(server_time), 'day')) && + has_intraday_duration_unit; + } - const changeExpiry = ({ target }) => { - const { name, value } = target; + const endtime_container_class = classNames('endtime-container', { + 'has-time': is_24_hours_contract, + }); - onChange({ target: { name: 'expiry_type', value } }); - onChangeUiStore({ name, value }); - }; + const changeExpiry = ({ target }) => { + const { name, value } = target; - return ( - <> - {expiry_list.length > 1 && ( - - )} - {expiry_type === 'duration' ? ( - <> -
- {duration_units_list.length >= 1 && ( - - )} - {advanced_duration_unit === 't' && contract_expiry_type === 'tick' && ( - - )} - {advanced_duration_unit === 'd' && ( + onChange({ target: { name: 'expiry_type', value } }); + onChangeUiStore({ name, value }); + }; + + return ( + <> + {expiry_list.length > 1 && ( + + )} + {expiry_type === 'duration' ? ( + <> +
+ {duration_units_list.length >= 1 && ( + + )} + {advanced_duration_unit === 't' && contract_expiry_type === 'tick' && ( + + )} + {advanced_duration_unit === 'd' && ( + + )} + {advanced_duration_unit !== 't' && advanced_duration_unit !== 'd' && ( + + )} +
+ + ) : ( + <> +
- )} - {advanced_duration_unit !== 't' && advanced_duration_unit !== 'd' && ( - - )} -
- - ) : ( - <> -
- - { - is_24_hours_contract && - // validation_errors={validation_errors.end_time} TODO: add validation_errors for end time - } -
- - )} - - ); -}; + { + is_24_hours_contract && + // validation_errors={validation_errors.end_time} TODO: add validation_errors for end time + } +
+ + )} + + ); + } +); AdvancedDuration.propTypes = { advanced_duration_unit: PropTypes.string, advanced_expiry_type: PropTypes.string, changeDurationUnit: PropTypes.func, - contract_expiry_type: PropTypes.string, - current_focus: PropTypes.string, duration_t: PropTypes.number, duration_units_list: MobxPropTypes.arrayOrObservableArray, expiry_date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), @@ -142,15 +143,8 @@ AdvancedDuration.propTypes = { onChange: PropTypes.func, onChangeUiStore: PropTypes.func, server_time: PropTypes.object, - setCurrentFocus: PropTypes.func, shared_input_props: PropTypes.object, start_date: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - validation_errors: PropTypes.object, }; -export default connect(({ modules, ui }) => ({ - contract_expiry_type: modules.trade.contract_expiry_type, - current_focus: ui.current_focus, - setCurrentFocus: ui.setCurrentFocus, - validation_errors: modules.trade.validation_errors, -}))(AdvancedDuration); +export default AdvancedDuration; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-mobile.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-mobile.jsx index 336b3a22ef8b..d6622b27a3ad 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-mobile.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-mobile.jsx @@ -3,7 +3,8 @@ import { Tabs, TickPicker, Numpad, RelativeDatepicker } from '@deriv/components' import { isEmptyObject, addComma, getDurationMinMaxValues } from '@deriv/shared'; import { Localize, localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; const submit_label = localize('OK'); @@ -25,328 +26,312 @@ const updateAmountChanges = (obj, stake_value, payout_value, basis, trade_basis, } }; -const Ticks = ({ - setDurationError, - basis_option, - toggleModal, - onChangeMultiple, - duration_min_max, - has_amount_error, - trade_duration, - trade_basis, - trade_amount, - trade_duration_unit, - payout_value, - stake_value, - selected_duration, - setSelectedDuration, -}) => { - React.useEffect(() => { - setDurationError(false); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); +const Ticks = observer( + ({ + setDurationError, + basis_option, + toggleModal, + has_amount_error, + payout_value, + stake_value, + selected_duration, + setSelectedDuration, + }) => { + const { + duration_min_max, + duration: trade_duration, + duration_unit: trade_duration_unit, + basis: trade_basis, + amount: trade_amount, + onChangeMultiple, + } = useTraderStore(); + React.useEffect(() => { + setDurationError(false); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); - const [min_tick, max_tick] = getDurationMinMaxValues(duration_min_max, 'tick', 't'); + const [min_tick, max_tick] = getDurationMinMaxValues(duration_min_max, 'tick', 't'); - const setTickDuration = value => { - const { value: duration } = value.target; - const on_change_obj = {}; + const setTickDuration = value => { + const { value: duration } = value.target; + const on_change_obj = {}; - // check for any amount changes from Amount trade params tab before submitting onChange object - if (!has_amount_error) - updateAmountChanges(on_change_obj, stake_value, payout_value, basis_option, trade_basis, trade_amount); + // check for any amount changes from Amount trade params tab before submitting onChange object + if (!has_amount_error) + updateAmountChanges(on_change_obj, stake_value, payout_value, basis_option, trade_basis, trade_amount); - if (trade_duration !== duration || trade_duration_unit !== 't') { - on_change_obj.duration_unit = 't'; - on_change_obj.duration = duration; - } + if (trade_duration !== duration || trade_duration_unit !== 't') { + on_change_obj.duration_unit = 't'; + on_change_obj.duration = duration; + } - if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); - toggleModal(); - }; + if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); + toggleModal(); + }; - const onTickChange = tick => setSelectedDuration('t', tick); - const tick_duration = trade_duration < min_tick && selected_duration < min_tick ? min_tick : selected_duration; - return ( -
- -
- ); -}; - -const TicksWrapper = connect(({ modules }) => ({ - duration_min_max: modules.trade.duration_min_max, - onChangeMultiple: modules.trade.onChangeMultiple, - trade_basis: modules.trade.basis, - trade_amount: modules.trade.amount, - trade_duration: modules.trade.duration, - trade_duration_unit: modules.trade.duration_unit, -}))(Ticks); - -const Numbers = ({ - addToast, - setDurationError, - basis_option, - toggleModal, - onChangeMultiple, - duration_min_max, - duration_unit_option, - has_amount_error, - contract_expiry = 'intraday', - payout_value, - stake_value, - trade_amount, - trade_basis, - trade_duration_unit, - trade_duration, - selected_duration, - setSelectedDuration, -}) => { - const { value: duration_unit } = duration_unit_option; - const [min, max] = getDurationMinMaxValues(duration_min_max, contract_expiry, duration_unit); - - const validateDuration = value => { - const localized_message = ( - + const onTickChange = tick => setSelectedDuration('t', tick); + const tick_duration = trade_duration < min_tick && selected_duration < min_tick ? min_tick : selected_duration; + return ( +
+ +
); - if (parseInt(value) < min || parseInt(selected_duration) > max) { - addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); - setDurationError(true); - return 'error'; - } else if (parseInt(value) > max) { - addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); - return 'error'; - } else if (value.toString().length < 1) { - addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); - setDurationError(true); - return false; - } + } +); - setDurationError(false); - return true; - }; +const Numbers = observer( + ({ + setDurationError, + basis_option, + toggleModal, + duration_unit_option, + has_amount_error, + contract_expiry = 'intraday', + payout_value, + stake_value, + selected_duration, + setSelectedDuration, + }) => { + const { ui } = useStore(); + const { addToast } = ui; + const { + duration_min_max, + duration: trade_duration, + duration_unit: trade_duration_unit, + basis: trade_basis, + amount: trade_amount, + onChangeMultiple, + } = useTraderStore(); + const { value: duration_unit } = duration_unit_option; + const [min, max] = getDurationMinMaxValues(duration_min_max, contract_expiry, duration_unit); - const setDuration = duration => { - const on_change_obj = {}; + const validateDuration = value => { + const localized_message = ( + + ); + if (parseInt(value) < min || parseInt(selected_duration) > max) { + addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); + setDurationError(true); + return 'error'; + } else if (parseInt(value) > max) { + addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); + return 'error'; + } else if (value.toString().length < 1) { + addToast({ key: 'duration_error', content: localized_message, type: 'error', timeout: 2000 }); + setDurationError(true); + return false; + } - // check for any amount changes from Amount trade params tab before submitting onChange object - if (!has_amount_error) - updateAmountChanges(on_change_obj, stake_value, payout_value, basis_option, trade_basis, trade_amount); + setDurationError(false); + return true; + }; - if (trade_duration !== duration || trade_duration_unit !== duration_unit) { - on_change_obj.duration_unit = duration_unit; - on_change_obj.duration = duration; - on_change_obj.expiry_type = 'duration'; - } + const setDuration = duration => { + const on_change_obj = {}; - if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); - toggleModal(); - }; + // check for any amount changes from Amount trade params tab before submitting onChange object + if (!has_amount_error) + updateAmountChanges(on_change_obj, stake_value, payout_value, basis_option, trade_basis, trade_amount); - const onNumberChange = num => { - setSelectedDuration(duration_unit, num); - validateDuration(num); - }; + if (trade_duration !== duration || trade_duration_unit !== duration_unit) { + on_change_obj.duration_unit = duration_unit; + on_change_obj.duration = duration; + on_change_obj.expiry_type = 'duration'; + } - return ( -
- { - return
{v}
; - }} - pip_size={0} - submit_label={submit_label} - min={min} - max={max} - reset_press_interval={350} - reset_value='' - onValidate={validateDuration} - onValueChange={onNumberChange} - /> -
- ); -}; + if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); + toggleModal(); + }; -const NumpadWrapper = connect(({ modules, ui }) => ({ - duration_min_max: modules.trade.duration_min_max, - trade_duration: modules.trade.duration, - trade_duration_unit: modules.trade.duration_unit, - trade_basis: modules.trade.basis, - trade_amount: modules.trade.amount, - onChangeMultiple: modules.trade.onChangeMultiple, - addToast: ui.addToast, -}))(Numbers); + const onNumberChange = num => { + setSelectedDuration(duration_unit, num); + validateDuration(num); + }; -const Duration = ({ - amount_tab_idx, - toggleModal, - duration_units_list, - duration_unit, - duration_tab_idx, - duration_min_max, - has_amount_error, - setDurationTabIdx, - setDurationError, - t_duration, - s_duration, - m_duration, - h_duration, - d_duration, - setSelectedDuration, - trade_basis, - stake_value, - payout_value, -}) => { - const duration_values = { + return ( +
+ { + return
{v}
; + }} + pip_size={0} + submit_label={submit_label} + min={min} + max={max} + reset_press_interval={350} + reset_value='' + onValidate={validateDuration} + onValueChange={onNumberChange} + /> +
+ ); + } +); + +const Duration = observer( + ({ + amount_tab_idx, + toggleModal, + duration_tab_idx, + has_amount_error, + setDurationTabIdx, + setDurationError, t_duration, s_duration, m_duration, h_duration, d_duration, - }; - const has_selected_tab_idx = typeof duration_tab_idx !== 'undefined'; - const active_index = has_selected_tab_idx - ? duration_tab_idx - : duration_units_list.findIndex(d => d.value === duration_unit); - const [min, max] = getDurationMinMaxValues(duration_min_max, 'daily', 'd'); - const handleRelativeChange = date => { - setSelectedDuration('d', date); - }; - const selected_basis_option = () => { - if (amount_tab_idx === 0) { - return 'stake'; - } else if (amount_tab_idx === 1) { - return 'payout'; - } - return trade_basis; - }; + setSelectedDuration, + stake_value, + payout_value, + }) => { + const { duration_units_list, duration_min_max, duration_unit, basis: trade_basis } = useTraderStore(); + const duration_values = { + t_duration, + s_duration, + m_duration, + h_duration, + d_duration, + }; + const has_selected_tab_idx = typeof duration_tab_idx !== 'undefined'; + const active_index = has_selected_tab_idx + ? duration_tab_idx + : duration_units_list.findIndex(d => d.value === duration_unit); + const [min, max] = getDurationMinMaxValues(duration_min_max, 'daily', 'd'); + const handleRelativeChange = date => { + setSelectedDuration('d', date); + }; + const selected_basis_option = () => { + if (amount_tab_idx === 0) { + return 'stake'; + } else if (amount_tab_idx === 1) { + return 'payout'; + } + return trade_basis; + }; - const onTabChange = index => { - setDurationTabIdx(index); - const { value: unit } = duration_units_list[index]; - setSelectedDuration(unit, duration_values[`${unit}_duration`]); - }; + const onTabChange = index => { + setDurationTabIdx(index); + const { value: unit } = duration_units_list[index]; + setSelectedDuration(unit, duration_values[`${unit}_duration`]); + }; - return ( -
- onTabChange(num)} single_tab_has_no_label top> - {duration_units_list.map(duration_unit_option => { - switch (duration_unit_option.value) { - case 't': - return ( -
- -
- ); - case 's': - return ( -
- -
- ); - case 'm': - return ( -
- -
- ); - case 'h': - return ( -
- -
- ); - case 'd': - return ( -
- - -
- ); - default: - return null; - } - })} -
-
- ); -}; + return ( +
+ onTabChange(num)} single_tab_has_no_label top> + {duration_units_list.map(duration_unit_option => { + switch (duration_unit_option.value) { + case 't': + return ( +
+ +
+ ); + case 's': + return ( +
+ +
+ ); + case 'm': + return ( +
+ +
+ ); + case 'h': + return ( +
+ +
+ ); + case 'd': + return ( +
+ + +
+ ); + default: + return null; + } + })} +
+
+ ); + } +); -export default connect(({ modules }) => ({ - duration_units_list: modules.trade.duration_units_list, - duration_min_max: modules.trade.duration_min_max, - duration_unit: modules.trade.duration_unit, - trade_basis: modules.trade.basis, -}))(Duration); +export default Duration; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-wrapper.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-wrapper.jsx index b5191bc16ab0..ad6230c1b972 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-wrapper.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/duration-wrapper.jsx @@ -1,27 +1,60 @@ import PropTypes from 'prop-types'; import React from 'react'; import { PropTypes as MobxPropTypes } from 'mobx-react'; -import { connect } from 'Stores/connect'; import { getDurationMinMaxValues } from '@deriv/shared'; import Duration from './duration.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const DurationWrapper = props => { +const DurationWrapper = observer(() => { + const { ui } = useStore(); const { - advanced_duration_unit, advanced_expiry_type, + advanced_duration_unit, + getDurationFromUnit, + is_advanced_duration, + onChangeUiStore, + simple_duration_unit, + duration_t, + } = ui; + const { + contract_expiry_type, + contract_type, duration, duration_unit, + duration_units_list, + duration_min_max, expiry_type, + expiry_date, + expiry_time, + start_date, + market_open_times, + onChange, + onChangeMultiple, + } = useTraderStore(); + + const duration_props = { + advanced_expiry_type, + advanced_duration_unit, getDurationFromUnit, is_advanced_duration, - onChange, onChangeUiStore, simple_duration_unit, contract_expiry_type, - duration_min_max, + duration, + duration_unit, + duration_t, duration_units_list, + duration_min_max, + expiry_type, + expiry_date, + expiry_time, + start_date, + market_open_times, + onChange, onChangeMultiple, - } = props; + contract_type, + }; const hasDurationUnit = (duration_type, is_advanced) => { let duration_list = [...duration_units_list]; @@ -155,58 +188,23 @@ const DurationWrapper = props => { setDurationUnit(); } - return ; -}; + return ( + + ); +}); DurationWrapper.propTypes = { - advanced_duration_unit: PropTypes.string, - advanced_expiry_type: PropTypes.string, - contract_expiry_type: PropTypes.string, - duration: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), duration_d: PropTypes.number, duration_h: PropTypes.number, duration_m: PropTypes.number, - duration_min_max: PropTypes.object, duration_s: PropTypes.number, - duration_t: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), duration_unit: PropTypes.string, duration_units_list: MobxPropTypes.arrayOrObservableArray, - expiry_date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - expiry_time: PropTypes.string, - expiry_type: PropTypes.string, getDurationFromUnit: PropTypes.func, - is_advanced_duration: PropTypes.bool, is_minimized: PropTypes.bool, - market_open_times: PropTypes.array, - onChange: PropTypes.func, - onChangeMultiple: PropTypes.func, - onChangeUiStore: PropTypes.func, sessions: MobxPropTypes.arrayOrObservableArray, - simple_duration_unit: PropTypes.string, - start_date: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), start_time: PropTypes.string, symbol: PropTypes.string, }; -export default connect(({ modules, ui }) => ({ - advanced_duration_unit: ui.advanced_duration_unit, - advanced_expiry_type: ui.advanced_expiry_type, - contract_type: modules.trade.contract_type, - contract_expiry_type: modules.trade.contract_expiry_type, - duration: modules.trade.duration, - duration_unit: modules.trade.duration_unit, - duration_units_list: modules.trade.duration_units_list, - duration_min_max: modules.trade.duration_min_max, - duration_t: ui.duration_t, - expiry_date: modules.trade.expiry_date, - expiry_time: modules.trade.expiry_time, - expiry_type: modules.trade.expiry_type, - getDurationFromUnit: ui.getDurationFromUnit, - is_advanced_duration: ui.is_advanced_duration, - onChange: modules.trade.onChange, - onChangeUiStore: ui.onChangeUiStore, - onChangeMultiple: modules.trade.onChangeMultiple, - simple_duration_unit: ui.simple_duration_unit, - start_date: modules.trade.start_date, - market_open_times: modules.trade.market_open_times, -}))(DurationWrapper); +export default DurationWrapper; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/simple-duration.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/simple-duration.jsx index 4c1827ecf0ad..813c364c942e 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/simple-duration.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Duration/simple-duration.jsx @@ -3,84 +3,75 @@ import PropTypes from 'prop-types'; import React from 'react'; import { ButtonToggle, InputField } from '@deriv/components'; import RangeSlider from 'App/Components/Form/RangeSlider'; -import { connect } from 'Stores/connect'; import TradingDatePicker from '../../DatePicker'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const SimpleDuration = ({ - contract_expiry_type, - changeDurationUnit, - current_focus, - duration_t, - duration_units_list, - getDurationFromUnit, - number_input_props, - shared_input_props, - simple_duration_unit, - validation_errors, - setCurrentFocus, -}) => { - const filterMinutesAndTicks = arr => { - const filtered_arr = arr.filter(du => du.value === 't' || du.value === 'm'); - if (filtered_arr.length <= 1) return []; +const SimpleDuration = observer( + ({ + changeDurationUnit, + duration_t, + duration_units_list, + getDurationFromUnit, + number_input_props, + shared_input_props, + }) => { + const { ui } = useStore(); + const { current_focus, setCurrentFocus, simple_duration_unit } = ui; + const { contract_expiry_type, validation_errors } = useTraderStore(); - return filtered_arr; - }; - const has_label = !duration_units_list.some(du => du.value === 't'); + const filterMinutesAndTicks = arr => { + const filtered_arr = arr.filter(du => du.value === 't' || du.value === 'm'); + if (filtered_arr.length <= 1) return []; - return ( - <> - {duration_units_list.length > 1 && ( - - )} - {simple_duration_unit === 't' && contract_expiry_type === 'tick' && ( - - )} - {simple_duration_unit === 'd' && ( - - )} - {simple_duration_unit !== 't' && simple_duration_unit !== 'd' && ( - - )} - - ); -}; + return filtered_arr; + }; + const has_label = !duration_units_list.some(du => du.value === 't'); + + return ( + <> + {duration_units_list.length > 1 && ( + + )} + {simple_duration_unit === 't' && contract_expiry_type === 'tick' && ( + + )} + {simple_duration_unit === 'd' && ( + + )} + {simple_duration_unit !== 't' && simple_duration_unit !== 'd' && ( + + )} + + ); + } +); SimpleDuration.propTypes = { changeDurationUnit: PropTypes.func, - contract_expiry_type: PropTypes.string, - current_focus: PropTypes.string, duration_t: PropTypes.number, duration_units_list: MobxPropTypes.arrayOrObservableArray, getDurationFromUnit: PropTypes.func, number_input_props: PropTypes.object, - setCurrentFocus: PropTypes.func, shared_input_props: PropTypes.object, - simple_duration_unit: PropTypes.string, - validation_errors: PropTypes.object, }; -export default connect(({ modules, ui }) => ({ - contract_expiry_type: modules.trade.contract_expiry_type, - current_focus: ui.current_focus, - setCurrentFocus: ui.setCurrentFocus, - simple_duration_unit: ui.simple_duration_unit, - validation_errors: modules.trade.validation_errors, -}))(SimpleDuration); +export default SimpleDuration; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx index a9d32d7821c3..0a75e6a38fa8 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/cancel-deal.jsx @@ -1,21 +1,24 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { Checkbox, Dropdown, Popover, PopoverMessageCheckbox } from '@deriv/components'; import { localize } from '@deriv/translations'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; import { onToggleCancellation, onChangeCancellationDuration } from 'Stores/Modules/Trading/Helpers/multiplier'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const CancelDeal = observer(() => { + const { ui } = useStore(); + const { + cancellation_range_list, + cancellation_duration, + has_cancellation, + has_stop_loss, + has_take_profit, + onChangeMultiple, + } = useTraderStore(); + + const { should_show_cancellation_warning, toggleCancellationWarning } = ui; -const CancelDeal = ({ - cancellation_range_list, - cancellation_duration, - has_cancellation, - has_take_profit, - has_stop_loss, - onChangeMultiple, - should_show_cancellation_warning, - toggleCancellationWarning, -}) => { const should_show_popover = (has_take_profit || has_stop_loss) && should_show_cancellation_warning; const [is_do_not_show_selected, setDoNotShowSelected] = React.useState(!should_show_cancellation_warning); @@ -95,26 +98,6 @@ const CancelDeal = ({ )} ); -}; - -CancelDeal.propTypes = { - cancellation_range_list: PropTypes.array, - cancellation_duration: PropTypes.string, - has_cancellation: PropTypes.bool, - has_stop_loss: PropTypes.bool, - has_take_profit: PropTypes.bool, - onChangeMultiple: PropTypes.func, - should_show_cancellation_warning: PropTypes.bool, - toggleCancellationWarning: PropTypes.func, -}; +}); -export default connect(({ modules, ui }) => ({ - cancellation_range_list: modules.trade.cancellation_range_list, - cancellation_duration: modules.trade.cancellation_duration, - has_cancellation: modules.trade.has_cancellation, - has_stop_loss: modules.trade.has_stop_loss, - has_take_profit: modules.trade.has_take_profit, - onChangeMultiple: modules.trade.onChangeMultiple, - should_show_cancellation_warning: ui.should_show_cancellation_warning, - toggleCancellationWarning: ui.toggleCancellationWarning, -}))(CancelDeal); +export default CancelDeal; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx index 9cb0a7e1504a..5885416e322a 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration-modal.jsx @@ -1,10 +1,13 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Button, Div100vhContainer, Modal, Text } from '@deriv/components'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import Expiration from './expiration.jsx'; +import { observer, useStore } from '@deriv/stores'; -const MultipliersExpirationModal = ({ is_open, enableApp, disableApp, toggleModal }) => { +const MultipliersExpirationModal = observer(({ is_open, toggleModal }) => { + const { ui } = useStore(); + const { enableApp, disableApp } = ui; return ( ); +}); + +MultipliersExpirationModal.propTypes = { + is_open: PropTypes.bool, + toggleModal: PropTypes.func, }; -export default connect(({ ui }) => ({ - enableApp: ui.enableApp, - disableApp: ui.disableApp, -}))(MultipliersExpirationModal); +export default MultipliersExpirationModal; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration.jsx index 33073f42c1cb..e308b241eede 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/expiration.jsx @@ -4,9 +4,13 @@ import { localize } from '@deriv/translations'; import { formatDuration, getDiffDuration, getDateFromNow } from '@deriv/shared'; import { Text } from '@deriv/components'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const Expiration = ({ expiration, start_time, is_text_only, text_size }) => { +const Expiration = observer(({ is_text_only, text_size }) => { + const { expiration } = useTraderStore(); + const { common } = useStore(); + const { server_time: start_time } = common; const { days, timestamp } = formatDuration(getDiffDuration(start_time.unix(), expiration), 'HH:mm'); const date = getDateFromNow(days, 'day', 'DD MMM YYYY'); @@ -49,16 +53,11 @@ const Expiration = ({ expiration, start_time, is_text_only, text_size }) => {
); -}; +}); Expiration.propTypes = { - expiration: PropTypes.number, is_text_only: PropTypes.bool, - start_time: PropTypes.number, text_size: PropTypes.string, }; -export default connect(({ modules, common }) => ({ - expiration: modules.trade.expiration, - start_time: common.server_time, -}))(Expiration); +export default Expiration; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/info.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/info.jsx index 0c9118857257..3042c960b29c 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/info.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/info.jsx @@ -3,134 +3,119 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Popover, Money, Text } from '@deriv/components'; import { Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; const commission_tooltip_margin = 30; const stop_out_tooltip_margin = 160; -const MultipliersInfo = ({ - amount = 0, - commission = 0, - className, - commission_text_size, - stop_out_text_size, - currency, - multiplier = 0, - has_stop_loss, - is_tooltip_relative, - should_show_tooltip, - stop_out = 0, -}) => { - const commission_text = ( - +const MultipliersInfo = observer( + ({ className, commission_text_size, stop_out_text_size, is_tooltip_relative, should_show_tooltip, ...props }) => { + const trade = useTraderStore(); + const { currency, has_stop_loss } = trade; + const multiplier = props.multiplier ?? (trade.multiplier || 0); + const amount = props.amount ?? (trade.amount || 0); + const commission = props.commission ?? (trade.commission || 0); + const stop_out = props.stop_out ?? (trade.stop_out || 0); + + const commission_text = ( + + ]} + /> + + ); + + const stop_out_text = ( + + ]} + /> + + ); + + const commission_tooltip = ( ]} + i18n_default_text='<0>{{commission_percentage}}% of (<1/> * {{multiplier}})' + values={{ + commission_percentage: Number((commission * 100) / (multiplier * amount)).toFixed(4), + multiplier, + }} + components={[ + , + , + ]} /> - - ); + ); - const stop_out_text = ( - + const stop_out_tooltip = ( ]} + i18n_default_text='When your current loss equals or exceeds {{stop_out_percentage}}% of your stake, your contract will be closed at the nearest available asset price.' + values={{ + stop_out_percentage: Math.floor(Math.abs(Number((stop_out * 100) / amount))), + }} /> - - ); - - const commission_tooltip = ( - , - , - ]} - /> - ); + ); - const stop_out_tooltip = ( - - ); + const getInfo = ({ text, message, margin }) => { + return should_show_tooltip ? ( + + {text} + + ) : ( + text + ); + }; - const getInfo = ({ text, message, margin }) => { - return should_show_tooltip ? ( - - {text} - - ) : ( - text - ); - }; - - return ( -
- {getInfo({ - text: commission_text, - message: commission_tooltip, - margin: commission_tooltip_margin, - })} - {!has_stop_loss && - getInfo({ - text: stop_out_text, - message: stop_out_tooltip, - margin: stop_out_tooltip_margin, + {getInfo({ + text: commission_text, + message: commission_tooltip, + margin: commission_tooltip_margin, })} -
- ); -}; + {!has_stop_loss && + getInfo({ + text: stop_out_text, + message: stop_out_tooltip, + margin: stop_out_tooltip_margin, + })} +
+ ); + } +); MultipliersInfo.propTypes = { - amount: PropTypes.number, className: PropTypes.string, - commission: PropTypes.number, commission_text_size: PropTypes.string, - currency: PropTypes.string, - has_stop_loss: PropTypes.bool, is_tooltip_relative: PropTypes.bool, - multiplier: PropTypes.number, should_show_tooltip: PropTypes.bool, - stop_out: PropTypes.number, stop_out_text_size: PropTypes.string, }; -export default connect(({ modules }, props) => ({ - amount: props.amount ?? modules.trade.amount, - commission: props.commission ?? modules.trade.commission, - currency: modules.trade.currency, - has_stop_loss: modules.trade.has_stop_loss, - multiplier: modules.trade.multiplier, - stop_out: props.stop_out ?? modules.trade.stop_out, -}))(MultipliersInfo); +export default MultipliersInfo; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/multiplier.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/multiplier.jsx index b6a38c53d9f2..2a41a0a088c0 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/multiplier.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/multiplier.jsx @@ -1,10 +1,10 @@ -import { PropTypes as MobxPropTypes } from 'mobx-react'; -import PropTypes from 'prop-types'; import React from 'react'; import { Dropdown } from '@deriv/components'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer } from '@deriv/stores'; -const Multiplier = ({ multiplier, multiplier_range_list, onChange }) => { +const Multiplier = observer(() => { + const { multiplier, multiplier_range_list, onChange } = useTraderStore(); return ( { onChange={onChange} /> ); -}; +}); -Multiplier.propTypes = { - multiplier: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - multiplier_range_list: MobxPropTypes.arrayOrObservableArray, - onChange: PropTypes.func, -}; - -export default connect(({ modules }) => ({ - multiplier: modules.trade.multiplier, - multiplier_range_list: modules.trade.multiplier_range_list, - onChange: modules.trade.onChange, -}))(Multiplier); +export default Multiplier; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/stop-loss.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/stop-loss.jsx index d14cc6d826bc..359885d07488 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/stop-loss.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/stop-loss.jsx @@ -1,25 +1,25 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { InputWithCheckbox } from '@deriv/components'; import { localize } from '@deriv/translations'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; import { isDesktop } from '@deriv/shared'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const StopLoss = observer(props => { + const { ui, client } = useStore(); + const trade = useTraderStore(); + + const { addToast, removeToast, current_focus, setCurrentFocus } = ui; + const { is_single_currency } = client; + const { amount, currency } = trade; + + const validation_errors = props.validation_errors ?? trade.validation_errors; + const stop_loss = props.stop_loss ?? trade.stop_loss; + const has_stop_loss = props.has_stop_loss ?? trade.has_stop_loss; + const onChangeMultiple = props.onChangeMultiple ?? trade.onChangeMultiple; + const onChange = props.onChange ?? trade.onChange; -const StopLoss = ({ - addToast, - removeToast, - amount, - currency, - current_focus, - has_stop_loss, - is_single_currency, - onChange, - onChangeMultiple, - setCurrentFocus, - stop_loss, - validation_errors, -}) => { const changeValue = e => { if (e.target.name === 'has_stop_loss') { const new_val = e.target.value; @@ -61,35 +61,6 @@ const StopLoss = ({ /> ); -}; - -StopLoss.propTypes = { - addToast: PropTypes.func, - amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - currency: PropTypes.string, - current_focus: PropTypes.string, - has_stop_loss: PropTypes.bool, - is_single_currency: PropTypes.bool, - onChange: PropTypes.func, - onChangeMultiple: PropTypes.func, - removeToast: PropTypes.func, - setCurrentFocus: PropTypes.func, - stop_loss: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - validation_errors: PropTypes.object, -}; +}); -export default connect(({ modules, client, ui }, props) => ({ - addToast: ui.addToast, - amount: modules.trade.amount, - currency: modules.trade.currency, - current_focus: ui.current_focus, - has_cancellation: props.has_cancellation ?? modules.trade.has_cancellation, - has_stop_loss: props.has_stop_loss ?? modules.trade.has_stop_loss, - is_single_currency: client.is_single_currency, - onChange: props.onChange ?? modules.trade.onChange, - onChangeMultiple: props.onChangeMultiple ?? modules.trade.onChangeMultiple, - setCurrentFocus: ui.setCurrentFocus, - removeToast: ui.removeToast, - stop_loss: props.stop_loss ?? modules.trade.stop_loss, - validation_errors: props.validation_errors ?? modules.trade.validation_errors, -}))(StopLoss); +export default StopLoss; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/take-profit.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/take-profit.jsx index 092519cbbe93..74b8c86d8979 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/take-profit.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/take-profit.jsx @@ -1,26 +1,26 @@ -import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; import { InputWithCheckbox } from '@deriv/components'; import { localize } from '@deriv/translations'; import { isDesktop } from '@deriv/shared'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const TakeProfit = observer(props => { + const { ui, client } = useStore(); + const trade = useTraderStore(); + + const { addToast, removeToast, current_focus, setCurrentFocus } = ui; + const { is_single_currency } = client; + const { is_accumulator, currency } = trade; + + const validation_errors = props.validation_errors ?? trade.validation_errors; + const take_profit = props.take_profit ?? trade.take_profit; + const has_take_profit = props.has_take_profit ?? trade.has_take_profit; + const onChangeMultiple = props.onChangeMultiple ?? trade.onChangeMultiple; + const onChange = props.onChange ?? trade.onChange; -const TakeProfit = ({ - addToast, - removeToast, - currency, - current_focus, - has_take_profit, - is_accumulator, - is_single_currency, - onChange, - onChangeMultiple, - setCurrentFocus, - take_profit, - validation_errors, -}) => { const changeValue = e => { if (e.target.name === 'has_take_profit') { const new_val = e.target.value; @@ -63,35 +63,6 @@ const TakeProfit = ({ /> ); -}; - -TakeProfit.propTypes = { - addToast: PropTypes.func, - currency: PropTypes.string, - current_focus: PropTypes.string, - has_info: PropTypes.bool, - has_take_profit: PropTypes.bool, - is_accumulator: PropTypes.bool, - is_single_currency: PropTypes.bool, - onChange: PropTypes.func, - onChangeMultiple: PropTypes.func, - removeToast: PropTypes.func, - setCurrentFocus: PropTypes.func, - take_profit: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - validation_errors: PropTypes.object, -}; +}); -export default connect(({ modules, client, ui }, props) => ({ - addToast: ui.addToast, - currency: modules.trade.currency, - current_focus: ui.current_focus, - has_take_profit: props.has_take_profit ?? modules.trade.has_take_profit, - is_accumulator: modules.trade.is_accumulator, - is_single_currency: client.is_single_currency, - onChange: props.onChange ?? modules.trade.onChange, - onChangeMultiple: props.onChangeMultiple ?? modules.trade.onChangeMultiple, - removeToast: ui.removeToast, - setCurrentFocus: ui.setCurrentFocus, - take_profit: props.take_profit ?? modules.trade.take_profit, - validation_errors: props.validation_errors ?? modules.trade.validation_errors, -}))(TakeProfit); +export default TakeProfit; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx index 2b2bc8e22060..3d73bfdb0205 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/Multiplier/widgets.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { Money, Text } from '@deriv/components'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer } from '@deriv/stores'; import MultiplierAmountModal from 'Modules/Trading/Containers/Multiplier/multiplier-amount-modal.jsx'; import RadioGroupOptionsModal from 'Modules/Trading/Containers/radio-group-options-modal.jsx'; import MultipliersExpiration from 'Modules/Trading/Components/Form/TradeParams/Multiplier/expiration.jsx'; @@ -54,13 +55,17 @@ const AmountWidget = ({ amount, currency, expiration, is_crypto_multiplier }) => ); }; -export const MultiplierAmountWidget = connect(({ modules }) => ({ - amount: modules.trade.amount, - expiration: modules.trade.expiration, - currency: modules.trade.currency, - is_crypto_multiplier: modules.trade.is_crypto_multiplier, - multiplier: modules.trade.multiplier, -}))(AmountWidget); +export const MultiplierAmountWidget = observer(() => { + const { amount, expiration, currency, is_crypto_multiplier, multiplier } = useTraderStore(); + const amount_widget_props = { + amount, + expiration, + currency, + is_crypto_multiplier, + multiplier, + }; + return ; +}); const RadioGroupOptionsWidget = ({ displayed_trade_param, modal_title }) => { const [is_open, setIsOpen] = React.useState(false); @@ -81,12 +86,16 @@ const RadioGroupOptionsWidget = ({ displayed_trade_param, modal_title }) => { ); }; -export const MultiplierOptionsWidget = connect(({ modules }) => ({ - displayed_trade_param: `x${modules.trade.multiplier}`, - modal_title: localize('Multiplier'), -}))(RadioGroupOptionsWidget); +export const MultiplierOptionsWidget = observer(() => { + const { multiplier } = useTraderStore(); + const displayed_trade_param = `x${multiplier}`; + const modal_title = localize('Multiplier'); + return ; +}); -export const AccumulatorOptionsWidget = connect(({ modules }) => ({ - displayed_trade_param: `${getGrowthRatePercentage(modules.trade.growth_rate)}%`, - modal_title: localize('Accumulate'), -}))(RadioGroupOptionsWidget); +export const AccumulatorOptionsWidget = observer(() => { + const { growth_rate } = useTraderStore(); + const displayed_trade_param = `${getGrowthRatePercentage(growth_rate)}%`; + const modal_title = localize('Accumulate'); + return ; +}); diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount-mobile.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount-mobile.jsx index bfc405638c10..d588f1377351 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount-mobile.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount-mobile.jsx @@ -4,206 +4,202 @@ import { getDecimalPlaces, isEmptyObject } from '@deriv/shared'; import React from 'react'; import classNames from 'classnames'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const Basis = ({ - addToast, - duration_unit, - duration_value, - toggleModal, - basis, - has_duration_error, - selected_basis, - setSelectedAmount, - onChangeMultiple, - currency, - trade_amount, - trade_basis, - trade_duration, - trade_duration_unit, - setAmountError, - contract_type, - stake_boundary, - vanilla_trade_type, -}) => { - const user_currency_decimal_places = getDecimalPlaces(currency); - const onNumberChange = num => { - setSelectedAmount(basis, num); - validateAmount(num); - }; - const formatAmount = value => - !isNaN(value) && value !== '' ? Number(value).toFixed(user_currency_decimal_places) : value; - const setBasisAndAmount = amount => { - const on_change_obj = {}; +const Basis = observer( + ({ + basis, + duration_unit, + duration_value, + toggleModal, + has_duration_error, + selected_basis, + setSelectedAmount, + setAmountError, + }) => { + const { ui, client } = useStore(); + const { addToast, vanilla_trade_type } = ui; + const { currency } = client; + const { + onChangeMultiple, + trade_amount, + trade_basis, + trade_duration_unit, + trade_duration, + contract_type, + stake_boundary, + } = useTraderStore(); + const user_currency_decimal_places = getDecimalPlaces(currency); + const onNumberChange = num => { + setSelectedAmount(basis, num); + validateAmount(num); + }; + const formatAmount = value => + !isNaN(value) && value !== '' ? Number(value).toFixed(user_currency_decimal_places) : value; + const setBasisAndAmount = amount => { + const on_change_obj = {}; - // Check for any duration changes in Duration trade params Tab before sending onChange object - if (duration_unit !== trade_duration_unit && !has_duration_error) on_change_obj.duration_unit = duration_unit; - if (duration_value !== trade_duration && !has_duration_error) on_change_obj.duration = duration_value; + // Check for any duration changes in Duration trade params Tab before sending onChange object + if (duration_unit !== trade_duration_unit && !has_duration_error) + on_change_obj.duration_unit = duration_unit; + if (duration_value !== trade_duration && !has_duration_error) on_change_obj.duration = duration_value; - if (amount !== trade_amount || basis !== trade_basis) { - on_change_obj.basis = basis; - on_change_obj.amount = amount; - } + if (amount !== trade_amount || basis !== trade_basis) { + on_change_obj.basis = basis; + on_change_obj.amount = amount; + } - if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); - toggleModal(); - }; - const zero_decimals = Number('0').toFixed(getDecimalPlaces(currency)); - const min_amount = parseFloat(zero_decimals.toString().replace(/.$/, '1')); + if (!isEmptyObject(on_change_obj)) onChangeMultiple(on_change_obj); + toggleModal(); + }; + const zero_decimals = Number('0').toFixed(getDecimalPlaces(currency)); + const min_amount = parseFloat(zero_decimals.toString().replace(/.$/, '1')); - const validateAmount = value => { - const localized_message = ; - const selected_value = parseFloat(value.toString()); + const validateAmount = value => { + const localized_message = ; + const selected_value = parseFloat(value.toString()); - if (value.toString() === '0.' || selected_value === 0) { - addToast({ key: 'amount_error', content: localized_message, type: 'error', timeout: 2000 }); - setAmountError(true); - return 'error'; - } else if (isNaN(selected_value) || selected_value < min_amount || value.toString().length < 1) { - addToast({ key: 'amount_error', content: localized_message, type: 'error', timeout: 2000 }); - setAmountError(true); - return false; - } - setAmountError(false); - return true; - }; + if (value.toString() === '0.' || selected_value === 0) { + addToast({ key: 'amount_error', content: localized_message, type: 'error', timeout: 2000 }); + setAmountError(true); + return 'error'; + } else if (isNaN(selected_value) || selected_value < min_amount || value.toString().length < 1) { + addToast({ key: 'amount_error', content: localized_message, type: 'error', timeout: 2000 }); + setAmountError(true); + return false; + } + setAmountError(false); + return true; + }; - return ( -
- {contract_type === 'vanilla' && ( -
-
- {localize('Min. stake')} - - {stake_boundary[vanilla_trade_type].min_stake} {currency} - -
-
- {localize('Max. stake')} - - {stake_boundary[vanilla_trade_type].max_stake} {currency} - -
-
- )} -
- { - return ( -
- {parseFloat(v) > 0 ? : v} -
- ); - }} - reset_press_interval={450} - reset_value='' - pip_size={user_currency_decimal_places} - onValidate={validateAmount} - submit_label={localize('OK')} - onValueChange={onNumberChange} - /> + return ( +
+ {contract_type === 'vanilla' && ( +
+
+ {localize('Min. stake')} + + {stake_boundary[vanilla_trade_type].min_stake} {currency} + +
+
+ {localize('Max. stake')} + + {stake_boundary[vanilla_trade_type].max_stake} {currency} + +
+
+ )} +
+ { + return ( +
+ {parseFloat(v) > 0 ? ( + + ) : ( + v + )} +
+ ); + }} + reset_press_interval={450} + reset_value='' + pip_size={user_currency_decimal_places} + onValidate={validateAmount} + submit_label={localize('OK')} + onValueChange={onNumberChange} + /> +
-
- ); -}; + ); + } +); -const AmountWrapper = connect(({ modules, client, ui }) => ({ - onChangeMultiple: modules.trade.onChangeMultiple, - trade_amount: modules.trade.amount, - trade_basis: modules.trade.basis, - trade_duration_unit: modules.trade.duration_unit, - trade_duration: modules.trade.duration, - currency: client.currency, - addToast: ui.addToast, - contract_type: modules.trade.contract_type, - vanilla_trade_type: ui.vanilla_trade_type, - stake_boundary: modules.trade.stake_boundary, -}))(Basis); +const Amount = observer( + ({ + toggleModal, + duration_value, + duration_unit, + has_duration_error, + amount_tab_idx, + setAmountError, + setAmountTabIdx, + setSelectedAmount, + stake_value, + payout_value, + }) => { + const { basis, basis_list } = useTraderStore(); + const has_selected_tab_idx = typeof amount_tab_idx !== 'undefined'; + const active_index = has_selected_tab_idx ? amount_tab_idx : basis_list.findIndex(b => b.value === basis); -const Amount = ({ - toggleModal, - basis_list, - basis, - duration_value, - duration_unit, - has_duration_error, - amount_tab_idx, - setAmountError, - setAmountTabIdx, - setSelectedAmount, - stake_value, - payout_value, -}) => { - const has_selected_tab_idx = typeof amount_tab_idx !== 'undefined'; - const active_index = has_selected_tab_idx ? amount_tab_idx : basis_list.findIndex(b => b.value === basis); + if (basis_list.length === 1) { + return ( + + ); + } - if (basis_list.length === 1) { return ( - +
+ + {basis_list.map(basis_option => { + switch (basis_option.value) { + case 'stake': + return ( +
+ +
+ ); + case 'payout': + return ( +
+ +
+ ); + default: + return null; + } + })} +
+
); } +); - return ( -
- - {basis_list.map(basis_option => { - switch (basis_option.value) { - case 'stake': - return ( -
- -
- ); - case 'payout': - return ( -
- -
- ); - default: - return null; - } - })} -
-
- ); -}; - -export default connect(({ modules }) => ({ - basis: modules.trade.basis, - basis_list: modules.trade.basis_list, - onChangeMultiple: modules.trade.onChangeMultiple, -}))(Amount); +export default Amount; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount.jsx index d656036999c9..8432a61225e1 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/amount.jsx @@ -4,13 +4,13 @@ import { Localize, localize } from '@deriv/translations'; import AllowEquals from './allow-equals.jsx'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { PropTypes as MobxPropTypes } from 'mobx-react'; import Multiplier from './Multiplier/multiplier.jsx'; import MultipliersInfo from './Multiplier/info.jsx'; import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; export const Input = ({ amount, @@ -48,31 +48,29 @@ export const Input = ({ /> ); -const Amount = ({ - amount, - basis, - basis_list, - contract_start_type, - contract_type, - contract_types_list, - currencies_list, - currency, - current_focus, - duration_unit, - expiry_type, - is_accumulator, - is_equal, - is_minimized, - is_multiplier, - is_nativepicker, - is_single_currency, - has_equals_only, - onChange, - setCurrentFocus, - validation_errors, - stake_boundary, - vanilla_trade_type, -}) => { +const Amount = observer(({ is_minimized, is_nativepicker }) => { + const { ui, client } = useStore(); + const { currencies_list, is_single_currency } = client; + const { setCurrentFocus, vanilla_trade_type, current_focus } = ui; + const { + amount, + basis, + basis_list, + contract_start_type, + contract_type, + contract_types_list, + currency, + duration_unit, + expiry_type, + is_accumulator, + is_equal, + is_multiplier, + has_equals_only, + onChange, + validation_errors, + stake_boundary, + } = useTraderStore(); + if (is_minimized) { return (
@@ -205,55 +203,11 @@ const Amount = ({ )} ); -}; +}); Amount.propTypes = { - amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - basis: PropTypes.string, - basis_list: MobxPropTypes.arrayOrObservableArray, - contract_start_type: PropTypes.string, - contract_type: PropTypes.string, - contract_types_list: MobxPropTypes.observableObject, - currencies_list: MobxPropTypes.observableObject, - currency: PropTypes.string, - current_focus: PropTypes.string, - duration_unit: PropTypes.string, - expiry_type: PropTypes.string, - is_accumulator: PropTypes.bool, - is_equal: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), is_minimized: PropTypes.bool, - is_multiplier: PropTypes.bool, is_nativepicker: PropTypes.bool, - is_single_currency: PropTypes.bool, - has_equals_only: PropTypes.bool, - setCurrentFocus: PropTypes.func, - onChange: PropTypes.func, - validation_errors: PropTypes.object, - stake_boundary: PropTypes.object, - vanilla_trade_type: PropTypes.object, }; -export default connect(({ modules, client, ui }) => ({ - amount: modules.trade.amount, - basis: modules.trade.basis, - basis_list: modules.trade.basis_list, - contract_start_type: modules.trade.contract_start_type, - contract_type: modules.trade.contract_type, - contract_types_list: modules.trade.contract_types_list, - currencies_list: client.currencies_list, - currency: modules.trade.currency, - current_focus: ui.current_focus, - duration_unit: modules.trade.duration_unit, - expiry_type: modules.trade.expiry_type, - is_accumulator: modules.trade.is_accumulator, - is_equal: modules.trade.is_equal, - is_single_currency: client.is_single_currency, - is_multiplier: modules.trade.is_multiplier, - has_equals_only: modules.trade.has_equals_only, - stop_out: modules.trade.stop_out, - onChange: modules.trade.onChange, - setCurrentFocus: ui.setCurrentFocus, - vanilla_trade_type: ui.vanilla_trade_type, - validation_errors: modules.trade.validation_errors, - stake_boundary: modules.trade.stake_boundary, -}))(Amount); +export default Amount; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/barrier.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/barrier.jsx index 44d2756b9ee2..4855881b8b1a 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/barrier.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/barrier.jsx @@ -4,25 +4,25 @@ import React from 'react'; import { DesktopWrapper, Icon, InputField, MobileWrapper, Modal, Text, usePrevious } from '@deriv/components'; import Fieldset from 'App/Components/Form/fieldset.jsx'; import { ValueMovement } from '../Purchase/contract-info'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import { localize } from '@deriv/translations'; import LabeledQuantityInputMobile from '../LabeledQuantityInputMobile'; -const Barrier = ({ - barrier_1, - barrier_2, - barrier_count, - barrier_pipsize, - current_focus, - proposal_info, - duration_unit, - is_minimized, - is_absolute_only, - onChange, - setCurrentFocus, - validation_errors, - trade_types, -}) => { +const Barrier = observer(({ is_minimized, is_absolute_only }) => { + const { ui } = useStore(); + const { current_focus, setCurrentFocus } = ui; + const { + barrier_1, + barrier_2, + barrier_count, + barrier_pipsize, + duration_unit, + onChange, + validation_errors, + proposal_info, + trade_types, + } = useTraderStore(); const [show_modal, setShowModal] = React.useState(false); const type_with_current_spot = Object.keys(trade_types).find(type => proposal_info?.[type]?.spot); const contract_info = proposal_info?.[type_with_current_spot]; @@ -217,34 +217,11 @@ const Barrier = ({ ); -}; +}); Barrier.propTypes = { - barrier_1: PropTypes.string, - barrier_2: PropTypes.string, - barrier_count: PropTypes.number, - barrier_pipsize: PropTypes.number, - current_focus: PropTypes.string, - duration_unit: PropTypes.string, is_absolute_only: PropTypes.bool, is_minimized: PropTypes.bool, - onChange: PropTypes.func, - proposal_info: PropTypes.object, - setCurrentFocus: PropTypes.func, - validation_errors: PropTypes.object, - trade_types: PropTypes.object, }; -export default connect(({ modules, ui }) => ({ - barrier_1: modules.trade.barrier_1, - barrier_2: modules.trade.barrier_2, - barrier_pipsize: modules.trade.barrier_pipsize, - barrier_count: modules.trade.barrier_count, - current_focus: ui.current_focus, - duration_unit: modules.trade.duration_unit, - onChange: modules.trade.onChange, - proposal_info: modules.trade.proposal_info, - setCurrentFocus: ui.setCurrentFocus, - validation_errors: modules.trade.validation_errors, - trade_types: modules.trade.trade_types, -}))(Barrier); +export default Barrier; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/last-digit.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/last-digit.jsx index ee60e5e55d80..87c16bb7da3c 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/last-digit.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/last-digit.jsx @@ -4,9 +4,11 @@ import { isDesktop } from '@deriv/shared'; import { localize } from '@deriv/translations'; import NumberSelector from 'App/Components/Form/number-selector.jsx'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const LastDigit = ({ is_minimized, last_digit, onChange }) => { +const LastDigit = observer(({ is_minimized }) => { + const { onChange, last_digit } = useTraderStore(); if (is_minimized) { return
{`${localize('Last Digit')}: ${last_digit}`}
; } @@ -25,7 +27,7 @@ const LastDigit = ({ is_minimized, last_digit, onChange }) => { /> ); -}; +}); LastDigit.propTypes = { is_minimized: PropTypes.bool, @@ -33,7 +35,4 @@ LastDigit.propTypes = { onChange: PropTypes.func, }; -export default connect(({ modules }) => ({ - last_digit: modules.trade.last_digit, - onChange: modules.trade.onChange, -}))(LastDigit); +export default LastDigit; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/strike.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/strike.jsx index f68a29c62bf4..e7a894956939 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/strike.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/strike.jsx @@ -4,23 +4,17 @@ import { DesktopWrapper, InputField, MobileWrapper, Dropdown, Text, Icon } from import { localize, Localize } from '@deriv/translations'; import { toMoment } from '@deriv/shared'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -import { connect } from 'Stores/connect'; import StrikeParamModal from 'Modules/Trading/Containers/strike-param-modal'; import './strike-field.scss'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const Strike = observer(() => { + const { ui, common } = useStore(); + const { barrier_1, onChange, validation_errors, strike_price_choices, expiry_type, expiry_date } = useTraderStore(); + const { current_focus, setCurrentFocus, advanced_duration_unit, vanilla_trade_type } = ui; + const { server_time } = common; -const Strike = ({ - barrier_1, - current_focus, - onChange, - validation_errors, - setCurrentFocus, - advanced_duration_unit, - strike_price_choices, - expiry_type, - expiry_date, - server_time, - vanilla_trade_type, -}) => { const [is_open, setIsOpen] = React.useState(false); const [should_open_dropdown, setShouldOpenDropdown] = React.useState(false); const [selected_value, setSelectedValue] = React.useState(barrier_1); @@ -36,7 +30,10 @@ const Strike = ({ const is_relative_strike_applicable = expiry_type === 'endtime' ? is_24_hours_contract : advanced_duration_unit !== 'd'; - const strike_price_list = strike_price_choices.map(strike_price => ({ text: strike_price, value: strike_price })); + const strike_price_list = strike_price_choices.map(strike_price => ({ + text: strike_price, + value: strike_price, + })); if (should_open_dropdown) { return ( @@ -151,19 +148,6 @@ const Strike = ({ ); -}; +}); -export default connect(({ modules, ui, common }) => ({ - barrier_1: modules.trade.barrier_1, - current_focus: ui.current_focus, - setCurrentFocus: ui.setCurrentFocus, - onChange: modules.trade.onChange, - validation_errors: modules.trade.validation_errors, - advanced_duration_unit: ui.advanced_duration_unit, - strike_price_choices: modules.trade.strike_price_choices, - expiry_type: modules.trade.expiry_type, - start_date: modules.trade.start_date, - expiry_date: modules.trade.expiry_date, - server_time: common.server_time, - vanilla_trade_type: ui.vanilla_trade_type, -}))(Strike); +export default Strike; diff --git a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx index 07ed81c8cbd3..d7fad2343977 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx @@ -1,9 +1,14 @@ import React from 'react'; import { ButtonToggle } from '@deriv/components'; -import { connect } from 'Stores/connect'; import Fieldset from 'App/Components/Form/fieldset.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; + +const VanillaTradeTypes = observer(() => { + const { ui } = useStore(); + const { onChange } = useTraderStore(); + const { onChangeUiStore, vanilla_trade_type } = ui; -const VanillaTradeTypes = ({ onChange, onChangeUiStore, vanilla_trade_type }) => { const changeTradeType = ({ target }) => { const { name, value } = target; @@ -26,10 +31,6 @@ const VanillaTradeTypes = ({ onChange, onChangeUiStore, vanilla_trade_type }) => /> ); -}; +}); -export default connect(({ modules, ui }) => ({ - onChange: modules.trade.onChange, - onChangeUiStore: ui.onChangeUiStore, - vanilla_trade_type: ui.vanilla_trade_type, -}))(VanillaTradeTypes); +export default VanillaTradeTypes; diff --git a/packages/trader/src/Modules/Trading/Components/Form/screen-small.jsx b/packages/trader/src/Modules/Trading/Components/Form/screen-small.jsx index fbbd2f593f37..b58e1e8f8c5f 100644 --- a/packages/trader/src/Modules/Trading/Components/Form/screen-small.jsx +++ b/packages/trader/src/Modules/Trading/Components/Form/screen-small.jsx @@ -3,7 +3,6 @@ import React from 'react'; import { Collapsible } from '@deriv/components'; import { TradeParamsLoader } from 'App/Components/Elements/ContentLoader'; import AllowEqualsMobile from 'Modules/Trading/Containers/allow-equals.jsx'; -import { connect } from 'Stores/connect'; import { hasCallPutEqual, hasDurationForCallPutEqual, @@ -26,6 +25,8 @@ import classNames from 'classnames'; import AccumulatorsStats from 'Modules/Contract/Components/AccumulatorsStats'; import Strike from 'Modules/Trading/Components/Form/TradeParams/strike.jsx'; import VanillaTradeTypes from 'Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; const CollapsibleTradeParams = ({ form_components, @@ -84,7 +85,11 @@ const CollapsibleTradeParams = ({ )} {!is_accumulator && } - {has_allow_equals && } + {has_allow_equals && ( +
+ +
+ )} {is_multiplier && (
@@ -119,15 +124,41 @@ const CollapsibleTradeParams = ({ ); }; -const ScreenSmall = ({ - is_trade_enabled, - duration_unit, - contract_types_list, - contract_type, - expiry_type, - contract_start_type, - ...props -}) => { +const ScreenSmall = observer(({ is_trade_enabled }) => { + const trade_store = useTraderStore(); + const { + is_accumulator, + is_multiplier, + is_vanilla, + duration_unit, + contract_types_list, + contract_type, + expiry_type, + contract_start_type, + form_components, + has_take_profit, + onChange, + previous_symbol, + is_trade_params_expanded, + setIsTradeParamsExpanded, + take_profit, + } = trade_store; + const is_allow_equal = !!trade_store.is_equal; + + const collapsible_trade_params_props = { + is_accumulator, + is_multiplier, + is_vanilla, + form_components, + has_take_profit, + onChange, + previous_symbol, + is_trade_params_expanded, + setIsTradeParamsExpanded, + take_profit, + is_allow_equal, + }; + const has_callputequal_duration = hasDurationForCallPutEqual( contract_types_list, duration_unit, @@ -143,34 +174,12 @@ const ScreenSmall = ({
) : ( - + ); -}; +}); ScreenSmall.propTypes = { - contract_start_type: PropTypes.string, - contract_type: PropTypes.string, - contract_types_list: PropTypes.object, - duration_unit: PropTypes.string, - expiry_type: PropTypes.string, is_trade_enabled: PropTypes.bool, }; -export default connect(({ modules }) => ({ - is_accumulator: modules.trade.is_accumulator, - is_allow_equal: !!modules.trade.is_equal, - is_multiplier: modules.trade.is_multiplier, - is_vanilla: modules.trade.is_vanilla, - duration_unit: modules.trade.duration_unit, - contract_types_list: modules.trade.contract_types_list, - contract_type: modules.trade.contract_type, - expiry_type: modules.trade.expiry_type, - contract_start_type: modules.trade.contract_start_type, - form_components: modules.trade.form_components, - has_take_profit: modules.trade.has_take_profit, - onChange: modules.trade.onChange, - previous_symbol: modules.trade.previous_symbol, - is_trade_params_expanded: modules.trade.is_trade_params_expanded, - setIsTradeParamsExpanded: modules.trade.setIsTradeParamsExpanded, - take_profit: modules.trade.take_profit, -}))(ScreenSmall); +export default ScreenSmall; diff --git a/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-amount-modal.jsx b/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-amount-modal.jsx index 5643a7434590..839d6bbcad8d 100644 --- a/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-amount-modal.jsx +++ b/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-amount-modal.jsx @@ -2,14 +2,18 @@ import React from 'react'; import { Div100vhContainer, Modal, Money, Popover, usePreventIOSZoom } from '@deriv/components'; import { useIsMounted, WS } from '@deriv/shared'; import { localize, Localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; import { requestPreviewProposal } from 'Stores/Modules/Trading/Helpers/preview-proposal'; import AmountMobile from 'Modules/Trading/Components/Form/TradeParams/amount-mobile.jsx'; import MultipliersInfo from 'Modules/Trading/Components/Form/TradeParams/Multiplier/info.jsx'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; -const MultiplierAmountModal = ({ is_open, enableApp, disableApp, toggleModal }) => { +const MultiplierAmountModal = observer(({ is_open, toggleModal }) => { // Fix to prevent iOS from zooming in erratically on quick taps usePreventIOSZoom(); + const { + ui: { enableApp, disableApp }, + } = useStore(); return ( @@ -27,26 +31,18 @@ const MultiplierAmountModal = ({ is_open, enableApp, disableApp, toggleModal }) title={localize('Stake')} > - + ); -}; +}); -export default connect(({ client, modules, ui }) => ({ - amount: modules.trade.amount, - form_components: modules.trade.form_components, - currency: client.currency, - duration: modules.trade.duration, - duration_unit: modules.trade.duration_unit, - duration_units_list: modules.trade.duration_units_list, - expiry_type: modules.trade.expiry_type, - enableApp: ui.enableApp, - disableApp: ui.disableApp, -}))(MultiplierAmountModal); +export default MultiplierAmountModal; + +const TradeParamsMobile = observer(({ toggleModal }) => { + const { amount, currency, trade_stop_out, trade_store } = useTraderStore(); -const TradeParamsMobile = ({ amount, currency, toggleModal, trade_store, trade_stop_out }) => { const [stake_value, setStakeValue] = React.useState(amount); const [commission, setCommission] = React.useState(null); const [stop_out, setStopOut] = React.useState(null); @@ -119,15 +115,4 @@ const TradeParamsMobile = ({ amount, currency, toggleModal, trade_store, trade_s /> ); -}; - -const TradeParamsMobileWrapper = connect(({ ui, modules }) => ({ - amount: modules.trade.amount, - currency: modules.trade.currency, - multiplier: modules.trade.multiplier, - multiplier_range_list: modules.trade.multiplier_range_list, - trade_stop_out: modules.trade.stop_out, - onChange: modules.trade.onChange, - addToast: ui.addToast, - trade_store: modules.trade, -}))(TradeParamsMobile); +}); diff --git a/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-options.jsx b/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-options.jsx index be311973a765..0b58e3f0c82b 100644 --- a/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-options.jsx +++ b/packages/trader/src/Modules/Trading/Containers/Multiplier/multiplier-options.jsx @@ -3,10 +3,13 @@ import MultipliersInfo from 'Modules/Trading/Components/Form/TradeParams/Multipl import RadioGroupWithInfoMobile from 'Modules/Trading/Components/Form/RadioGroupWithInfoMobile'; import { requestPreviewProposal } from 'Stores/Modules/Trading/Helpers/preview-proposal'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import { useIsMounted, WS } from '@deriv/shared'; -const MultiplierOptions = ({ amount, multiplier, multiplier_range_list, onChange, toggleModal, trade_store }) => { +const MultiplierOptions = observer(() => { + const { amount, multiplier, multiplier_range_list, onChange, toggleModal, trade_store } = useTraderStore(); + const [commission, setCommission] = React.useState(null); const [stop_out, setStopOut] = React.useState(null); const isMounted = useIsMounted(); @@ -52,12 +55,6 @@ const MultiplierOptions = ({ amount, multiplier, multiplier_range_list, onChange /> ); -}; - -export default connect(({ modules }) => ({ - amount: modules.trade.amount, - multiplier: modules.trade.multiplier, - multiplier_range_list: modules.trade.multiplier_range_list, - onChange: modules.trade.onChange, - trade_store: modules.trade, -}))(MultiplierOptions); +}); + +export default MultiplierOptions; diff --git a/packages/trader/src/Modules/Trading/Containers/Multiplier/risk-management-dialog.jsx b/packages/trader/src/Modules/Trading/Containers/Multiplier/risk-management-dialog.jsx index 021fc62e9ea4..7cb12004a094 100644 --- a/packages/trader/src/Modules/Trading/Containers/Multiplier/risk-management-dialog.jsx +++ b/packages/trader/src/Modules/Trading/Containers/Multiplier/risk-management-dialog.jsx @@ -3,24 +3,23 @@ import React from 'react'; import { MobileDialog, Button, Div100vhContainer } from '@deriv/components'; import { isDeepEqual, pick } from '@deriv/shared'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import StopLoss from 'Modules/Trading/Components/Form/TradeParams/Multiplier/stop-loss.jsx'; import TakeProfit from 'Modules/Trading/Components/Form/TradeParams/Multiplier/take-profit.jsx'; import CancelDeal from 'Modules/Trading/Components/Elements/Multiplier/cancel-deal-mobile.jsx'; -const RiskManagementDialog = ({ - is_open, - onClose, - take_profit, - stop_loss, - has_take_profit, - has_stop_loss, - has_cancellation, - cancellation_duration, - cancellation_range_list, - onChangeMultiple, - toggleDialog, -}) => { +const RiskManagementDialog = observer(({ is_open, onClose, toggleDialog }) => { + const { + take_profit, + has_take_profit, + has_stop_loss, + stop_loss, + has_cancellation, + cancellation_range_list, + cancellation_duration, + onChangeMultiple, + } = useTraderStore(); const applied_risk_management_state = { take_profit, stop_loss, @@ -137,15 +136,6 @@ const RiskManagementDialog = ({ ); -}; +}); -export default connect(({ modules }) => ({ - take_profit: modules.trade.take_profit, - has_take_profit: modules.trade.has_take_profit, - stop_loss: modules.trade.stop_loss, - has_stop_loss: modules.trade.has_stop_loss, - has_cancellation: modules.trade.has_cancellation, - cancellation_range_list: modules.trade.cancellation_range_list, - cancellation_duration: modules.trade.cancellation_duration, - onChangeMultiple: modules.trade.onChangeMultiple, -}))(RiskManagementDialog); +export default RiskManagementDialog; diff --git a/packages/trader/src/Modules/Trading/Containers/allow-equals.jsx b/packages/trader/src/Modules/Trading/Containers/allow-equals.jsx index 27124f1381b6..e38a4f91eb98 100644 --- a/packages/trader/src/Modules/Trading/Containers/allow-equals.jsx +++ b/packages/trader/src/Modules/Trading/Containers/allow-equals.jsx @@ -1,9 +1,10 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer } from '@deriv/stores'; import React from 'react'; import { Checkbox, Text } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; const AllowEquals = ({ onChange, is_allow_equal, has_equals_only, className }) => { const handleOnChange = e => { @@ -35,8 +36,12 @@ AllowEquals.propTypes = { onChange: PropTypes.func, }; -export default connect(({ modules }) => ({ - is_allow_equal: !!modules.trade.is_equal, - has_equals_only: modules.trade.has_equals_only, - onChange: modules.trade.onChange, -}))(AllowEquals); +export default observer(() => { + const { is_equal, has_equals_only, onChange } = useTraderStore(); + const allow_equals_props = { + is_allow_equal: !!is_equal, + has_equals_only, + onChange, + }; + return ; +}); diff --git a/packages/trader/src/Modules/Trading/Containers/chart-widgets.jsx b/packages/trader/src/Modules/Trading/Containers/chart-widgets.jsx index a865cce21eed..187f02209352 100644 --- a/packages/trader/src/Modules/Trading/Containers/chart-widgets.jsx +++ b/packages/trader/src/Modules/Trading/Containers/chart-widgets.jsx @@ -2,36 +2,23 @@ import React from 'react'; import { isMobile } from '@deriv/shared'; import Digits from 'Modules/Contract/Components/Digits'; import AccumulatorsStats from 'Modules/Contract/Components/AccumulatorsStats'; -import { connect } from 'Stores/connect'; import BottomWidgets from '../../SmartChart/Components/bottom-widgets.jsx'; -import ControlWidgets from '../../SmartChart/Components/control-widgets.jsx'; import TopWidgets from '../../SmartChart/Components/top-widgets.jsx'; import { symbolChange } from '../../SmartChart/Helpers/symbol'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; -export const DigitsWidget = connect(({ modules, contract_trade }) => ({ - contract_info: contract_trade.last_contract.contract_info || {}, - digits_info: contract_trade.last_contract.digits_info || {}, - display_status: contract_trade.last_contract.display_status, - is_digit_contract: contract_trade.last_contract.is_digit_contract, - is_ended: contract_trade.last_contract.is_ended, - selected_digit: modules.trade.last_digit, - onDigitChange: modules.trade.onChange, - underlying: modules.trade.symbol, - trade_type: modules.trade.contract_type, -}))( - ({ - contract_info, - digits, - digits_info, - display_status, - is_digit_contract, - is_ended, - onDigitChange, - selected_digit, - tick, - trade_type, - underlying, - }) => ( +export const DigitsWidget = observer(({ digits, tick }) => { + const { contract_trade } = useStore(); + const { + onChange: onDigitChange, + symbol: underlying, + contract_type: trade_type, + last_digit: selected_digit, + } = useTraderStore(); + const { last_contract } = contract_trade; + const { contract_info = {}, digits_info = {}, display_status, is_digit_contract, is_ended } = last_contract; + return ( ({ selected_digit={selected_digit} underlying={underlying} /> - ) -); + ); +}); // Chart widgets passed into SmartCharts -export const ChartTopWidgets = connect(({ modules, ui }) => ({ - onSymbolChange: modules.trade.onChange, - theme: ui.is_dark_mode_on ? 'dark' : 'light', -}))(({ onSymbolChange, charts_ref, theme, is_digits_widget_active, open_market, open }) => { +export const ChartTopWidgets = observer(({ charts_ref, is_digits_widget_active, open_market, open }) => { + const { ui } = useStore(); + const { onChange: onSymbolChange } = useTraderStore(); + const { is_dark_mode_on } = ui; + const theme = is_dark_mode_on ? 'dark' : 'light'; let yAxiswidth; if (charts_ref && charts_ref.chart) { yAxiswidth = charts_ref.chart.yAxiswidth; @@ -76,10 +64,3 @@ export const ChartBottomWidgets = ({ digits, tick, show_accumulators_stats }) => Widget={show_accumulators_stats ? : } /> ); - -export const ChartControlWidgets = connect(({ contract_trade }) => ({ - updateChartType: contract_trade.updateChartType, - updateGranularity: contract_trade.updateGranularity, -}))(({ updateChartType, updateGranularity }) => ( - -)); diff --git a/packages/trader/src/Modules/Trading/Containers/contract-type.jsx b/packages/trader/src/Modules/Trading/Containers/contract-type.jsx index e11bec00842a..914be9a0c118 100644 --- a/packages/trader/src/Modules/Trading/Containers/contract-type.jsx +++ b/packages/trader/src/Modules/Trading/Containers/contract-type.jsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { MobileWrapper, usePrevious } from '@deriv/components'; import { unsupported_contract_types_list } from '@deriv/shared'; @@ -8,18 +7,23 @@ import { ToastPopup } from 'Modules/Trading/Containers/toast-popup.jsx'; import { getMarketNamesMap } from '../../../Constants'; import ContractTypeWidget from '../Components/Form/ContractType'; import { getAvailableContractTypes } from '../Helpers/contract-type'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; + +const Contract = observer(() => { + const { + contract_type, + contract_types_list, + is_mobile_digit_view_selected: is_digit_view, + is_equal, + onChange, + symbol, + } = useTraderStore(); + const { + common: { current_language }, + client: { is_virtual }, + } = useStore(); -const Contract = ({ - contract_type, - contract_types_list, - is_digit_view, - is_equal, - is_virtual, - onChange, - symbol, - current_language, -}) => { const list = getAvailableContractTypes(contract_types_list, unsupported_contract_types_list); const digits_message = localize('Last digit stats for latest 1000 ticks for {{ underlying_name }}', { @@ -46,26 +50,6 @@ const Contract = ({ /> ); -}; - -Contract.propTypes = { - contract_type: PropTypes.string, - contract_types_list: PropTypes.object, - is_digit_view: PropTypes.bool, - is_equal: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - is_virtual: PropTypes.bool, - onChange: PropTypes.func, - symbol: PropTypes.string, - current_language: PropTypes.string, -}; +}); -export default connect(({ modules, client, common }) => ({ - contract_type: modules.trade.contract_type, - contract_types_list: modules.trade.contract_types_list, - is_digit_view: modules.trade.is_mobile_digit_view_selected, - is_equal: modules.trade.is_equal, - is_virtual: client.is_virtual, - onChange: modules.trade.onChange, - symbol: modules.trade.symbol, - current_language: common.current_language, -}))(Contract); +export default Contract; diff --git a/packages/trader/src/Modules/Trading/Containers/purchase.jsx b/packages/trader/src/Modules/Trading/Containers/purchase.jsx index 8c1dec8db138..8b434f09da6e 100644 --- a/packages/trader/src/Modules/Trading/Containers/purchase.jsx +++ b/packages/trader/src/Modules/Trading/Containers/purchase.jsx @@ -1,38 +1,38 @@ -import PropTypes from 'prop-types'; import React from 'react'; import { isAccumulatorContract, isEmptyObject, isMobile } from '@deriv/shared'; import { localize } from '@deriv/translations'; import PurchaseButtonsOverlay from 'Modules/Trading/Components/Elements/purchase-buttons-overlay.jsx'; import PurchaseFieldset from 'Modules/Trading/Components/Elements/purchase-fieldset.jsx'; import { getContractTypePosition } from 'Constants/contract'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; import ContractInfo from 'Modules/Trading/Components/Form/Purchase/contract-info.jsx'; -const Purchase = ({ - active_positions, - basis, - contract_type, - currency, - growth_rate, - has_cancellation, - is_accumulator, - is_market_closed, - is_mobile, - is_multiplier, - is_purchase_enabled, - is_trade_enabled, - is_vanilla, - onClickPurchase, - onHoverPurchase, - proposal_info, - purchase_info, - purchased_states_arr, - setPurchaseState, - symbol, - trade_types, - validation_errors, - vanilla_trade_type, -}) => { +const Purchase = observer(({ is_market_closed }) => { + const { + portfolio: { active_positions }, + ui: { purchase_states: purchased_states_arr, is_mobile, setPurchaseState }, + } = useStore(); + const { + basis, + contract_type, + currency, + is_accumulator, + is_multiplier, + growth_rate, + has_cancellation, + is_purchase_enabled, + is_vanilla, + onPurchase: onClickPurchase, + onHoverPurchase, + proposal_info, + purchase_info, + symbol, + validation_errors, + vanilla_trade_type, + trade_types, + is_trade_enabled, + } = useTraderStore(); const is_high_low = /^high_low$/.test(contract_type.toLowerCase()); const isLoading = info => { const has_validation_error = Object.values(validation_errors).some(e => e.length); @@ -125,51 +125,6 @@ const Purchase = ({ ); } return components; -}; +}); -Purchase.propTypes = { - active_positions: PropTypes.array, - basis: PropTypes.string, - currency: PropTypes.string, - growth_rate: PropTypes.number, - has_cancellation: PropTypes.bool, - is_accumulator: PropTypes.bool, - is_multiplier: PropTypes.bool, - is_mobile: PropTypes.bool, - is_purchase_locked: PropTypes.bool, - is_trade_enabled: PropTypes.bool, - onClickPurchase: PropTypes.func, - onHoverPurchase: PropTypes.func, - proposal_info: PropTypes.object, - purchase_info: PropTypes.object, - purchased_states_arr: PropTypes.array, - setPurchaseState: PropTypes.func, - symbol: PropTypes.string, - trade_types: PropTypes.object, - validation_errors: PropTypes.object, -}; - -export default connect(({ modules, portfolio, ui }) => ({ - active_positions: portfolio.active_positions, - basis: modules.trade.basis, - contract_type: modules.trade.contract_type, - currency: modules.trade.currency, - growth_rate: modules.trade.growth_rate, - has_cancellation: modules.trade.has_cancellation, - is_accumulator: modules.trade.is_accumulator, - is_multiplier: modules.trade.is_multiplier, - is_purchase_enabled: modules.trade.is_purchase_enabled, - is_trade_enabled: modules.trade.is_trade_enabled, - is_vanilla: modules.trade.is_vanilla, - onClickPurchase: modules.trade.onPurchase, - onHoverPurchase: modules.trade.onHoverPurchase, - proposal_info: modules.trade.proposal_info, - purchase_info: modules.trade.purchase_info, - symbol: modules.trade.symbol, - trade_types: modules.trade.trade_types, - validation_errors: modules.trade.validation_errors, - vanilla_trade_type: modules.trade.vanilla_trade_type, - is_mobile: ui.is_mobile, - purchased_states_arr: ui.purchase_states, - setPurchaseState: ui.setPurchaseState, -}))(Purchase); +export default Purchase; diff --git a/packages/trader/src/Modules/Trading/Containers/radio-group-options-modal.jsx b/packages/trader/src/Modules/Trading/Containers/radio-group-options-modal.jsx index 5880564e6009..63090bd44529 100644 --- a/packages/trader/src/Modules/Trading/Containers/radio-group-options-modal.jsx +++ b/packages/trader/src/Modules/Trading/Containers/radio-group-options-modal.jsx @@ -1,23 +1,18 @@ import React from 'react'; import { Div100vhContainer, Modal, usePreventIOSZoom } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; import { getGrowthRatePercentage, getTickSizeBarrierPercentage, isEmptyObject } from '@deriv/shared'; import MultiplierOptions from 'Modules/Trading/Containers/Multiplier/multiplier-options.jsx'; import RadioGroupWithInfoMobile from 'Modules/Trading/Components/Form/RadioGroupWithInfoMobile'; +import { observer, useStore } from '@deriv/stores'; + +const RadioGroupOptionsModal = observer(({ is_open, modal_title, toggleModal }) => { + const { accumulator_range_list, growth_rate, onChange, tick_size_barrier, proposal_info } = useTraderStore(); + const { + ui: { enableApp, disableApp }, + } = useStore(); -const RadioGroupOptionsModal = ({ - accumulator_range_list, - enableApp, - disableApp, - growth_rate, - is_open, - modal_title, - onChange, - proposal_info, - tick_size_barrier, - toggleModal, -}) => { // Fix to prevent iOS from zooming in erratically on quick taps usePreventIOSZoom(); const has_error_or_not_loaded = @@ -66,14 +61,6 @@ const RadioGroupOptionsModal = ({ ); -}; +}); -export default connect(({ modules, ui }) => ({ - accumulator_range_list: modules.trade.accumulator_range_list, - disableApp: ui.disableApp, - enableApp: ui.enableApp, - growth_rate: modules.trade.growth_rate, - onChange: modules.trade.onChange, - proposal_info: modules.trade.proposal_info, - tick_size_barrier: modules.trade.tick_size_barrier, -}))(RadioGroupOptionsModal); +export default RadioGroupOptionsModal; diff --git a/packages/trader/src/Modules/Trading/Containers/test.jsx b/packages/trader/src/Modules/Trading/Containers/test.jsx index 5e6fb7368a55..18354bc3ae0e 100644 --- a/packages/trader/src/Modules/Trading/Containers/test.jsx +++ b/packages/trader/src/Modules/Trading/Containers/test.jsx @@ -1,7 +1,8 @@ import { toJS } from 'mobx'; import PropTypes from 'prop-types'; import React from 'react'; -import { connect } from 'Stores/connect'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; const styles = { container: { @@ -30,7 +31,16 @@ const styles = { }, }; -const Test = props => { +const Test = observer(() => { + const stores = useStore(); + const trade_store = useTraderStore(); + const test_stores = { + trade: Object.entries(trade_store), + client: Object.entries(stores.client), + ui: Object.entries(stores.ui), + portfolio: Object.entries(stores.portfolio), + }; + const [is_visible, setIsVisible] = React.useState(false); const [store, setStore] = React.useState('trade'); @@ -63,7 +73,7 @@ const Test = props => { return (
- {Object.keys(props).map(storage => ( + {Object.keys(test_stores).map(storage => (

setStore(storage)} @@ -73,18 +83,13 @@ const Test = props => {

))}
- {props[store].sort().map(renderStoreContent)} + {test_stores[store].sort().map(renderStoreContent)}
); -}; +}); Test.propTypes = { entries: PropTypes.array, }; -export default connect(({ modules, client, ui, portfolio }) => ({ - trade: Object.entries(modules.trade), - client: Object.entries(client), - ui: Object.entries(ui), - portfolio: Object.entries(portfolio), -}))(Test); +export default Test; diff --git a/packages/trader/src/Modules/Trading/Containers/toast-popup.jsx b/packages/trader/src/Modules/Trading/Containers/toast-popup.jsx index c3fe7034a99f..460cfee96b12 100644 --- a/packages/trader/src/Modules/Trading/Containers/toast-popup.jsx +++ b/packages/trader/src/Modules/Trading/Containers/toast-popup.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import ReactDOM from 'react-dom'; import { MobileWrapper, Toast } from '@deriv/components'; -import { connect } from 'Stores/connect'; +import { observer, useStore } from '@deriv/stores'; export const ToastPopup = ({ portal_id = 'popup_root', children, className, ...props }) => { if (!document.getElementById(portal_id)) return null; @@ -54,8 +54,15 @@ NetworkStatusToastError.propTypes = { message: PropTypes.string, }; -export const NetworkStatusToastErrorPopup = connect(({ common }) => ({ - network_status: common.network_status, -}))(({ network_status }) => ( - -)); +export const NetworkStatusToastErrorPopup = observer(() => { + const { + common: { network_status }, + } = useStore(); + return ( + + ); +}); diff --git a/packages/trader/src/Modules/Trading/Containers/trade-params-mobile.jsx b/packages/trader/src/Modules/Trading/Containers/trade-params-mobile.jsx index 8cc9f5d322b9..382cb95b7e0b 100644 --- a/packages/trader/src/Modules/Trading/Containers/trade-params-mobile.jsx +++ b/packages/trader/src/Modules/Trading/Containers/trade-params-mobile.jsx @@ -6,11 +6,10 @@ import AmountMobile from 'Modules/Trading/Components/Form/TradeParams/amount-mob import Barrier from 'Modules/Trading/Components/Form/TradeParams/barrier.jsx'; import DurationMobile from 'Modules/Trading/Components/Form/TradeParams/Duration/duration-mobile.jsx'; import LastDigit from 'Modules/Trading/Components/Form/TradeParams/last-digit.jsx'; -import { PropTypes as MobxPropTypes } from 'mobx-react'; -import PropTypes from 'prop-types'; +import { observer, useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import React from 'react'; import classNames from 'classnames'; -import { connect } from 'Stores/connect'; import { localize, Localize } from '@deriv/translations'; const DEFAULT_DURATION = Object.freeze({ @@ -31,19 +30,12 @@ const reducer = (state, payload) => { const makeGetDefaultDuration = (trade_duration, trade_duration_unit) => duration_unit => trade_duration_unit === duration_unit ? trade_duration : DEFAULT_DURATION[duration_unit]; -const TradeParamsModal = ({ - amount, - duration, - duration_unit, - form_components, - is_open, - enableApp, - disableApp, - toggleModal, - currency, - duration_units_list, - is_vanilla, -}) => { +const TradeParamsModal = observer(({ is_open, toggleModal }) => { + const { client, ui } = useStore(); + const { currency } = client; + const { enableApp, disableApp } = ui; + const { amount, form_components, duration, duration_unit, duration_units_list, is_vanilla } = useTraderStore(); + // eslint-disable-next-line react-hooks/exhaustive-deps const getDefaultDuration = React.useCallback(makeGetDefaultDuration(duration, duration_unit), []); @@ -137,7 +129,7 @@ const TradeParamsModal = ({ > - ); -}; - -TradeParamsModal.propTypes = { - amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - duration: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - duration_unit: PropTypes.string, - duration_units_list: MobxPropTypes.arrayOrObservableArray, - form_components: MobxPropTypes.arrayOrObservableArray, - is_open: PropTypes.bool, - is_vanilla: PropTypes.bool, - disableApp: PropTypes.func, - enableApp: PropTypes.func, - toggleModal: PropTypes.func, - currency: PropTypes.string, -}; +}); -export default connect(({ client, modules, ui }) => ({ - amount: modules.trade.amount, - form_components: modules.trade.form_components, - currency: client.currency, - duration: modules.trade.duration, - duration_unit: modules.trade.duration_unit, - duration_units_list: modules.trade.duration_units_list, - expiry_type: modules.trade.expiry_type, - enableApp: ui.enableApp, - disableApp: ui.disableApp, - is_vanilla: modules.trade.is_vanilla, -}))(TradeParamsModal); +export default TradeParamsModal; -const TradeParamsMobile = ({ - currency, - toggleModal, - isVisible, - setAmountTabIdx, - amount_tab_idx, - setTradeParamTabIdx, - trade_param_tab_idx, - setDurationTabIdx, - duration_unit, - duration_units_list, - duration_value, - duration_tab_idx, - has_amount_error, - has_duration_error, - is_vanilla, - // amount - setAmountError, - setSelectedAmount, - stake_value, - payout_value, - // duration - setDurationError, - setSelectedDuration, - t_duration, - s_duration, - m_duration, - h_duration, - d_duration, - // basis - basis_list, - basis, -}) => { - const getDurationText = () => { - const duration = duration_units_list.find(d => d.value === duration_unit); - return `${duration_value} ${ - duration && (duration_value > 1 ? localize(duration.text) : localize(duration.text.slice(0, -1))) - }`; - }; +const TradeParamsMobile = observer( + ({ + currency, + toggleModal, + isVisible, + setAmountTabIdx, + amount_tab_idx, + setTradeParamTabIdx, + trade_param_tab_idx, + setDurationTabIdx, + duration_unit, + duration_units_list, + duration_value, + duration_tab_idx, + has_amount_error, + has_duration_error, + // amount + setAmountError, + setSelectedAmount, + stake_value, + payout_value, + // duration + setDurationError, + setSelectedDuration, + t_duration, + s_duration, + m_duration, + h_duration, + d_duration, + }) => { + const { basis_list, basis, is_vanilla } = useTraderStore(); + const getDurationText = () => { + const duration = duration_units_list.find(d => d.value === duration_unit); + return `${duration_value} ${ + duration && (duration_value > 1 ? localize(duration.text) : localize(duration.text.slice(0, -1))) + }`; + }; - const getAmountText = () => { - const has_selected_tab_idx = typeof amount_tab_idx !== 'undefined'; - const active_index = has_selected_tab_idx ? amount_tab_idx : basis_list.findIndex(b => b.value === basis); + const getAmountText = () => { + const has_selected_tab_idx = typeof amount_tab_idx !== 'undefined'; + const active_index = has_selected_tab_idx ? amount_tab_idx : basis_list.findIndex(b => b.value === basis); - return ; - }; + return ; + }; - const getHeaderContent = tab_key => { - switch (tab_key) { - case 'duration': - return ( -
-
{localize('Duration')}
-
- {has_duration_error ? localize('Error') : getDurationText()} -
-
- ); - case 'amount': - return ( -
-
- {is_vanilla ? localize('Stake') : localize('Amount')} + const getHeaderContent = tab_key => { + switch (tab_key) { + case 'duration': + return ( +
+
{localize('Duration')}
+
+ {has_duration_error ? localize('Error') : getDurationText()} +
-
- {has_amount_error ? localize('Error') : getAmountText()} + ); + case 'amount': + return ( +
+
+ {is_vanilla ? localize('Stake') : localize('Amount')} +
+
+ {has_amount_error ? localize('Error') : getAmountText()} +
+ ); + default: + return null; + } + }; + return ( + + {isVisible('duration') && ( +
+
- ); - default: - return null; - } - }; - return ( - - {isVisible('duration') && ( -
- -
- )} - {isVisible('amount') && ( -
- -
- )} -
- ); -}; - -const TradeParamsMobileWrapper = connect(({ modules }) => ({ - basis_list: modules.trade.basis_list, - basis: modules.trade.basis, - is_vanilla: modules.trade.is_vanilla, -}))(TradeParamsMobile); + )} + {isVisible('amount') && ( +
+ +
+ )} +
+ ); + } +); -export const LastDigitMobile = connect(({ modules }) => ({ - form_components: modules.trade.form_components, -}))(({ form_components }) => form_components.includes('last_digit') && ); +export const LastDigitMobile = observer(() => { + const { form_components } = useTraderStore(); + return form_components.includes('last_digit') && ; +}); -export const BarrierMobile = connect(({ modules }) => ({ - form_components: modules.trade.form_components, -}))(({ form_components }) => form_components.includes('barrier') && ); +export const BarrierMobile = observer(() => { + const { form_components } = useTraderStore(); + return form_components.includes('barrier') && ; +}); diff --git a/packages/trader/src/Modules/Trading/Containers/trade-params.jsx b/packages/trader/src/Modules/Trading/Containers/trade-params.jsx index 5addbb35a8b3..cd34a3ce49a9 100644 --- a/packages/trader/src/Modules/Trading/Containers/trade-params.jsx +++ b/packages/trader/src/Modules/Trading/Containers/trade-params.jsx @@ -1,4 +1,3 @@ -import { PropTypes as MobxPropTypes } from 'mobx-react'; import PropTypes from 'prop-types'; import React from 'react'; import classNames from 'classnames'; @@ -14,10 +13,12 @@ import Expiration from 'Modules/Trading/Components/Form/TradeParams/Multiplier/e import AccumulatorsInfoDisplay from 'Modules/Trading/Components/Form/TradeParams/Accumulator/accumulators-info-display.jsx'; import Strike from 'Modules/Trading/Components/Form/TradeParams/strike.jsx'; import VanillaTradeTypes from 'Modules/Trading/Components/Form/TradeParams/vanilla-trade-types.jsx'; -import { connect } from 'Stores/connect'; +import { observer } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import Fieldset from 'App/Components/Form/fieldset.jsx'; -const TradeParams = ({ form_components, is_minimized }) => { +const TradeParams = observer(({ is_minimized }) => { + const { form_components } = useTraderStore(); const isVisible = component_key => { return form_components.includes(component_key); }; @@ -39,12 +40,9 @@ const TradeParams = ({ form_components, is_minimized }) => { {isVisible('accu_info_display') && } ); -}; +}); TradeParams.propTypes = { - form_components: MobxPropTypes.arrayOrObservableArray, is_minimized: PropTypes.bool, }; -export default connect(({ modules }) => ({ - form_components: modules.trade.form_components, -}))(TradeParams); +export default TradeParams; diff --git a/packages/trader/src/Modules/Trading/Containers/trade.jsx b/packages/trader/src/Modules/Trading/Containers/trade.jsx index 61950b4261a7..ef6c38c08555 100644 --- a/packages/trader/src/Modules/Trading/Containers/trade.jsx +++ b/packages/trader/src/Modules/Trading/Containers/trade.jsx @@ -1,10 +1,8 @@ import React from 'react'; -import PropTypes from 'prop-types'; import classNames from 'classnames'; import { DesktopWrapper, Div100vhContainer, MobileWrapper, SwipeableWrapper } from '@deriv/components'; import { isDesktop, isMobile } from '@deriv/shared'; import ChartLoader from 'App/Components/Elements/chart-loader.jsx'; -import { connect } from 'Stores/connect'; import PositionsDrawer from 'App/Components/Elements/PositionsDrawer'; import MarketIsClosedOverlay from 'App/Components/Elements/market-is-closed-overlay.jsx'; import Test from './test.jsx'; @@ -13,6 +11,8 @@ import FormLayout from '../Components/Form/form-layout.jsx'; import AllMarkers from '../../SmartChart/Components/all-markers.jsx'; import AccumulatorsChartElements from '../../SmartChart/Components/Markers/accumulators-chart-elements.jsx'; import ToolbarWidgets from '../../SmartChart/Components/toolbar-widgets.jsx'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { observer, useStore } from '@deriv/stores'; const BottomWidgetsMobile = ({ tick, digits, setTick, setDigits }) => { React.useEffect(() => { @@ -29,33 +29,37 @@ const BottomWidgetsMobile = ({ tick, digits, setTick, setDigits }) => { return null; }; -const Trade = ({ - form_components, - getFirstOpenMarket, - should_show_active_symbols_loading, - is_chart_loading, - is_dark_theme, - is_eu, - is_market_closed, - is_market_unavailable_visible, - is_trade_enabled, - is_virtual, - network_status, - NotificationMessages, - onChange, - onMount, - onUnmount, - prepareTradeStore, - setContractTypes, - setMobileDigitView, - is_accumulator, - show_digits_stats, - should_show_multipliers_onboarding, - symbol, - is_synthetics_available, - is_synthetics_trading_market_available, - is_vanilla, -}) => { +const Trade = observer(() => { + const { client, common, ui } = useStore(); + const { + form_components, + getFirstOpenMarket, + should_show_active_symbols_loading, + is_chart_loading, + is_market_closed, + is_trade_enabled, + onChange, + onMount, + onUnmount, + prepareTradeStore, + setContractTypes, + setMobileDigitView, + show_digits_stats, + is_accumulator, + symbol, + is_synthetics_available, + is_synthetics_trading_market_available, + is_vanilla, + } = useTraderStore(); + const { + notification_messages_ui: NotificationMessages, + has_only_forward_starting_contracts: is_market_unavailable_visible, + should_show_multipliers_onboarding, + is_dark_mode_on: is_dark_theme, + } = ui; + const { is_eu, is_virtual } = client; + const { network_status } = common; + const [digits, setDigits] = React.useState([]); const [tick, setTick] = React.useState({}); const [try_synthetic_indices, setTrySyntheticIndices] = React.useState(false); @@ -230,36 +234,9 @@ const Trade = ({
); -}; +}); -export default connect(({ client, common, modules, ui }) => ({ - getFirstOpenMarket: modules.trade.getFirstOpenMarket, - is_accumulator: modules.trade.is_accumulator, - is_eu: client.is_eu, - is_virtual: client.is_virtual, - is_synthetics_available: modules.trade.is_synthetics_available, - is_synthetics_trading_market_available: modules.trade.is_synthetics_trading_market_available, - network_status: common.network_status, - contract_type: modules.trade.contract_type, - form_components: modules.trade.form_components, - should_show_active_symbols_loading: modules.trade.should_show_active_symbols_loading, - is_chart_loading: modules.trade.is_chart_loading, - is_market_closed: modules.trade.is_market_closed, - show_digits_stats: modules.trade.show_digits_stats, - is_trade_enabled: modules.trade.is_trade_enabled, - prepareTradeStore: modules.trade.prepareTradeStore, - setMobileDigitView: modules.trade.setMobileDigitView, - symbol: modules.trade.symbol, - onMount: modules.trade.onMount, - onUnmount: modules.trade.onUnmount, - purchase_info: modules.trade.purchase_info, - NotificationMessages: ui.notification_messages_ui, - is_market_unavailable_visible: ui.has_only_forward_starting_contracts, - should_show_multipliers_onboarding: ui.should_show_multipliers_onboarding, - onChange: modules.trade.onChange, - setContractTypes: modules.trade.setContractTypes, - is_vanilla: modules.trade.is_vanilla, -}))(Trade); +export default Trade; // CHART (ChartTrade)-------------------------------------------------------- @@ -269,8 +246,12 @@ import { SmartChart } from 'Modules/SmartChart'; const SmartChartWithRef = React.forwardRef((props, ref) => ); // ChartMarkers -------------------------- -const Markers = ({ markers_array, is_dark_theme, granularity, currency, config }) => - markers_array.map(marker => { +const ChartMarkers = observer(config => { + const { ui, client, contract_trade } = useStore(); + const { markers_array, granularity } = contract_trade; + const { is_dark_mode_on: is_dark_theme } = ui; + const { currency } = client; + return markers_array.map(marker => { const Marker = AllMarkers[marker.type]; return ( ); }); +}); -const ChartMarkers = connect(({ ui, client, contract_trade }) => ({ - markers_array: contract_trade.markers_array, - is_digit_contract: contract_trade.is_digit_contract, - granularity: contract_trade.granularity, - is_dark_theme: ui.is_dark_mode_on, - currency: client.currency, -}))(Markers); - -const Chart = props => { +const ChartTrade = observer(props => { + const { is_accumulator, end_epoch, topWidgets, charts_ref } = props; + const { client, ui, common, contract_trade, portfolio } = useStore(); const { accumulator_barriers_data, - all_positions, - topWidgets, - charts_ref, + granularity, + chart_type, updateGranularity, updateChartType, - active_symbols, - chart_layout, - chart_type, + should_highlight_current_spot, + } = contract_trade; + const { all_positions } = portfolio; + const { is_chart_layout_default, is_chart_countdown_visible, is_dark_mode_on } = ui; + const { is_socket_opened, current_language } = common; + const { should_show_eu_content } = client; + const { chartStateChange, - exportLayout, - extra_barriers = [], - end_epoch, - granularity, - has_alternative_source, - is_accumulator, is_trade_enabled, - is_socket_opened, - main_barrier, - refToAddTick, - setChartStatus, - settings, - should_show_eu_content, + main_barrier_flattened: main_barrier, + barriers_flattened: extra_barriers, show_digits_stats, - should_highlight_current_spot, symbol, + exportLayout, + setChartStatus, + chart_layout, wsForget, wsForgetStream, wsSendRequest, wsSubscribe, - } = props; + active_symbols, + has_alternative_source, + refToAddTick, + } = useTraderStore(); + + const settings = { + assetInformation: false, // ui.is_chart_asset_info_visible, + countdown: is_chart_countdown_visible, + isHighestLowestMarkerEnabled: false, // TODO: Pending UI, + language: current_language.toLowerCase(), + position: is_chart_layout_default ? 'bottom' : 'left', + theme: is_dark_mode_on ? 'dark' : 'light', + }; const { current_spot, current_spot_time } = accumulator_barriers_data[symbol] || {}; @@ -422,75 +405,4 @@ const Chart = props => { )} ); -}; - -Chart.propTypes = { - accumulator_barriers_data: PropTypes.object, - all_positions: PropTypes.array, - topWidgets: PropTypes.func, - charts_ref: PropTypes.object, - bottomWidgets: PropTypes.func, - chart_type: PropTypes.string, - chart_layout: PropTypes.any, - chartStateChange: PropTypes.func, - exportLayout: PropTypes.func, - end_epoch: PropTypes.number, - granularity: PropTypes.number, - is_accumulator: PropTypes.bool, - is_trade_enabled: PropTypes.bool, - is_socket_opened: PropTypes.bool, - has_alternative_source: PropTypes.bool, - main_barrier: PropTypes.any, - refToAddTick: PropTypes.func, - setChartStatus: PropTypes.func, - settings: PropTypes.object, - should_show_eu_content: PropTypes.bool, - should_highlight_current_spot: PropTypes.bool, - symbol: PropTypes.string, - wsForget: PropTypes.func, - wsForgetStream: PropTypes.func, - wsSendRequest: PropTypes.func, - wsSubscribe: PropTypes.func, -}; - -const ChartTrade = connect(({ client, modules, ui, common, contract_trade, portfolio }) => ({ - accumulator_barriers_data: contract_trade.accumulator_barriers_data, - all_positions: portfolio.all_positions, - is_socket_opened: common.is_socket_opened, - granularity: contract_trade.granularity, - chart_type: contract_trade.chart_type, - chartStateChange: modules.trade.chartStateChange, - updateChartType: contract_trade.updateChartType, - updateGranularity: contract_trade.updateGranularity, - settings: { - assetInformation: false, // ui.is_chart_asset_info_visible, - countdown: ui.is_chart_countdown_visible, - isHighestLowestMarkerEnabled: false, // TODO: Pending UI, - language: common.current_language.toLowerCase(), - position: ui.is_chart_layout_default ? 'bottom' : 'left', - theme: ui.is_dark_mode_on ? 'dark' : 'light', - }, - last_contract: { - is_digit_contract: contract_trade.last_contract.is_digit_contract, - is_ended: contract_trade.last_contract.is_ended, - }, - is_accumulator: modules.trade.is_accumulator, - is_trade_enabled: modules.trade.is_trade_enabled, - main_barrier: modules.trade.main_barrier_flattened, - extra_barriers: modules.trade.barriers_flattened, - should_show_eu_content: client.should_show_eu_content, - show_digits_stats: modules.trade.show_digits_stats, - should_highlight_current_spot: contract_trade.should_highlight_current_spot, - contract_type: modules.trade.contract_type, - symbol: modules.trade.symbol, - exportLayout: modules.trade.exportLayout, - setChartStatus: modules.trade.setChartStatus, - chart_layout: modules.trade.chart_layout, - wsForget: modules.trade.wsForget, - wsForgetStream: modules.trade.wsForgetStream, - wsSendRequest: modules.trade.wsSendRequest, - wsSubscribe: modules.trade.wsSubscribe, - active_symbols: modules.trade.active_symbols, - has_alternative_source: modules.trade.has_alternative_source, - refToAddTick: modules.trade.refToAddTick, -}))(Chart); +}); diff --git a/packages/trader/src/Stores/Modules/Trading/Helpers/multiplier.js b/packages/trader/src/Stores/Modules/Trading/Helpers/multiplier.js index 21b2a8269991..8376eb452063 100644 --- a/packages/trader/src/Stores/Modules/Trading/Helpers/multiplier.js +++ b/packages/trader/src/Stores/Modules/Trading/Helpers/multiplier.js @@ -1,5 +1,3 @@ -import { connect } from 'Stores/connect'; - export const onToggleCancellation = ({ has_cancellation, onChangeMultiple }) => { // e.target.checked is not reliable, we have to toggle its previous value const new_val = !has_cancellation; @@ -27,14 +25,3 @@ export const onChangeCancellationDuration = ({ event, onChangeMultiple }) => { cancellation_duration: value, }); }; - -// eslint-disable-next-line no-empty-pattern -export const connectWithContractUpdate = connect(({}, { contract = {} }) => { - return { - validation_errors: contract.validation_errors, - contract_update_take_profit: contract.contract_update_take_profit, - contract_update_stop_loss: contract.contract_update_stop_loss, - has_contract_update_take_profit: contract.has_contract_update_take_profit, - has_contract_update_stop_loss: contract.has_contract_update_stop_loss, - }; -}); diff --git a/packages/trader/src/Stores/connect.js b/packages/trader/src/Stores/connect.js deleted file mode 100644 index 4ef42c8d18b6..000000000000 --- a/packages/trader/src/Stores/connect.js +++ /dev/null @@ -1,31 +0,0 @@ -import { useObserver } from 'mobx-react'; -import React from 'react'; - -const isClassComponent = Component => - !!(typeof Component === 'function' && Component.prototype && Component.prototype.isReactComponent); - -export const MobxContent = React.createContext(null); - -function injectStorePropsToComponent(propsToSelectFn, BaseComponent) { - const Component = own_props => { - const store = React.useContext(MobxContent); - - let ObservedComponent = BaseComponent; - - if (isClassComponent(BaseComponent)) { - const FunctionalWrapperComponent = props => ; - ObservedComponent = FunctionalWrapperComponent; - } - - return useObserver(() => ObservedComponent({ ...own_props, ...propsToSelectFn(store, own_props) })); - }; - - Component.displayName = BaseComponent.name; - return Component; -} - -export const MobxContentProvider = ({ store, children }) => { - return {children}; -}; - -export const connect = propsToSelectFn => Component => injectStorePropsToComponent(propsToSelectFn, Component); diff --git a/packages/trader/src/Stores/useTraderStores.tsx b/packages/trader/src/Stores/useTraderStores.tsx new file mode 100644 index 000000000000..5e4db0cd77c2 --- /dev/null +++ b/packages/trader/src/Stores/useTraderStores.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { useStore } from '@deriv/stores'; +import TradeStore from './Modules/Trading/trade-store'; + +const TraderStoreContext = React.createContext(null); + +export const TraderStoreProvider = ({ children }: React.PropsWithChildren) => { + const { modules } = useStore(); + // const memoizedValue = useMemo(() => new TraderStore(), []); + + return {children}; +}; + +export const useTraderStore = () => { + const store = React.useContext(TraderStoreContext); + + if (!store) { + throw new Error('useTraderStore must be used within TraderStoreProvider'); + } + + return store; +}; diff --git a/packages/trader/src/trader-providers.tsx b/packages/trader/src/trader-providers.tsx new file mode 100644 index 000000000000..ce527e2c0347 --- /dev/null +++ b/packages/trader/src/trader-providers.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { StoreProvider } from '@deriv/stores'; +import { TraderStoreProvider } from 'Stores/useTraderStores'; +import type { TCoreStores } from '@deriv/stores/types'; + +export const TraderProviders = ({ children, store }: React.PropsWithChildren<{ store: TCoreStores }>) => { + return ( + + {children} + + ); +}; + +export default TraderProviders;