Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Cancel Close Contracts and TP,SL actions #53

6 changes: 0 additions & 6 deletions packages/trader/src/AppV2/Components/BottomNav/bottom-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
} from '@deriv/quill-icons';
import BottomNavItem from './bottom-nav-item';
import { Badge } from '@deriv-com/quill-ui';
import ContractDetailsFooter from '../ContractDetailsFooter';

type BottomNavProps = {
className?: string;
Expand Down Expand Up @@ -47,10 +46,6 @@ const bottomNavItems = [
icon: <StandaloneBarsRegularIcon iconSize='sm' fill='var(--semantic-color-monochrome-textIcon-normal-high)' />,
label: <Localize i18n_default_text='Menu' />,
},
{
icon: <StandaloneBarsRegularIcon iconSize='sm' fill='var(--semantic-color-monochrome-textIcon-normal-high)' />,
label: <Localize i18n_default_text='Details' />,
},
];

const BottomNav = ({ className, children }: BottomNavProps) => {
Expand All @@ -59,7 +54,6 @@ const BottomNav = ({ className, children }: BottomNavProps) => {
return (
<div className={classNames('bottom-nav', className)}>
<div className='bottom-nav-selection'>{children[selectedIndex]}</div>
{selectedIndex === 4 && <ContractDetailsFooter />}
<div className='bottom-nav-container'>
{bottomNavItems.map((item, index) => (
<BottomNavItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
gap: var(--semantic-spacing-gap-md);
width: 100%;
box-shadow: var(--core-elevation-shadow-210);
position: fixed;
bottom: 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,80 @@
import { Button } from '@deriv-com/quill-ui';
import { TContractInfo, getCardLabels, isMultiplierContract, isValidToCancel, isValidToSell } from '@deriv/shared';
import { useStore } from '@deriv/stores';
import { getRemainingTime } from 'AppV2/Utils/helper';
import { observer } from 'mobx-react';
import React from 'react';

const ContractDetailsFooter = () => {
type ContractInfoProps = {
contract_info: TContractInfo;
};

const ContractDetailsFooter = observer(({ contract_info }: ContractInfoProps) => {
const {
bid_price,
currency,
contract_id,
cancellation: { date_expiry: cancellation_date_expiry } = {},
profit,
contract_type,
} = contract_info;

const { contract_replay, common } = useStore();
const { server_time } = common;
const { onClickCancel, onClickSell, is_sell_requested } = contract_replay;
const is_valid_to_sell = isValidToSell(contract_info);
const is_valid_to_cancel = isValidToCancel(contract_info);
const is_multiplier = isMultiplierContract(contract_type);

return (
<div className='contract-details-footer--container'>
<Button variant='secondary' label='Close @ 9.00 USD' color='black' size='lg' fullWidth />
{is_multiplier ? (
<>
<Button
variant='secondary'
label={`${getCardLabels().CLOSE} ${!is_valid_to_cancel ? `@${bid_price} ${currency}` : ''}`}
color='black'
size='lg'
isLoading={is_sell_requested}
disabled={is_sell_requested || (Number(profit) < 0 && is_valid_to_cancel)}
onClick={() => onClickSell(contract_id)}
fullWidth
/>
{is_valid_to_cancel && (
<Button
onClick={() => onClickCancel(contract_id)}
variant='secondary'
label={`${getCardLabels().CANCEL} ${getRemainingTime({
end_time: cancellation_date_expiry,
format: 'mm:ss',
getCardLabels,
start_time: server_time,
})}`}
color='black'
disabled={Number(profit) >= 0}
size='lg'
fullWidth
/>
)}
</>
) : (
<Button
variant='secondary'
label={
is_valid_to_sell
? `${getCardLabels().CLOSE} @ ${bid_price} ${currency}`
: getCardLabels().RESALE_NOT_OFFERED
}
color='black'
size='lg'
isLoading={is_sell_requested && is_valid_to_sell}
onClick={is_valid_to_sell ? () => onClickSell(contract_id) : undefined}
fullWidth
disabled={!is_valid_to_sell}
/>
)}
</div>
);
};
});

export default ContractDetailsFooter;
44 changes: 21 additions & 23 deletions packages/trader/src/AppV2/Components/OrderDetails/order-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,28 @@ const OrderDetails = ({ contract_info }: ContractInfoProps) => {
const details = orderDetails ? orderDetails.details : {};
return (
<div className='order-details'>
<CardWrapper title='Order Details'>
<div className='table'>
{Object.entries(details).map(([key, value], index) => (
<div className='row' key={index}>
<div className='cell'>
<Text size='sm' color='quill-typography__color--subtle'>
<Localize i18n_default_text={key} />
</Text>
</div>
<div className='cell'>
{Array.isArray(value) ? (
value.map((val, i) => (
<Text key={i} size='sm'>
{val}
</Text>
))
) : (
<Text size='sm'>{value as string | number}</Text>
)}
</div>
<div className='table'>
{Object.entries(details).map(([key, value], index) => (
<div className='row' key={index}>
<div className='cell'>
<Text size='sm' color='quill-typography__color--subtle'>
<Localize i18n_default_text={key} />
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This way will not work. You need to localize the labels directly and pass localized text here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@akmal-deriv Its changed now . localize added to the useOrderDetail Hook

</Text>
</div>
))}
</div>
</CardWrapper>
<div className='cell'>
{Array.isArray(value) ? (
value.map((val, i) => (
<Text key={i} size='sm'>
{val}
</Text>
))
) : (
<Text size='sm'>{value as string | number}</Text>
)}
</div>
</div>
))}
</div>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,104 @@ import DealCancellationRemainingTime from '../DealCancellationRemainingTime/deal
import { observer } from '@deriv/stores';
import useContractDetails from 'AppV2/Hooks/useContractDetails';
import { CONTRACT_TYPES, isAccumulatorContract, isValidToCancel } from '@deriv/shared';
import { useTraderStore } from 'Stores/useTraderStores';

type RiskManagementItemProps = {
label: React.ReactNode;
modal_body_content: React.ReactNode;
validation_message?: React.ReactNode;
is_deal_cancellation?: boolean;
value?: number | null;
type?: string;
};

const RiskManagementItem = observer(
({ label, modal_body_content, validation_message, is_deal_cancellation = false }: RiskManagementItemProps) => {
const [toggle, setToggle] = React.useState(false);
const [isOpen, setIsOpen] = React.useState(false);
const dummy_boolean = false; // This will be flag from backend
const { has_take_profit } = useTraderStore();
const { contract_info } = useContractDetails();
({
label,
modal_body_content,
validation_message,
is_deal_cancellation = false,
value,
type,
}: RiskManagementItemProps) => {
const [toggle, setToggle] = React.useState(Boolean(value));
const [isSheetOpen, setIsSheetOpen] = React.useState(false);
const [isEnabled, setIsEnabled] = React.useState(false);
const dummy_boolean = false;
const [stepperValue, setStepperValue] = React.useState(0);
const { contract_info, contract } = useContractDetails();
const { contract_type, currency } = contract_info;
const { validation_errors, updateLimitOrder, clearContractUpdateConfigValues } = contract;
const is_valid_to_cancel = isValidToCancel(contract_info);
const is_accumulator = isAccumulatorContract(contract_type);

React.useEffect(() => {
if (value) {
setStepperValue(value);
setToggle(Boolean(value));
}
return () => clearContractUpdateConfigValues();
}, [clearContractUpdateConfigValues, value]);

const isDealCancellation = is_valid_to_cancel;
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]?.length > 0 ? validation_errors[errorKey][0] : '';

const info_message = {
[CONTRACT_TYPES.ACCUMULATOR]: (
<Localize i18n_default_text='Take profit can’t be adjusted for ongoing accumulator contracts.' />
),
[CONTRACT_TYPES.MULTIPLIER.UP || CONTRACT_TYPES.MULTIPLIER.DOWN]:
[CONTRACT_TYPES.MULTIPLIER.UP]:
is_valid_to_cancel && !is_deal_cancellation ? (
<Localize i18n_default_text='Take profit and stop loss are unavailable while deal cancellation is enabled.' />
) : (
''
),
[CONTRACT_TYPES.MULTIPLIER.DOWN]:
is_valid_to_cancel && !is_deal_cancellation ? (
<Localize i18n_default_text='Take profit and stop loss are unavailable while deal cancellation is enabled.' />
) : (
''
),
} as const;

const onChange = (
e: React.ChangeEvent<HTMLInputElement> | { target: { name: string; value: number | string | boolean } }
) => {
const { value } = e.target;
setStepperValue(value as number);
contract.onChange?.({
name: `contract_update_${type}`,
value,
});
};

const handleToggleSwitch = (value: boolean) => {
clearContractUpdateConfigValues();
if (value) {
setIsSheetOpen(true);
setIsEnabled(true);
} else {
contract.onChange?.({
name: `has_contract_update_${type}`,
value,
});
updateLimitOrder();
setToggle(!toggle);
}
};

const onSave = () => {
if (isEnabled) {
contract.onChange?.({
name: `has_contract_update_${type}`,
value: true,
});
setIsEnabled(false);
}
updateLimitOrder();
};
return (
<div className='risk-management-item--container'>
<div className='risk-management-item'>
Expand All @@ -50,44 +116,68 @@ const RiskManagementItem = observer(
/>
</span>
{!is_deal_cancellation &&
(has_take_profit && is_accumulator ? (
<Text size='sm'>5 USD</Text>
(is_accumulator ? (
<Text size='sm'>
{finalValue} {currency}
</Text>
) : (
<ToggleSwitch checked={toggle} onChange={() => setToggle(!toggle)} />
<ToggleSwitch
disabled={isDealCancellation}
checked={toggle}
onChange={handleToggleSwitch}
/>
))}
{is_valid_to_cancel && is_deal_cancellation && <DealCancellationRemainingTime />}
</div>
{toggle && (
{!is_accumulator && toggle && (
<TextField
variant='fill'
inputSize='md'
disabled={isSheetOpen}
textAlignment='center'
value='5.00 USD'
onClick={() => setIsOpen(true)}
onFocus={() => setIsOpen(true)}
value={`${finalValue.toFixed(2)} ${currency}`}
onClick={() => {
clearContractUpdateConfigValues();
setStepperValue(finalValue);
setIsSheetOpen(true);
}}
onFocus={() => setIsSheetOpen(true)}
/>
)}
<ActionSheet.Root expandable isOpen={isOpen} onClose={() => setIsOpen(false)}>
<ActionSheet.Root
expandable
isOpen={isSheetOpen}
position='left'
onClose={() => {
setIsEnabled(false);
setIsSheetOpen(false);
}}
>
<ActionSheet.Portal>
<ActionSheet.Header title={label} />
<ActionSheet.Content>
<TextFieldWithSteppers
variant='fill'
inputSize='md'
textAlignment='center'
status='neutral'
unit={currency}
unitPlacement='right'
message={validation_message}
/>
{isSheetOpen && (
<TextFieldWithSteppers
variant='fill'
inputSize='md'
textAlignment='center'
status={errorMessage ? 'error' : 'neutral'}
name={type}
unit={currency}
value={Math.abs(stepperValue)}
onChange={onChange}
unitPlacement='right'
decimals={0}
message={errorMessage}
/>
)}
</ActionSheet.Content>
<ActionSheet.Footer
isPrimaryButtonDisabled={errorMessage !== ''}
shouldCloseOnPrimaryButtonClick
primaryAction={{
content: localize('Save'),
onAction: () => {
//do the save
},
onAction: onSave,
}}
/>
</ActionSheet.Portal>
Expand Down
3 changes: 3 additions & 0 deletions packages/trader/src/AppV2/Components/StopLoss/stop-loss.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import RiskManagementItem from '../RiskManagementItem';

const StopLoss = observer(() => {
const { contract_info } = useContractDetails();
const { limit_order } = contract_info;
const { is_stop_loss_visible } = getContractDetailsConfig(contract_info.contract_type ?? '');

return is_stop_loss_visible ? (
Expand All @@ -15,6 +16,8 @@ const StopLoss = observer(() => {
modal_body_content={
<Localize i18n_default_text='When your loss reaches or exceeds the set amount, your trade will be closed automatically.' />
}
value={limit_order?.stop_loss?.order_amount}
type='stop_loss'
validation_message='hello'
/>
) : null;
Expand Down
Loading
Loading