Skip to content

Commit

Permalink
Akmal / feat: add missing validations and enable save button for take…
Browse files Browse the repository at this point in the history
… profit and stop loss fields (deriv-com#17321)

* feat: add missing validations and enable save button for take profit and stop loss fields

* feat: rename variable for better clarity

* chore: update types and test cases

* fix: apply suggestions

* fix: formatting
  • Loading branch information
akmal-deriv authored Nov 4, 2024
1 parent 8d22a5a commit 8ae25e2
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 11 deletions.
3 changes: 3 additions & 0 deletions packages/stores/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ export type TPortfolioPosition = {
contract_info: ProposalOpenContract &
Portfolio1 & {
contract_update?: ContractUpdate;
validation_params?: {
[key: string]: { min: string; max: string };
};
};
current_tick?: number;
details?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,18 @@ describe('RiskManagementItem component', () => {
currency: 'USD',
contract_id: 1,
is_valid_to_cancel: 1,
validation_params: {
stop_loss: { min: '1', max: '100' },
take_profit: { min: '1', max: '100' },
},
},
contract: {
contract_info: {
contract_id: 1,
validation_params: {
stop_loss: { min: '1', max: '100' },
take_profit: { min: '1', max: '100' },
},
},
contract_update_history: [],
contract_update_take_profit: 100,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type RiskManagementItemProps = {
modal_body_content: React.ReactNode;
is_deal_cancellation?: boolean;
value?: number | null;
type?: string;
type?: 'take_profit' | 'stop_loss';
};

const RiskManagementItem = observer(
Expand All @@ -31,7 +31,7 @@ const RiskManagementItem = observer(
const [isEnabled, setIsEnabled] = React.useState(false);
const [stepperValue, setStepperValue] = React.useState<number | string>();
const { contract_info, contract } = useContractDetails();
const { contract_type, currency } = contract_info;
const { contract_type, currency, validation_params } = contract_info;
const { validation_errors, updateLimitOrder, clearContractUpdateConfigValues } = contract;
const is_valid_to_cancel = isValidToCancel(contract_info);
const is_accumulator = isAccumulatorContract(contract_type);
Expand All @@ -49,7 +49,7 @@ const RiskManagementItem = observer(
const finalValue = Math.abs(value as number);

const errorKey = `contract_update_${type}` as 'contract_update_stop_loss' | 'contract_update_take_profit';
const errorMessage = validation_errors[errorKey]?.[0] ?? '';
const validation_error_message = validation_errors[errorKey]?.[0] ?? '';

const messageForMultiplier = is_valid_to_cancel ? (
<Localize i18n_default_text='Take profit and/or stop loss are not available while deal cancellation is active.' />
Expand Down Expand Up @@ -91,6 +91,7 @@ const RiskManagementItem = observer(
};

const onSave = () => {
if (error_message) return;
if (isEnabled) {
contract.onChange?.({
name: `has_contract_update_${type}`,
Expand All @@ -99,7 +100,29 @@ const RiskManagementItem = observer(
setIsEnabled(false);
}
updateLimitOrder();
setIsSheetOpen(false);
};

const min_value = type && (validation_params?.[type]?.min ?? 0);
const max_value = type && (validation_params?.[type]?.max ?? 0);

const error_message = (() => {
const field_label = type === 'take_profit' ? localize('take profit') : localize('stop loss');
if (stepperValue && min_value && +stepperValue < +min_value) {
return localize('Please enter a {{field_label}} amount that’s at least {{min_value}}.', {
field_label,
min_value,
});
}
if (stepperValue && max_value && +stepperValue > +max_value) {
return localize('Maximum {{field_label}} allowed is {{max_value}}.', {
field_label,
max_value,
});
}
return validation_error_message;
})();

return (
<div className='risk-management-item__container'>
<div className='risk-management-item'>
Expand Down Expand Up @@ -163,14 +186,14 @@ const RiskManagementItem = observer(
className='text-field--custom'
customType='commaRemoval'
decimals={getDecimalPlaces(currency)}
message={errorMessage}
message={error_message}
minusDisabled={Number(stepperValue) - 1 <= 0}
name={type}
noStatusIcon
onChange={onChange}
placeholder={localize('Amount')}
regex={/[^0-9.,]/g}
status={errorMessage ? 'error' : 'neutral'}
status={error_message ? 'error' : 'neutral'}
textAlignment='center'
inputMode='decimal'
unitLeft={getCurrencyDisplayCode(currency)}
Expand All @@ -187,10 +210,7 @@ const RiskManagementItem = observer(
)}
</ActionSheet.Content>
<ActionSheet.Footer
isPrimaryButtonDisabled={
!!errorMessage || finalValue == stepperValue || stepperValue === '' || stepperValue == 0
}
shouldCloseOnPrimaryButtonClick
shouldCloseOnPrimaryButtonClick={false}
primaryAction={{
content: <Localize i18n_default_text='Save' />,
onAction: onSave,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ describe('StopLoss component', () => {
jest.clearAllMocks();
});

it('passes correct props to RiskManagementItem component when stop loss is visible', () => {
it('passes correct validation_params prop to RiskManagementItem component', () => {
render(<StopLoss />);

expect(screen.getByText('Risk Management Item Mock')).toBeInTheDocument();
expect(screen.getByText('Stop loss')).toBeInTheDocument();
expect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ describe('TakeProfit component', () => {
jest.clearAllMocks();
});

it('passes correct props to RiskManagementItem component when take profit is visible', () => {
it('passes correct validation_params prop to RiskManagementItem component', () => {
render(<TakeProfit />);

expect(screen.getByText('Risk Management Item Mock')).toBeInTheDocument();
expect(screen.getByText('Take profit')).toBeInTheDocument();
expect(
Expand Down

0 comments on commit 8ae25e2

Please sign in to comment.