Skip to content

Commit

Permalink
[DTRA] Maryia/DTRA-1468/feat: Stake functionality for V2 (binary-com#…
Browse files Browse the repository at this point in the history
…16486)

* fix: purchase button background fix & adding box-shadow

* revert: box shadow on purchase button is no longer required

* feat: init Stake

* feat: add stake/payout info to stake bottom sheet & purchase button fixes

* chore: remove unused opacity as quill has been updated

* refactor: util function getDisplayedContractTypes

* feat: use local state to not hide info upon proposal error

* chore: handle empty input error

* fix: error handling - allow showing error initially

* fix: initial value

* fix: mult info

* chore: max payout error handling

* chore: displayed payout values state

* fix: stake logic for rise/fall & higher/lower

* refactor: logic refactoring

* fix: stake styles

* chore: styling & coloring

* feat: add new error for max payout exceeded to purchase button

* feat: use initial values from local storage for stake

* refactor: StakeDetails

* refactor: stake

* test: Stake

* test: add test for Stake basis

* test: fix take-profit test

* fix: show initial value in the Stake textbox

* refactor: address comment

* feat: prevent save action if proposal response has not been received yet

* fix: address comment for comma in stake input

* chore: allow input from numpad with comma that will be auto-replaced with dot
  • Loading branch information
maryia-deriv committed Aug 26, 2024
1 parent 778a079 commit 4fdc5d2
Show file tree
Hide file tree
Showing 20 changed files with 831 additions and 135 deletions.
7 changes: 4 additions & 3 deletions packages/stores/src/mockStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ const mock = (): TStores & { is_mock: boolean } => {
cancellation_range_list: [],
clearContractPurchaseToastBox: jest.fn(),
clearPurchaseInfo: jest.fn(),
clearWheelPickerInitialValues: jest.fn(),
clearV2ParamsInitialValues: jest.fn(),
contract_expiry_type: '',
contract_purchase_toast_box: {},
contract_start_type: '',
Expand Down Expand Up @@ -753,7 +753,7 @@ const mock = (): TStores & { is_mock: boolean } => {
setHoveredBarrier: jest.fn(),
setIsTradeParamsExpanded: jest.fn(),
setTradeTypeTab: jest.fn(),
setWheelPickerInitialValues: jest.fn(),
setV2ParamsInitialValues: jest.fn(),
stake_boundary: {},
start_date: 0,
stop_loss: 0,
Expand All @@ -767,8 +767,9 @@ const mock = (): TStores & { is_mock: boolean } => {
trade_type_tab: '',
trade_types: {},
validation_errors: {},
validation_params: {},
vanilla_trade_type: '',
wheel_picker_initial_values: {},
v2_params_initial_values: {},
},
},
feature_flags: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Money } from '@deriv/components';

type TPurchaseButtonContent = {
current_stake?: number | null;
error?: React.ReactNode;
info: ReturnType<typeof useTraderStore>['proposal_info'][0] | Record<string, never>;
is_reverse?: boolean;
is_high_low?: boolean;
Expand All @@ -25,6 +26,7 @@ type TPurchaseButtonContent = {
const PurchaseButtonContent = ({
currency,
current_stake,
error,
has_open_accu_contract,
info,
is_accumulator,
Expand Down Expand Up @@ -68,26 +70,28 @@ const PurchaseButtonContent = ({
)}
data-testid='dt_purchase_button_wrapper'
>
{!is_content_empty && (
{(!is_content_empty || error) && (
<React.Fragment>
<CaptionText
as='span'
size='sm'
className={clsx(!has_open_accu_contract && 'purchase-button__information__item')}
>
{text_basis}
{!error && text_basis}
</CaptionText>
<CaptionText
as='span'
size='sm'
className={clsx(!has_open_accu_contract && 'purchase-button__information__item')}
>
<Money
amount={amount}
currency={currency}
should_format={!is_turbos && !is_vanilla}
show_currency
/>
{error || (
<Money
amount={amount}
currency={currency}
should_format={!is_turbos && !is_vanilla}
show_currency
/>
)}
</CaptionText>
</React.Fragment>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
height: var(--core-size-2800);
gap: 0px;

&:nth-child(2):not(.purchase-button--loading) {
&:not(:first-child):not(.purchase-button--loading) {
align-items: flex-start;
}
&--single {
Expand Down Expand Up @@ -54,13 +54,18 @@
position: absolute;
background-color: var(--core-color-solid-slate-50);
top: 0;
left: var(--core-spacing-400);
width: calc(100% - var(--core-spacing-800));
inset-inline-start: var(--core-spacing-400);
width: calc((100% - var(--core-spacing-800) - var(--core-spacing-400)) / 2);
height: calc(100% - var(--core-spacing-400));
border-radius: var(--component-button-border-radius-lg);
z-index: -1;
}
&:disabled {
opacity: var(--core-opacity-300); // disabled button opacity in quill-ui is 0.48 (var(--core-opacity-600))

&:last-child:not(.single) {
inset-inline-start: unset;
inset-inline-end: var(--core-spacing-400);
}
&.single {
width: calc(100% - var(--core-spacing-800));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import clsx from 'clsx';
import { observer } from 'mobx-react';
import { Localize } from '@deriv/translations';
import { useStore } from '@deriv/stores';
import { useTraderStore } from 'Stores/useTraderStores';
import { Button, useNotifications } from '@deriv-com/quill-ui';
Expand All @@ -17,6 +18,7 @@ import {
import PurchaseButtonContent from './purchase-button-content';
import { getTradeTypeTabsList } from 'AppV2/Utils/trade-params-utils';
import { StandaloneStopwatchRegularIcon } from '@deriv/quill-icons';
import { getDisplayedContractTypes } from 'AppV2/Utils/trade-types-utils';

const PurchaseButton = observer(() => {
const [loading_button_index, setLoadingButtonIndex] = React.useState<number | null>(null);
Expand Down Expand Up @@ -62,9 +64,7 @@ const PurchaseButton = observer(() => {
is_vanilla_fx,
is_vanilla,
};
const trade_types_array = Object.keys(trade_types).filter(
type => !getTradeTypeTabsList(contract_type).length || type === trade_type_tab
);
const contract_types = getDisplayedContractTypes(trade_types, contract_type, trade_type_tab);
const active_accu_contract = is_accumulator
? all_positions.find(
({ contract_info, type }) =>
Expand Down Expand Up @@ -119,18 +119,24 @@ const PurchaseButton = observer(() => {
disabled={is_accu_sell_disabled}
onClick={() => onClickSell(active_accu_contract?.contract_info.contract_id)}
/>
{is_accu_sell_disabled && <div className='purchase-button purchase-button--disabled-background' />}
{is_accu_sell_disabled && <div className='purchase-button--disabled-background single' />}
</div>
);
}

return (
<div className='purchase-button__wrapper'>
{trade_types_array.map((trade_type, index) => {
{contract_types.map((trade_type, index) => {
const info = proposal_info?.[trade_type] || {};
const is_single_button = trade_types_array.length === 1;
const is_single_button = contract_types.length === 1;
const is_loading = loading_button_index === index;
const is_disabled = !is_trade_enabled_v2;
const is_disabled = !is_trade_enabled_v2 || info.has_error;
/* TODO: stop using error text for is_max_payout_exceeded after validation_params are added to proposal API (both success & error response):
E.g., for is_max_payout_exceeded, we have to temporarily check the error text: Max payout error always contains 3 numbers, the check will work for any languages: */
const float_number_search_regex = /\d+(\.\d+)?/g;
const is_max_payout_exceeded =
info.has_error && info.message?.match(float_number_search_regex)?.length === 3;
const error_message = is_max_payout_exceeded ? <Localize i18n_default_text='Exceeds max payout' /> : '';

return (
<React.Fragment key={trade_type}>
Expand All @@ -154,13 +160,16 @@ const PurchaseButton = observer(() => {
{!is_loading && !is_accumulator && (
<PurchaseButtonContent
{...purchase_button_content_props}
error={error_message}
info={info}
is_reverse={!!index}
/>
)}
</Button>
{is_disabled && !is_loading && (
<div className='purchase-button purchase-button--disabled-background' />
<div
className={clsx('purchase-button--disabled-background', is_single_button && 'single')}
/>
)}
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import { ActionSheet, Text, WheelPicker } from '@deriv-com/quill-ui';
import { localize, Localize } from '@deriv/translations';
import { getGrowthRatePercentage } from '@deriv/shared';
import { Skeleton } from '@deriv/components';
import type { TWheelPickerInitialValues } from 'Stores/Modules/Trading/trade-store';
import type { TV2ParamsInitialValues } from 'Stores/Modules/Trading/trade-store';

type TGrowthRatePickerProps = {
accumulator_range_list?: number[];
growth_rate: number;
maximum_ticks: number;
setGrowthRate: (growth_rate: number) => void;
setWheelPickerInitialValues: ({
value,
name,
}: {
value: number | string;
name: keyof TWheelPickerInitialValues;
}) => void;
setV2ParamsInitialValues: ({ value, name }: { value: number | string; name: keyof TV2ParamsInitialValues }) => void;
should_show_details?: boolean;
tick_size_barrier_percentage: string;
};
Expand All @@ -31,7 +25,7 @@ const GrowthRatePicker = ({
growth_rate,
maximum_ticks,
setGrowthRate,
setWheelPickerInitialValues,
setV2ParamsInitialValues,
should_show_details,
tick_size_barrier_percentage,
}: TGrowthRatePickerProps) => {
Expand All @@ -52,7 +46,7 @@ const GrowthRatePicker = ({
React.useEffect(() => {
if (!initial_growth_rate.current && growth_rate) {
initial_growth_rate.current = growth_rate;
setWheelPickerInitialValues({ value: growth_rate, name: 'growth_rate' });
setV2ParamsInitialValues({ value: growth_rate, name: 'growth_rate' });
}
return () => {
if (initial_growth_rate.current && initial_growth_rate.current !== selected_growth_rate.current) {
Expand All @@ -65,7 +59,7 @@ const GrowthRatePicker = ({

const handleSave = () => {
initial_growth_rate.current = selected_growth_rate.current;
setWheelPickerInitialValues({ value: selected_growth_rate.current, name: 'growth_rate' });
setV2ParamsInitialValues({ value: selected_growth_rate.current, name: 'growth_rate' });
};

const handlePickerValuesChange = (value: string | number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ const GrowthRate = observer(({ is_minimized }: TGrowthRateProps) => {
maximum_ticks,
onChange,
proposal_info,
setWheelPickerInitialValues,
setV2ParamsInitialValues,
tick_size_barrier_percentage,
wheel_picker_initial_values,
v2_params_initial_values,
} = useTraderStore();

const [is_open, setIsOpen] = React.useState(false);
Expand All @@ -53,7 +53,7 @@ const GrowthRate = observer(({ is_minimized }: TGrowthRateProps) => {
maximum_ticks={maximum_ticks}
growth_rate={growth_rate}
setGrowthRate={handleGrowthRateChange}
setWheelPickerInitialValues={setWheelPickerInitialValues}
setV2ParamsInitialValues={setV2ParamsInitialValues}
should_show_details={is_proposal_data_available}
tick_size_barrier_percentage={tick_size_barrier_percentage}
/>
Expand All @@ -78,7 +78,7 @@ const GrowthRate = observer(({ is_minimized }: TGrowthRateProps) => {
];

React.useEffect(() => {
const initial_growth_rate = wheel_picker_initial_values?.growth_rate;
const initial_growth_rate = v2_params_initial_values?.growth_rate;
if (initial_growth_rate && growth_rate !== initial_growth_rate) handleGrowthRateChange(initial_growth_rate);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
Expand Down
Loading

0 comments on commit 4fdc5d2

Please sign in to comment.