diff --git a/packages/shared/src/utils/constants/contract.ts b/packages/shared/src/utils/constants/contract.ts index 65d5764a96bd..08d5db96e81f 100644 --- a/packages/shared/src/utils/constants/contract.ts +++ b/packages/shared/src/utils/constants/contract.ts @@ -10,7 +10,9 @@ import { LocalStore } from '../storage'; export const getLocalizedBasis = () => ({ accumulator: localize('Accumulators'), + current_stake: localize('Current stake'), multiplier: localize('Multiplier'), + max_payout: localize('Max payout'), payout_per_pip: localize('Payout per pip'), payout_per_point: localize('Payout per point'), payout: localize('Payout'), diff --git a/packages/trader/src/AppV2/Components/BottomNav/bottom-nav.tsx b/packages/trader/src/AppV2/Components/BottomNav/bottom-nav.tsx index 8c48b3a569d3..4408a0c6dc5b 100644 --- a/packages/trader/src/AppV2/Components/BottomNav/bottom-nav.tsx +++ b/packages/trader/src/AppV2/Components/BottomNav/bottom-nav.tsx @@ -22,7 +22,7 @@ type BottomNavProps = { const BottomNav = observer(({ children, className }: BottomNavProps) => { const history = useHistory(); const location = useLocation(); - const { active_positions_count } = useStore().portfolio; + const { active_positions_count, onMount, onUnmount } = useStore().portfolio; const bottomNavItems = [ { @@ -85,7 +85,11 @@ const BottomNav = observer(({ children, className }: BottomNavProps) => { setSelectedIndex(index); history.push(bottomNavItems[index].path); }; - + React.useEffect(() => { + onMount(); + return onUnmount; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return (
{children}
diff --git a/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button-content.tsx b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button-content.tsx new file mode 100644 index 000000000000..136162ecc51e --- /dev/null +++ b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button-content.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import clsx from 'clsx'; +import { CaptionText } from '@deriv-com/quill-ui'; +import { useTraderStore } from 'Stores/useTraderStores'; +import { getLocalizedBasis } from '@deriv/shared'; +import { Money } from '@deriv/components'; + +type TPurchaseButtonContent = { + current_stake?: number | null; + info: ReturnType['proposal_info'][0]; + is_reverse?: boolean; +} & Pick< + ReturnType, + | 'currency' + | 'has_open_accu_contract' + | 'is_accumulator' + | 'is_multiplier' + | 'is_vanilla_fx' + | 'is_vanilla' + | 'is_turbos' +>; + +const PurchaseButtonContent = ({ + currency, + current_stake, + has_open_accu_contract, + info, + is_accumulator, + is_multiplier, + is_turbos, + is_vanilla, + is_vanilla_fx, + is_reverse, +}: TPurchaseButtonContent) => { + const localized_basis = getLocalizedBasis(); + + const getAmount = () => { + if (is_multiplier) return info.stake; + if (is_accumulator) return has_open_accu_contract ? Number(current_stake) : info.maximum_payout; + return info?.obj_contract_basis?.value; + }; + const getTextBasis = () => { + if (is_turbos || (is_vanilla && !is_vanilla_fx)) return localized_basis.payout_per_point; + if (is_vanilla_fx) return localized_basis.payout_per_pip; + if (is_multiplier) return localized_basis.stake; + if (is_accumulator) return has_open_accu_contract ? localized_basis.current_stake : localized_basis.max_payout; + return localized_basis.payout; + }; + + return ( + + + {getTextBasis()} + + + + + + ); +}; + +export default PurchaseButtonContent; diff --git a/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.scss b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.scss index c25b7b1969a7..c3cb40186a49 100644 --- a/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.scss +++ b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.scss @@ -3,18 +3,41 @@ padding-block: var(--core-spacing-400); align-items: flex-end; height: var(--core-size-2800); + gap: 0; - & + & { + &:nth-child(2):not(.purchase-button--loading) { align-items: flex-start; } - &__payout { - width: 100%; - display: inline-flex; - justify-content: space-between; + &--single { + align-items: center; + justify-content: center; + + .purchase-button__information__wrapper { + justify-content: center; + gap: var(--core-spacing-400); + } + } + + &--loading { align-items: center; - font-size: var(--core-fontSize-50); - line-height: var(--core-lineHeight-100); + } + + &__information { + &__wrapper { + width: 100%; + display: inline-flex; + justify-content: space-between; + align-items: center; + + &--reverse { + flex-direction: row-reverse; + } + } + + &__item { + color: var(--core-color-solid-slate-50); + } } &__wrapper { diff --git a/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.tsx b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.tsx index 55a499ecd8a5..63760f7e580f 100644 --- a/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.tsx +++ b/packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.tsx @@ -1,35 +1,170 @@ import React from 'react'; +import clsx from 'clsx'; +import { observer } from 'mobx-react'; +import { useStore } from '@deriv/stores'; +import { useTraderStore } from 'Stores/useTraderStores'; import { Button } from '@deriv-com/quill-ui'; -import { Localize, localize } from '@deriv/translations'; - -// TODO: add Text component from Quill UI when it will support sm size with font-size 12px -const PurchaseButton = () => ( -
- - -
-); +import { useDevice } from '@deriv-com/ui'; +import { + getContractTypeDisplay, + getIndicativePrice, + hasContractEntered, + isAccumulatorContract, + isEmptyObject, + isOpen, + isValidToSell, +} from '@deriv/shared'; +import { Localize } from '@deriv/translations'; +import { TTradeStore } from 'Types'; +import PurchaseButtonContent from './purchase-button-content'; + +const PurchaseButton = observer(() => { + const { + portfolio: { all_positions, onClickSell }, + ui: { purchase_states: purchased_states_arr, setPurchaseState }, + } = useStore(); + const { + contract_type, + currency, + has_open_accu_contract, + is_accumulator, + is_multiplier, + is_purchase_enabled, + is_trade_enabled, + is_turbos, + is_vanilla_fx, + is_vanilla, + onPurchase, + proposal_info, + symbol, + trade_types, + validation_errors, + } = useTraderStore(); + const { isMobile } = useDevice(); + //TODO: add error handling when design will be ready + const is_high_low = /^high_low$/.test(contract_type.toLowerCase()); + const is_proposal_empty = isEmptyObject(proposal_info); + const is_disabled = !is_trade_enabled || !is_purchase_enabled || is_proposal_empty; + const purchase_button_content_props = { + currency, + has_open_accu_contract, + is_accumulator, + is_multiplier, + is_turbos, + is_vanilla_fx, + is_vanilla, + }; + const trade_types_array = Object.keys(trade_types); + + const isLoading = (info: TTradeStore['proposal_info'][string]) => { + const has_validation_error = Object.values(validation_errors).some(e => e.length); + return !has_validation_error && !info?.has_error && !info.id; + }; + + const active_accu_contract = is_accumulator + ? all_positions.find( + ({ contract_info, type }) => + isAccumulatorContract(type) && contract_info.underlying === symbol && !contract_info.is_sold + ) + : undefined; + const is_valid_to_sell = active_accu_contract?.contract_info + ? hasContractEntered(active_accu_contract.contract_info) && + isOpen(active_accu_contract.contract_info) && + isValidToSell(active_accu_contract.contract_info) + : false; + const current_stake = + (is_valid_to_sell && active_accu_contract && getIndicativePrice(active_accu_contract.contract_info)) || null; + + if (is_accumulator && has_open_accu_contract) { + const info = proposal_info?.[trade_types_array[0]] || {}; + return ( +
+ +
+ ); + } + + if (trade_types_array.length === 1) { + const info = proposal_info?.[trade_types_array[0]] || {}; + const is_loading = isLoading(info) || !is_purchase_enabled; + + return ( +
+ +
+ ); + } + + return ( +
+ {trade_types_array.map((trade_type, index) => { + const info = proposal_info?.[trade_type] || {}; + const is_loading = isLoading(info); + const is_another_button_loading = + is_loading && + purchased_states_arr.includes(true) && + !purchased_states_arr[index] && + !is_purchase_enabled; + + return ( + + ); + })} +
+ ); +}); export default PurchaseButton;