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 = () => (
-
-
}
- fullWidth
- className='purchase-button'
- >
-
- {localize('Payout')}
- 19.55 USD
-
-
-
}
- fullWidth
- className='purchase-button'
- >
-
- 19.55 USD
- {localize('Payout')}
-
-
-
-);
+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 (
+
+
}
+ fullWidth
+ className='purchase-button purchase-button--single'
+ disabled={!is_valid_to_sell || active_accu_contract?.is_sell_requested}
+ onClick={() => onClickSell(active_accu_contract?.contract_info.contract_id)}
+ >
+
+
+
+ );
+ }
+
+ 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;