Commit dc349fce authored by Dmytro Zavgorodniy's avatar Dmytro Zavgorodniy

[RNA-761] Add CartHOC

parent 2671390e
import React, { Component } from 'react'
import { InteractionManager } from 'react-native'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { debounce, reduce, toNumber, isNil } from 'lodash'
import hoistStatics from 'hoist-non-react-statics'
import { updateStoreCartProductCount } from 'tipsi_api/actions'
import { Router } from 'tipsi-router'
import {
metaSelector,
userSelector,
createStoreSelector,
createStoreCartSelector,
createInventorySelector,
} from 'tipsi_api/selectors'
import { modifyStoreCart, loadStoreCart } from '../actions'
import { createModifiedStoreCartSelector } from '../selectors'
const getStoreId = (state, props) => props.storeId
const getInventoryId = (state, props) => props.inventoryId
const mapStateToProps = createSelector(
userSelector,
metaSelector,
createStoreSelector(getStoreId),
createStoreCartSelector(getStoreId),
createModifiedStoreCartSelector(getStoreId),
createInventorySelector(getInventoryId),
({ user }, meta, { store }, { isLoading, order, orderProducts }, storeCart, { inventory }) => {
const modifiedStoreCartCounts = reduce(storeCart, (memo, count) => memo + count, 0)
const modifiedOrderCount = modifiedStoreCartCounts + orderProducts.reduce(
(memo, { count, inventory: { id } }) => isNil(storeCart[id]) ? memo + count : memo,
0
)
const result = {
user,
store,
order,
inventory,
orderProducts,
modifiedOrderCount,
modifiedStoreCart: storeCart,
isLoadingStoreCart: isLoading,
orderCount: order ? order.total_count : 0,
storeCartStatuses: meta.storeCartInventory.fetchStatus,
}
return result
}
)
const mapDispatchToProps = { modifyStoreCart, loadStoreCart, updateStoreCartProductCount }
export default function CartHOC(WrappedComponent) {
class Wrapper extends Component {
static propTypes = {
// props
storeId: PropTypes.number.isRequired,
inventoryId: PropTypes.number,
// map state to props
user: PropTypes.object,
store: PropTypes.object,
order: PropTypes.object,
inventory: PropTypes.object,
orderProducts: PropTypes.array.isRequired,
modifiedOrderCount: PropTypes.number.isRequired,
modifiedStoreCart: PropTypes.object.isRequired,
isLoadingStoreCart: PropTypes.bool.isRequired,
orderCount: PropTypes.number.isRequired,
storeCartStatuses: PropTypes.object.isRequired,
// map dispatch to props
modifyStoreCart: PropTypes.func.isRequired,
loadStoreCart: PropTypes.func.isRequired,
updateStoreCartProductCount: PropTypes.func.isRequired,
}
static defaultProps = {
// props
inventoryId: undefined,
// map state to props
user: undefined,
store: undefined,
order: undefined,
inventory: undefined,
}
componentDidMount() {
this.loadStoreCart()
}
componentWillReceiveProps(nextProps) {
const isUserSignIn = !this.props.user && nextProps.user
if (isUserSignIn) {
this.loadStoreCart()
}
}
loadStoreCart = () => {
InteractionManager.runAfterInteractions(() => {
if (!this.props.isLoadingStoreCart && !this.props.order && this.props.user) {
this.props.loadStoreCart(this.props.storeId)
}
})
}
modifyStoreCart = async (inventoryId, count) => {
await this.props.modifyStoreCart(this.props.storeId, { inventoryId, count })
}
updateStoreCart = () => {
const products = reduce(this.props.modifiedStoreCart, (memo, count, inventoryIdKey) => (
memo.concat([{ inventory_id: toNumber(inventoryIdKey), count }])
), [])
if (products.length > 0) {
this.props.updateStoreCartProductCount(this.props.storeId, products)
}
}
debounceUpdateStoreCart = debounce(this.updateStoreCart, 1000)
handleAddInventoryToCart = async (inventoryId, count = 1) => {
if (!this.props.user) {
Router.showModal(null, Router.routes.login, {
config: { navigationBar: { visible: false } },
})
return
}
await this.modifyStoreCart(inventoryId, count)
this.updateStoreCart()
}
handleUpdateInventoryInCart = async (inventoryId, count) => {
await this.modifyStoreCart(inventoryId, count)
this.debounceUpdateStoreCart()
}
handleRemoveInventoryFromCart = async (inventoryId) => {
await this.modifyStoreCart(inventoryId, 0)
this.updateStoreCart()
}
handleOpenCart = () => {
Router.push(null, Router.routes.cart, { storeId: this.props.storeId })
}
render() {
return (
<WrappedComponent
{...this.props}
addInventoryToCart={this.handleAddInventoryToCart}
updateInventoryInCart={this.handleUpdateInventoryInCart}
removeInventoryFromCart={this.handleRemoveInventoryFromCart}
openCart={this.handleOpenCart}
/>
)
}
}
return connect(mapStateToProps, mapDispatchToProps)(hoistStatics(Wrapper, WrappedComponent))
}
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