Commit b4d7433e authored by Dmytro Zavgorodniy's avatar Dmytro Zavgorodniy

[RNA-761] Update Cart HOC

parent 4776003d
import React, { Component } from 'react'
import { Router } from 'tipsi-router'
import PropTypes from 'prop-types'
import { NavigationStyles } from '@expo/ex-navigation'
import stripe from 'tipsi-stripe'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { get } from 'lodash'
import { requestPayment, finalizePayment } from '../../actions'
import { createPaymentSelector } from '../../selectors'
import { defaultDeliveryType } from '../../utils/deliveryTypes'
import getPaymentMethod from '../../utils/getPaymentMethod'
import { CREDIT_CARD } from '../../constants/paymentMethods'
import CartHOC from '../CartHOC'
const getStoreId = (_, props) => props.storeId
const mapStateToProps = createSelector(
createPaymentSelector(getStoreId),
payment => ({
requestPaymentLoading: !!payment.requestPaymentLoading,
finalizePaymentLoading: !!payment.finalizePaymentLoading,
})
)
const mapDispatchToProps = { requestPayment, finalizePayment }
export default function enhanceCart(ComposedComponent) {
return class Wrapper extends Component {
class Wrapper extends Component {
static propTypes = {
// route props
storeId: PropTypes.number.isRequired,
// external props
isFocused: PropTypes.bool.isRequired,
// map state to props
requestPaymentLoading: PropTypes.bool.isRequired,
finalizePaymentLoading: PropTypes.bool.isRequired,
// map dispatch to props
requestPayment: PropTypes.func.isRequired,
finalizePayment: PropTypes.func.isRequired,
// Cart HOC
order: PropTypes.object,
orderProducts: PropTypes.array.isRequired,
modifiedStoreCart: PropTypes.object.isRequired,
isLoadingStoreCart: PropTypes.bool.isRequired,
// storeCartStatuses: PropTypes.object.isRequired,
updateInventoryInCart: PropTypes.func.isRequired,
removeInventoryFromCart: PropTypes.func.isRequired,
}
static defaultProps = {
// Cart HOC
order: undefined,
}
state = {
currentItemIndex: 0,
paymentMethod: CREDIT_CARD,
deliveryType: defaultDeliveryType,
}
componentWillMount() {
Router.setTitle('Shopping Cart')
this.updatePaymentMethod()
}
componentDidMount() {
if (!this.props.storeId) {
throw Error('No storeId provided')
}
}
componentWillReceiveProps(nextProps) {
if (this.props.isFocused !== nextProps.isFocused && nextProps.isFocused) {
this.updatePaymentMethod()
}
}
getProductItem = () => {
const product = this.props.orderProducts[this.state.currentItemIndex] || {}
const inventoryId = product.inventory_id || get(product, 'inventory.id')
const modifiedCount = this.props.modifiedStoreCart[inventoryId]
const currentCount = modifiedCount || product.count
return { product, inventoryId, currentCount }
}
updatePaymentMethod = async () => {
const paymentMethod = await getPaymentMethod()
this.setState({ paymentMethod })
}
itemIndexChanged = (index) => {
this.setState({ currentItemIndex: index })
}
deliveryTypeChanged = deliveryType => (
this.setState({ deliveryType })
)
updateInventoryInCart = (count) => {
const { inventoryId } = this.getProductItem()
this.props.updateInventoryInCart(inventoryId, count)
}
removeInventoryFromCart = () => {
const { inventoryId } = this.getProductItem()
this.props.removeInventoryFromCart(inventoryId)
}
pay = async () => {
const { storeId, order: { id: orderId, code }, isLoadingStoreCart } = this.props
const { deliveryType, paymentMethod } = this.state
if (isLoadingStoreCart) {
return
}
let cardId
if (paymentMethod === CREDIT_CARD) {
try {
cardId = await this.selectCard()
} catch (error) {
// no any error in this case, handle cancel action here
return
}
}
try {
await this.props.requestPayment(storeId, deliveryType)
} catch (error) {
return
}
let title = code
if (paymentMethod === CREDIT_CARD) {
try {
title = (await this.showPaymentDetails(storeId, orderId, cardId)).code
} catch (error) {
// no any error in this case, handle cancel action here
return
}
} else {
try {
title = (await this.props.finalizePayment(storeId, paymentMethod)).code
} catch (error) {
const { TPSErrorDomain, TPSErrorCodeUserCancel } = stripe
const userCanceled = error.domain === TPSErrorDomain &&
error.code === TPSErrorCodeUserCancel
if (!userCanceled) {
if (error.code && error.code === 'incorrectShippingAddress') {
Router.push(null, Router.routes.deliveryZones, { error })
}
}
return
}
}
Router.replace(null, Router.routes.order, { orderId, title })
Router.showModal(
null,
Router.routes.paymentReceipt,
{
orderId,
config: {
styles: {
...NavigationStyles.Fade,
sceneAnimations: props => ({
...NavigationStyles.Fade.sceneAnimations(props),
backgroundColor: 'rgba(0,0,0,0.5)',
shadowOpacity: 0,
opacity: 1,
}),
},
},
}, 1000)
}
selectCard = () => new Promise(async (resolve, reject) => {
try {
const cardId = await this.selectCardPromise()
Router.pop()
resolve(cardId)
} catch (error) {
// no any error in this case, handle cancel action here
Router.pop()
reject()
}
})
selectCardPromise = () => new Promise((resolve, reject) => {
Router.push(null, Router.routes.paymentMethods, {
finishCallback: resolve,
cancelCallback: reject,
})
})
showPaymentDetails = (storeId, orderId, cardId) => new Promise(async (resolve, reject) => {
try {
const order = await this.showPaymentDetailsPromise(storeId, orderId, cardId)
Router.dismissModal()
resolve(order)
} catch (error) {
// no any error in this case, handle cancel action here
Router.dismissModal()
reject()
}
})
showPaymentDetailsPromise = (storeId, orderId, cardId) => new Promise((resolve, reject) => {
Router.showModal(null, Router.routes.paymentDetails, {
storeId,
orderId,
cardId,
finishCallback: resolve,
cancelCallback: reject,
config: {
styles: {
...NavigationStyles.Fade,
sceneAnimations: props => ({
...NavigationStyles.Fade.sceneAnimations(props),
backgroundColor: 'rgba(0,0,0,0.5)',
shadowOpacity: 0,
opacity: 1,
}),
},
},
})
})
render() {
return (
<ComposedComponent {...this.props} />
<ComposedComponent
{...this.props}
currentItemIndex={this.state.currentItemIndex}
paymentMethod={this.state.paymentMethod}
deliveryType={this.state.deliveryType}
order={this.props.order}
orderProducts={this.props.orderProducts}
isLoadingStoreCart={this.props.isLoadingStoreCart}
requestPaymentLoading={this.props.requestPaymentLoading}
finalizePaymentLoading={this.props.finalizePaymentLoading}
getProductItem={this.getProductItem}
updatePaymentMethod={this.updatePaymentMethod}
itemIndexChanged={this.itemIndexChanged}
deliveryTypeChanged={this.deliveryTypeChanged}
updateInventoryInCart={this.updateInventoryInCart}
removeInventoryFromCart={this.removeInventoryFromCart}
pay={this.pay}
/>
)
}
}
return connect(mapStateToProps, mapDispatchToProps)(CartHOC(Wrapper))
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment