forked from binary-com/deriv-app
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DTRA-1424 / Kate / Enable purchase functionality (binary-com#145)
* refactor: customize amount of buttons and it name * feat: add basis text and amount for button based on contract type * refactor: purchase button * feat: eanble purchase functionality * feat: add sell functionality for acc button * chore: add caption text from quill * fix: add store init to bottomnav
- Loading branch information
1 parent
7930387
commit 00fff44
Showing
5 changed files
with
285 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
packages/trader/src/AppV2/Components/PurchaseButton/purchase-button-content.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<typeof useTraderStore>['proposal_info'][0]; | ||
is_reverse?: boolean; | ||
} & Pick< | ||
ReturnType<typeof useTraderStore>, | ||
| '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 ( | ||
<CaptionText | ||
size='sm' | ||
className={clsx( | ||
'purchase-button__information__wrapper', | ||
is_reverse && 'purchase-button__information__wrapper--reverse' | ||
)} | ||
> | ||
<CaptionText | ||
as='span' | ||
size='sm' | ||
className={clsx(!has_open_accu_contract && 'purchase-button__information__item')} | ||
> | ||
{getTextBasis()} | ||
</CaptionText> | ||
<CaptionText | ||
as='span' | ||
size='sm' | ||
className={clsx(!has_open_accu_contract && 'purchase-button__information__item')} | ||
> | ||
<Money | ||
amount={getAmount()} | ||
currency={currency} | ||
should_format={!is_turbos && !is_vanilla} | ||
show_currency | ||
/> | ||
</CaptionText> | ||
</CaptionText> | ||
); | ||
}; | ||
|
||
export default PurchaseButtonContent; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
197 changes: 166 additions & 31 deletions
197
packages/trader/src/AppV2/Components/PurchaseButton/purchase-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 = () => ( | ||
<div className='purchase-button__wrapper'> | ||
<Button | ||
color='purchase' | ||
size='lg' | ||
label={<Localize i18n_default_text='Rise' />} | ||
fullWidth | ||
className='purchase-button' | ||
> | ||
<p className='purchase-button__payout'> | ||
<span>{localize('Payout')}</span> | ||
<span>19.55 USD</span> | ||
</p> | ||
</Button> | ||
<Button | ||
color='sell' | ||
size='lg' | ||
label={<Localize i18n_default_text='Fall' />} | ||
fullWidth | ||
className='purchase-button' | ||
> | ||
<p className='purchase-button__payout'> | ||
<span>19.55 USD</span> | ||
<span>{localize('Payout')}</span> | ||
</p> | ||
</Button> | ||
</div> | ||
); | ||
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 ( | ||
<div className='purchase-button__wrapper'> | ||
<Button | ||
color='black' | ||
variant='secondary' | ||
size='lg' | ||
label={<Localize i18n_default_text='Sell' />} | ||
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)} | ||
> | ||
<PurchaseButtonContent | ||
{...purchase_button_content_props} | ||
info={info} | ||
current_stake={current_stake} | ||
/> | ||
</Button> | ||
</div> | ||
); | ||
} | ||
|
||
if (trade_types_array.length === 1) { | ||
const info = proposal_info?.[trade_types_array[0]] || {}; | ||
const is_loading = isLoading(info) || !is_purchase_enabled; | ||
|
||
return ( | ||
<div className='purchase-button__wrapper'> | ||
<Button | ||
color='purchase' | ||
size='lg' | ||
label={getContractTypeDisplay(trade_types_array[0], { | ||
isHighLow: is_high_low, | ||
showButtonName: true, | ||
})} | ||
fullWidth | ||
className='purchase-button purchase-button--single' | ||
isLoading={is_loading} | ||
disabled={(is_disabled || !info.id) && !is_loading} | ||
onClick={() => onPurchase(info.id, info.stake, trade_types_array[0], isMobile)} | ||
> | ||
{!is_loading && <PurchaseButtonContent {...purchase_button_content_props} info={info} />} | ||
</Button> | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className='purchase-button__wrapper'> | ||
{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 ( | ||
<Button | ||
key={trade_type} | ||
color={index ? 'purchase' : 'sell'} | ||
size='lg' | ||
label={getContractTypeDisplay(trade_type, { isHighLow: is_high_low, showButtonName: true })} | ||
fullWidth | ||
className={clsx( | ||
'purchase-button', | ||
is_loading && !is_another_button_loading && 'purchase-button--loading' | ||
)} | ||
isLoading={is_loading && !is_another_button_loading} | ||
disabled={((is_disabled || !info.id) && !is_loading) || is_another_button_loading} | ||
onClick={() => { | ||
setPurchaseState(index); | ||
onPurchase(info.id, info.stake, trade_type, isMobile); | ||
}} | ||
> | ||
{(!is_loading || is_another_button_loading) && ( | ||
<PurchaseButtonContent | ||
{...purchase_button_content_props} | ||
info={info} | ||
is_reverse={!!index} | ||
/> | ||
)} | ||
</Button> | ||
); | ||
})} | ||
</div> | ||
); | ||
}); | ||
|
||
export default PurchaseButton; |