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(refactor): refactor checkout dot com handler #6326

Open
wants to merge 1 commit into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,33 +73,28 @@ const Success: React.FC<Props> = ({ handleClose }) => {
<Value data-e2e='sbCreated'>{format(new Date(sellOrder.createdAt), 'PPpp')}</Value>
</Row>

<>
{sellOrder.state !== 'FAILED' && (
<Row>
<Title>
<FormattedMessage
id='modals.simplebuy.summary.rate'
defaultMessage='Exchange Rate'
/>
</Title>
<Value data-e2e='sbRate'>
{fiatToString({
unit: sellCounterCurrency,
value: sellOrder.priceFunnel.price
})}{' '}
/ 1 {sellBaseCurrency}
</Value>
</Row>
)}
{sellOrder.state !== 'FAILED' && (
<Row>
<Title>
<FormattedMessage id='copy.amount' defaultMessage='Amount' />
<FormattedMessage id='modals.simplebuy.summary.rate' defaultMessage='Exchange Rate' />
</Title>
<Value data-e2e='sbPurchasing'>
{sellBaseAmount} of {sellBaseCurrency}
<Value data-e2e='sbRate'>
{fiatToString({
unit: sellCounterCurrency,
value: sellOrder.priceFunnel.price
})}{' '}
/ 1 {sellBaseCurrency}
</Value>
</Row>
</>
)}
<Row>
<Title>
<FormattedMessage id='copy.amount' defaultMessage='Amount' />
</Title>
<Value data-e2e='sbPurchasing'>
{sellBaseAmount} of {sellBaseCurrency}
</Value>
</Row>
{sellOrder.priceFunnel.outputMoney !== '0' && sellOrder.state !== 'FAILED' && (
<Row>
<Title>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,64 +1,87 @@
import React, { useCallback, useEffect, useState } from 'react'
import { connect, ConnectedProps, useDispatch } from 'react-redux'
import { bindActionCreators } from 'redux'
import { useDispatch, useSelector } from 'react-redux'
import { clearSubmitErrors } from 'redux-form'

import { BSOrderType, ProviderDetailsType, WalletOptionsType } from '@core/types'
import BaseError from 'components/BuySell/Error'
import { GenericNabuErrorFlyout } from 'components/GenericNabuErrorFlyout'
import { actions, selectors } from 'data'
import { buySell } from 'data/components/actions'
import { CARD_ERROR_CODE, FORM_BS_PREVIEW_SELL } from 'data/components/buySell/model'
import { RootState } from 'data/rootReducer'
import {
getBSCard,
getBSMobilePaymentMethod,
getBSOrder,
getBSProviderDetails
} from 'data/components/buySell/selectors'
import { useRemote } from 'hooks'
import { isNabuError } from 'services/errors'

import Loading from './template.loading'
import Success from './template.success'

const ThreeDSHandlerCheckoutDotCom = (props: Props) => {
const [isPolling, setPolling] = useState(false)
const order = useRemote(() => props.orderR)
const card = useRemote(() => props.cardR)
const providerDetails = useRemote(() => props.providerDetailsR)
const ThreeDSHandlerCheckoutDotCom = () => {
const [polling, setPolling] = useState(false)

const mobilePaymentMethod = useSelector(getBSMobilePaymentMethod)

const {
data: orderData,
error: orderError,
hasData: orderHasData,
isLoading: orderLoading,
isNotAsked: orderNotAsked
} = useRemote(getBSOrder)

const {
data: cardData,
error: cardError,
hasData: cardHasData,
isLoading: cardLoading,
isNotAsked: cardNotAsked
} = useRemote(getBSCard)

const {
data: providerData,
error: providerError,
isLoading: providerLoading
} = useRemote(getBSProviderDetails)

const dispatch = useDispatch()

const handlePostMessage = async ({ data }: { data: { payment: 'SUCCESS' } }) => {
const handlePostMessage = ({ data }: { data: { payment: 'SUCCESS' } }) => {
if (data.payment !== 'SUCCESS') return

setPolling(true)

if (order.hasData && order.data) {
props.buySellActions.pollOrder({ orderId: order.data.id, waitUntilSettled: true })
} else if (card.hasData && card.data) {
props.buySellActions.pollCard(card.data.id)
if (orderHasData && orderData) {
dispatch(buySell.pollOrder({ orderId: orderData.id, waitUntilSettled: true }))
} else if (cardHasData && cardData) {
dispatch(buySell.pollCard(cardData.id))
}
}

const handleBack = useCallback(() => {
if (order.data) {
return props.buySellActions.proceedToBuyConfirmation({
mobilePaymentMethod: props.mobilePaymentMethod,
paymentMethodId: order.data.paymentMethodId,
paymentType: order.data.paymentType
})
if (orderData) {
dispatch(
buySell.proceedToBuyConfirmation({
mobilePaymentMethod,
paymentMethodId: orderData.paymentMethodId,
paymentType: orderData.paymentType
})
)
} else {
dispatch(buySell.setStep({ step: 'DETERMINE_CARD_PROVIDER' }))
}

props.buySellActions.setStep({
step: 'DETERMINE_CARD_PROVIDER'
})
}, [order.data, props.buySellActions, props.mobilePaymentMethod])
}, [orderData?.id, mobilePaymentMethod])

const handleReset = useCallback(() => {
props.buySellActions.destroyCheckout()
dispatch(buySell.destroyCheckout())

dispatch(clearSubmitErrors(FORM_BS_PREVIEW_SELL))
}, [props.buySellActions, dispatch])
}, [dispatch])

const handleRetry = useCallback(() => {
props.buySellActions.setStep({
step: 'DETERMINE_CARD_PROVIDER'
})
}, [props.buySellActions])
dispatch(buySell.setStep({ step: 'DETERMINE_CARD_PROVIDER' }))
}, [])

useEffect(() => {
window.addEventListener('message', handlePostMessage, false)
Expand All @@ -84,39 +107,39 @@ const ThreeDSHandlerCheckoutDotCom = (props: Props) => {
[handleReset, handleBack, handleRetry]
)

if (order.hasError && order.error) {
return renderError(order.error)
if (orderError) {
return renderError(orderError)
}

if (card.hasError && card.error) {
return renderError(card.error)
if (cardError) {
return renderError(cardError)
}

if (providerDetails.hasError && providerDetails.error) {
return renderError(providerDetails.error)
if (providerError) {
return renderError(providerError)
}

if (order.isLoading || card.isLoading) {
if (orderLoading || cardLoading) {
return <Loading />
}

if (order.isNotAsked && card.isNotAsked) {
if (orderNotAsked && cardNotAsked) {
return <Loading />
}

if (isPolling) {
return <Loading polling order={order.hasData} />
if (polling) {
return <Loading polling order={orderHasData} />
}

let paymentLink = ''

if (order.data?.attributes?.cardProvider?.cardAcquirerName === 'CHECKOUTDOTCOM') {
paymentLink = encodeURIComponent(order.data?.attributes?.cardProvider.paymentLink)
} else if (order.data?.attributes?.cardCassy?.cardAcquirerName === 'CHECKOUTDOTCOM') {
paymentLink = encodeURIComponent(order.data?.attributes?.cardCassy.paymentLink)
} else if (providerDetails.data) {
paymentLink = encodeURIComponent(providerDetails.data.cardProvider.paymentLink)
} else if (!providerDetails.isLoading && !order.isLoading) {
if (orderData?.attributes?.cardProvider?.cardAcquirerName === 'CHECKOUTDOTCOM') {
paymentLink = encodeURIComponent(orderData?.attributes?.cardProvider.paymentLink)
} else if (orderData?.attributes?.cardCassy?.cardAcquirerName === 'CHECKOUTDOTCOM') {
paymentLink = encodeURIComponent(orderData?.attributes?.cardCassy.paymentLink)
} else if (providerData) {
paymentLink = encodeURIComponent(providerData.cardProvider.paymentLink)
} else if (!providerLoading && !orderLoading) {
return (
<BaseError
code={CARD_ERROR_CODE.CREATE_FAILED}
Expand All @@ -131,44 +154,7 @@ const ThreeDSHandlerCheckoutDotCom = (props: Props) => {
return <Loading />
}

return (
<Success
handleBack={handleBack}
order={order?.data}
paymentLink={paymentLink}
domains={props.domains}
/>
)
return <Success handleBack={handleBack} paymentLink={paymentLink} />
}

const mapStateToProps = (state: RootState) => ({
cardR: selectors.components.buySell.getBSCard(state),
checkoutDotComApiKey: selectors.components.buySell.getCheckoutApiKey(state),
domains: selectors.core.walletOptions.getDomains(state).getOrElse({
walletHelper: 'https://wallet-helper.blockchain.com'
} as WalletOptionsType['domains']),
mobilePaymentMethod: selectors.components.buySell.getBSMobilePaymentMethod(state),
orderR: selectors.components.buySell.getBSOrder(state),
origin: selectors.components.buySell.getOrigin(state),
providerDetailsR: selectors.components.buySell.getBSProviderDetails(state)
})

const mapDispatchToProps = (dispatch) => ({
buySellActions: bindActionCreators(actions.components.buySell, dispatch)
})

const connector = connect(mapStateToProps, mapDispatchToProps)

type OwnProps = {
handleClose: () => void
}

export type SuccessStateType = {
domains: WalletOptionsType['domains']
order?: BSOrderType
providerDetails?: ProviderDetailsType
}

export type Props = OwnProps & ConnectedProps<typeof connector>

export default connector(ThreeDSHandlerCheckoutDotCom)
export default ThreeDSHandlerCheckoutDotCom
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react'
import { useSelector } from 'react-redux'
import styled from 'styled-components'

import { getDomains } from '@core/redux/walletOptions/selectors'
import { Icon } from 'blockchain-info-components'
import { FlyoutWrapper } from 'components/Flyout'

import { SuccessStateType } from '.'

const CustomFlyoutWrapper = styled(FlyoutWrapper)`
height: 100%;
`
Expand All @@ -16,27 +16,28 @@ const Iframe = styled.iframe`
margin-top: 16px;
`

const Success = (props: Props) => {
const Success = ({ handleBack, paymentLink }: Props) => {
const domains = useSelector(getDomains).getOrElse({
walletHelper: 'https://wallet-helper.blockchain.com'
})
return (
<CustomFlyoutWrapper>
<>
<Icon
cursor
name='arrow-left'
size='20px'
color='grey600'
role='button'
onClick={props.handleBack}
/>
<Iframe
sandbox='allow-forms allow-scripts allow-same-origin'
src={`${props.domains.walletHelper}/wallet-helper/checkoutdotcom/#/paymentLink/${props.paymentLink}`}
/>
</>
<Icon
cursor
name='arrow-left'
size='20px'
color='grey600'
role='button'
onClick={handleBack}
/>
<Iframe
sandbox='allow-forms allow-scripts allow-same-origin'
src={`${domains.walletHelper}/wallet-helper/checkoutdotcom/#/paymentLink/${paymentLink}`}
/>
</CustomFlyoutWrapper>
)
}

type Props = SuccessStateType & { handleBack: () => void; paymentLink: string }
type Props = { handleBack: () => void; paymentLink: string }

export default Success
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ class BuySell extends PureComponent<Props, State> {
)}
{this.props.step === '3DS_HANDLER_CHECKOUTDOTCOM' && (
<FlyoutChild>
<ThreeDSHandlerCheckoutDotCom {...this.props} handleClose={this.handleClose} />
<ThreeDSHandlerCheckoutDotCom />
</FlyoutChild>
)}
{this.props.step === '3DS_HANDLER_STRIPE' && (
Expand Down
Loading