Commit 0d53087f authored by Denis Sedura's avatar Denis Sedura

[RNA-761] Wrap Itemdetails, AddToCartView

parent 47f3f35a
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { denormalize } from 'normalizr'
import { createSelector } from 'reselect'
import { isEqual } from 'lodash'
import {
entitiesSelector,
paginationsSelector,
createStoreSelector,
createStoreCartOrderSelector,
createInventorySelector,
userSelector,
} from 'tipsi_api/selectors'
import { Schemas } from 'tipsi_api/middleware'
import {
loadStoreCart,
addInventoryToCart,
increaseInventoryCount,
decreaseInventoryCount,
} from '../../actions/storeCarts'
import { createCartStatusSelector } from '../../selectors'
export function enhanceAddToCartView(ComposedComponent) {
class Wrapper extends Component {
static propTypes = {
user: PropTypes.object,
inventoryType: PropTypes.string,
storeId: PropTypes.number.isRequired,
inventoryId: PropTypes.number.isRequired,
store: PropTypes.object,
inventory: PropTypes.object,
order: PropTypes.object,
orderProduct: PropTypes.object,
loadStoreCart: PropTypes.func.isRequired,
addInventoryToCart: PropTypes.func.isRequired,
increaseInventoryCount: PropTypes.func.isRequired,
decreaseInventoryCount: PropTypes.func.isRequired,
isLoadingCart: PropTypes.bool,
isAddingToCart: PropTypes.bool,
isIncreasingCount: PropTypes.bool,
isDecreasingCount: PropTypes.bool,
isRemovingFromCart: PropTypes.bool,
}
static defaultProps = {
user: undefined,
inventoryType: 'other',
store: undefined,
inventory: undefined,
order: undefined,
orderProduct: undefined,
isLoadingCart: false,
isAddingToCart: false,
isIncreasingCount: false,
isDecreasingCount: false,
isRemovingFromCart: false,
}
shouldComponentUpdate(nextProps) {
return !isEqual(this.props, nextProps)
}
loadStoreCart = () => {
const { storeId, inventoryId, isLoadingCart } = this.props
if (!isLoadingCart) {
this.props.loadStoreCart({ storeId, inventoryId })
}
}
addToCart = () => {
const { storeId, inventoryId, isAddingToCart, user } = this.props
if (!user) {
// this.props.navigation.showModal('Login')
console.log('No user')
return
}
if (!isAddingToCart) {
this.props.addInventoryToCart({ storeId, inventoryId })
}
}
increaseCount = () => {
const { storeId, inventoryId, isIncreasingCount } = this.props
if (!isIncreasingCount) {
this.props.increaseInventoryCount({ storeId, inventoryId })
}
}
decreaseCount = () => {
const { storeId, inventoryId, isDecreasingCount, isRemovingFromCart } = this.props
const loading = isDecreasingCount || isRemovingFromCart
if (!loading) {
this.props.decreaseInventoryCount({ storeId, inventoryId })
}
}
countForOrder = (order) => {
let count = 0
if (order && order.total_count) {
count = order.total_count
}
return count
}
countForOrderProduct = (orderProduct) => {
let count = 0
if (orderProduct && orderProduct.count) {
count = orderProduct.count
}
return count
}
handleAddToCartButtonOnPress = () => {
const { isLoadingCart, isAddingToCart } = this.props
const loading = isLoadingCart || isAddingToCart
if (!loading) {
this.addToCart()
}
}
handleCartButtonOnPress = () => {
// const { order: { id: orderId }, navigation } = this.props
// const navigatorApp = navigation.getNavigator('app')
// navigatorApp.push('Cart', { orderId })
}
handleRemoveButtonOnPress = () => {
this.decreaseCount()
}
handleAddButtonOnPress = () => {
this.increaseCount()
}
render() {
console.log('props', this.props)
return (
<ComposedComponent
{...this.props}
countForOrder={this.countForOrder}
countForOrderProduct={this.countForOrderProduct}
handleCartButtonOnPress={this.handleCartButtonOnPress}
handleAddButtonOnPress={this.handleAddButtonOnPress}
handleRemoveButtonOnPress={this.handleRemoveButtonOnPress}
handleAddToCartButtonOnPress={this.handleAddToCartButtonOnPress}
/>
)
}
}
const getStoreId = (state, props) => props.storeId
const inventoryIdSelector = (state, props) => props.inventoryId
const createStoreCartSelector = createSelector(
createStoreCartOrderSelector(getStoreId),
paginationsSelector,
entitiesSelector,
(order = {}, paginations, entities) => {
const { ids = [] } = paginations.orderProducts[order.id] || {}
const orderProducts = denormalize(ids, Schemas.ORDER_PRODUCT_ARRAY, entities)
return { order, orderProducts }
}
)
const createStoreInventoryCartSelector = createSelector(
createStoreCartSelector,
createInventorySelector(inventoryIdSelector),
inventoryIdSelector,
({ order, orderProducts }, { inventory }, inventoryId) => ({
order,
inventory,
orderProduct: orderProducts.find(product => product.inventory.id === inventoryId),
})
)
const mapStateToProps = createSelector(
createStoreSelector(getStoreId),
createCartStatusSelector(getStoreId, inventoryIdSelector),
createStoreInventoryCartSelector,
userSelector,
({ store }, status, { order, inventory, orderProduct }, { user }) => ({
store,
order,
orderProduct,
inventory,
user,
...status,
})
)
return connect(mapStateToProps, {
loadStoreCart,
addInventoryToCart,
increaseInventoryCount,
decreaseInventoryCount,
})(Wrapper)
}
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import {
loadInventoryItem,
loadWine,
loadDrink,
createUserFavorite,
removeUserFavorite,
} from 'tipsi_api/actions'
import { createSelector } from 'reselect'
import {
createInventorySelector,
createWineSelector,
createDrinkSelector,
userSelector,
metaSelector,
} from 'tipsi_api/selectors'
import { itemFormatter } from '../../utils/formatters'
import { enhanceAddToCartView } from './AddToCartView'
function enhanceItemDetails(Wine, Drink, AddToCartView) {
const AddToCartViewHOC = enhanceAddToCartView(AddToCartView)
class Wrapper extends Component {
static propTypes = {
itemType: PropTypes.oneOf(['wine', 'drink']).isRequired,
}
static details = {
wine: Wine,
drink: Drink,
}
render() {
const DetailsComponent = Wrapper.details[this.props.itemType]
return (
<DetailsComponent {...this.props}>
<AddToCartViewHOC
storeId={this.props.storeId}
inventoryId={this.props.inventory.id}
inventoryType={this.props.itemType}
/>
</DetailsComponent>
)
}
}
const WINE_FIELDS = {
wine: 'id,name,vintage,country,region,sub_regions,label_url,type,pro_rating,' +
'vintage_note,style_scoring,varietals,winemakers_note,producer,designation,' +
'avg_review,user_review,user_favorite',
country: 'name,description,image_url',
region: 'name,description,image_url',
sub_region: 'name,description,image_url',
pro_rating: 'shortcut,rating,name,rating_description',
style: 'id,name,score',
varietal: 'description,name',
designation: 'name,description',
avg_review: 'value,count',
user_review: 'id,wine_id,value,text',
user_favorite: 'id,wine_id',
}
const DRINK_FIELDS = {
drink: 'id,name,description,drink_type,producer,country,label_url,tag,' +
'avg_review,user_review,user_favorite',
country: 'name,description,image_url',
producer: 'id,name,description',
tag: 'name',
avg_review: 'value,count',
user_review: 'id,drink_id,value,text',
user_favorite: 'id,drink_id',
}
const WINE_INVENTORY_FIELDS = {
inventory: 'id,price,note,value_pick,staff_pick,special_price,' +
'special_price_on,special_price_amount,in_stock,wine,unit_size,pack_size,external_id',
...WINE_FIELDS,
}
const DRINK_INVENTORY_FIELDS = {
inventory: 'id,price,note,value_pick,staff_pick,special_price,' +
'special_price_on,special_price_amount,in_stock,drink,unit_size,pack_size,external_id',
...DRINK_FIELDS,
}
const inventoryIdSelector = (state, props) => props.inventoryId
const itemTypeSelector = (state, props) => props.itemType
const itemIdSelector = (state, props) => props.itemId
const createInventoryItemSelector = inventoryItemSelector => createSelector(
[userSelector, itemTypeSelector, inventoryItemSelector, metaSelector],
({ user }, itemType, { inventory, item, isLoading }, meta) => {
const { userFavorite } = itemFormatter(itemType, item)
const favoriteId = userFavorite ? userFavorite.id : 'new'
return {
user,
inventory,
item,
isLoading,
isFavoriteLoading: !!meta.favorites.fetchStatus[favoriteId],
}
}
)
const itemWineSelector = createInventoryItemSelector(
createSelector(
createWineSelector(itemIdSelector),
({ wine = {}, isLoading }) => ({ item: wine, isLoading })
)
)
const itemDrinkSelector = createInventoryItemSelector(
createSelector(
createDrinkSelector(itemIdSelector),
({ drink = {}, isLoading }) => ({ item: drink, isLoading })
)
)
const inventoryWineSelector = createInventoryItemSelector(
createSelector(
createInventorySelector(inventoryIdSelector),
({ inventory = {}, isLoading }) => ({ inventory, item: inventory.wine, isLoading })
)
)
const inventoryDrinkSelector = createInventoryItemSelector(
createSelector(
createInventorySelector(inventoryIdSelector),
({ inventory = {}, isLoading }) => ({ inventory, item: inventory.drink, isLoading })
)
)
const selectors = {
'item-wine': itemWineSelector,
'item-drink': itemDrinkSelector,
'inventory-wine': inventoryWineSelector,
'inventory-drink': inventoryDrinkSelector,
}
const mapStateToProps = (state, { detailsType, itemType }) => (
selectors[`${detailsType}-${itemType}`]
)
const mapDispatchToActions = (dispatch, props) => {
const { detailsType, itemType, inventoryId, itemId } = props
let loadDetails
switch (`${detailsType}-${itemType}`) {
case 'item-wine':
loadDetails = () => loadWine(itemId, WINE_FIELDS)
break
case 'item-drink':
loadDetails = () => loadDrink(itemId, DRINK_FIELDS)
break
case 'inventory-wine':
loadDetails = () => loadInventoryItem(inventoryId, WINE_INVENTORY_FIELDS)
break
case 'inventory-drink':
loadDetails = () => loadInventoryItem(inventoryId, DRINK_INVENTORY_FIELDS)
break
default:
// nothing
}
return bindActionCreators({ loadDetails, createUserFavorite, removeUserFavorite }, dispatch)
}
return connect(mapStateToProps, mapDispatchToActions)(Wrapper)
}
export default enhanceItemDetails
export { default as enhanceItemDetails } from './ItemDetails'
......@@ -2,6 +2,7 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { Router } from 'tipsi-router'
import { mapValues, reduce, groupBy, maxBy } from 'lodash'
import { search, searchInventory, clearPaginationCache } from 'tipsi_api/actions'
import { createSearchListSelector, createSearchInventoryListSelector } from 'tipsi_api/selectors'
......@@ -128,45 +129,41 @@ export function enhanceSearchResultList(ComposedComponent) {
}
handleStoreWineRowPress = ({ storeId, storeWineId: inventoryId }) => (
// this.props.navigator.push('ItemDetails', {
// storeId,
// inventoryId,
// itemType: 'wine',
// title: 'Wine Details',
// detailsType: 'inventory',
// })
console.log('Push ItemDetails')
Router.push(null, Router.routes.itemDetails, {
storeId,
inventoryId,
itemType: 'wine',
title: 'Wine Details',
detailsType: 'inventory',
})
)
handleWineRowPress = ({ wineId: itemId }) => (
// this.props.navigator.push('ItemDetails', {
// itemId,
// itemType: 'wine',
// detailsType: 'item',
// title: 'Wine Details',
// })
console.log('Push ItemDetails')
Router.push(null, Router.routes.itemDetails, {
itemId,
itemType: 'wine',
detailsType: 'item',
title: 'Wine Details',
})
)
handleStoreDrinkRowPress = ({ storeId, storeDrinkId: inventoryId }) => (
// this.props.navigator.push('ItemDetails', {
// storeId,
// inventoryId,
// itemType: 'drink',
// title: 'Drink Details',
// detailsType: 'inventory',
// })
console.log('Push ItemDetails')
Router.push(null, Router.routes.itemDetails, {
storeId,
inventoryId,
itemType: 'drink',
title: 'Drink Details',
detailsType: 'inventory',
})
)
handleDrinkRowPress = ({ drinkId: itemId }) => (
// this.props.navigator.push('ItemDetails', {
// detailsType: 'item',
// itemType: 'drink',
// itemId,
// title: 'Drink Details',
// })
console.log('Push ItemDetails')
Router.push(null, Router.routes.itemDetails, {
detailsType: 'item',
itemType: 'drink',
itemId,
title: 'Drink Details',
})
)
handleSectionPress = (storeId, title, tabIndex) => (
......
......@@ -2,3 +2,4 @@ export { enhanceAppComponent } from './App'
export { enhanceInitialComponent } from './InitialScreen'
export { enhanceAgeConfirmation } from './AgeConfirmation'
export { enhanceMain } from './Main'
export { enhanceItemDetails } from './ItemDetails'
import { reduce, keys } from 'lodash'
import { enhanceAppComponent } from './Screens/App'
import { enhanceAppComponent, enhanceItemDetails } from './Screens'
import { enhanceSearch } from './Screens/Search'
const routesMap = {
......@@ -11,6 +11,10 @@ const routesMap = {
path: 'search',
component: enhanceSearch,
},
itemDetails: {
path: 'itemDetails',
component: enhanceItemDetails,
},
}
export function createRoutes(routes = {}) {
......
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