Commit 903be1dd authored by Denis Sedura's avatar Denis Sedura

[RNA-785] Extract Store details. Store tabs wine, beers, spirits, other

parent 761e4fba
......@@ -30,6 +30,7 @@ function enhanceItemDetails(Wine, Drink, AddToCartView) {
storeId: PropTypes.number,
user: PropTypes.object,
item: PropTypes.object.isRequired,
inventoryId: PropTypes.number,
inventory: PropTypes.object,
createUserFavorite: PropTypes.func.isRequired,
removeUserFavorite: PropTypes.func.isRequired,
......@@ -39,6 +40,7 @@ function enhanceItemDetails(Wine, Drink, AddToCartView) {
user: undefined,
storeId: undefined,
inventory: undefined,
inventoryId: undefined,
}
static details = {
......
......@@ -28,8 +28,7 @@ function enhanceNearbyStoreList(ComposedComponent) {
)
handleRowPress = (storeId, title) => (
// this.props.navigator.push('Store', { storeId, title })
console.log('Push Store', title)
Router.push(null, Router.routes.store, { title, storeId })
)
handleSubmitEditing = query => (
......
......@@ -20,11 +20,8 @@ export function enhanceSearchResultList(ComposedComponent) {
search: PropTypes.func.isRequired,
searchInventory: PropTypes.func.isRequired,
clearPaginationCache: PropTypes.func.isRequired,
results: PropTypes.array.isRequired,
inventoryLoaded: PropTypes.bool.isRequired,
regularSearchIsLoading: PropTypes.bool.isRequired,
inventorySearchIsLoading: PropTypes.bool.isRequired,
currentLocation: PropTypes.object.isRequired,
}
static defaultProps = {
......@@ -167,13 +164,12 @@ export function enhanceSearchResultList(ComposedComponent) {
)
handleSectionPress = (storeId, title, tabIndex) => (
// this.props.navigator.push('Store', {
// title,
// storeId,
// tabIndex,
// searchQuery: this.props.searchPageQuery,
// })
console.log('Push Store')
Router.push(null, Router.routes.store, {
title,
storeId,
tabIndex,
searchQuery: this.props.searchPageQuery,
})
)
render() {
......
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 {
createSearchInventoryListSelector,
createStoreSelector,
createStoreCartOrderSelector,
entitiesSelector,
} from 'tipsi_api/selectors'
import { searchInventory, clearPaginationCache } from 'tipsi_api/actions'
import { STORE_SEARCH_KEY } from '../../actions'
import { createStoreCartStatusSelector } from '../../selectors/storeCarts'
import { convertFiltersToQuery } from '../../reducers/storeFilters'
function enhanceDrinkList(ComposedComponent, drinkType, listLabel) {
class Wrapper extends Component {
static propTypes = {
storeId: PropTypes.number.isRequired,
storeDrinks: PropTypes.object.isRequired,
isLoading: PropTypes.bool.isRequired,
inventoryType: PropTypes.string.isRequired,
itemsCount: PropTypes.number.isRequired,
loadStoreDrinks: PropTypes.func.isRequired,
clearSearchCache: PropTypes.func.isRequired,
nextPage: PropTypes.number,
isTabLoaded: PropTypes.bool.isRequired,
searchQuery: PropTypes.string,
storeFilters: PropTypes.object,
store: PropTypes.object,
orderProducts: PropTypes.object,
storeCart: PropTypes.object.isRequired,
orderProductsInventory: PropTypes.object,
onAddToCartPress: PropTypes.func.isRequired,
onRemoveFromCartPress: PropTypes.func.isRequired,
}
static defaultProps = {
nextPage: undefined,
searchQuery: undefined,
storeFilters: undefined,
store: undefined,
orderProductsInventory: {},
orderProducts: {},
}
clearSearchCache = () => {
this.props.clearSearchCache()
}
handleOnRowPress = (inventoryId) => {
const { storeId, inventoryType } = this.props
Router.push(null, Router.routes.itemDetails, {
storeId,
inventoryId,
inventoryType,
itemType: 'drink',
title: 'Drink Details',
detailsType: 'inventory',
})
}
loadStoreDrinks = (page) => {
const { storeId, searchQuery: query, storeFilters } = this.props
const fields = {
fts: 'id,inventory,rank,drink',
inventory: 'id,price,drink,in_stock,value_pick,staff_pick,special_price,' +
'special_price_on,special_price_amount,unit_size,pack_size,external_id',
drink: 'id,name,label_url,country,tag',
country: 'name',
tag: 'name',
}
if (this.lastSearchInventory) {
this.lastSearchInventory.cancel()
}
const filters = convertFiltersToQuery(storeFilters)
const props = { storeId, fields, query, ...filters }
if (page) {
props.page = page
}
this.lastSearchInventory = this.props.loadStoreDrinks(props)
}
handleEndReached = () => {
if (this.props.nextPage) {
this.loadStoreDrinks(this.props.nextPage)
}
}
render() {
return (
<ComposedComponent
{...this.props}
loadStoreDrinks={this.loadStoreDrinks}
clearSearchCache={this.clearSearchCache}
handleEndReached={this.handleEndReached}
handleOnRowPress={this.handleOnRowPress}
/>
)
}
}
const getStoreId = (state, props) => props.storeId
const selectorsWithStoreId = createSelector(
createStoreSelector(getStoreId),
createStoreCartOrderSelector(getStoreId),
createStoreCartStatusSelector(getStoreId),
({ store }, order = {}, storeCart) => ({ store, order, storeCart })
)
const drinkKey = `drinks/${drinkType}`
const mapPropsToKey = props => `${props.storeId}/${drinkKey}`
const mapStateToProps = createSelector(
(state, props) => ({ state, props }),
selectorsWithStoreId,
createSearchInventoryListSelector((state, props) => mapPropsToKey(props)),
entitiesSelector,
({ state, props }, { store, order, storeCart }, { result, ...rest }, entities) => ({
...rest,
store,
storeCart,
searchQuery: state.searchQueries[STORE_SEARCH_KEY],
storeFilters: state.storeFilters[mapPropsToKey(props)],
orderProducts: entities.orderProducts,
orderProductsInventory: state.relations.orderProductsInventory[order.id],
itemsCount: result.length,
inventoryType: drinkType,
storeDrinks: {
[listLabel]: result,
},
})
)
const mapDispatchToProps = (dispatch, props) => ({
loadStoreDrinks: params => dispatch(
searchInventory({ ...params, drinkType, key: mapPropsToKey(props) })
),
clearSearchCache: () => dispatch(
clearPaginationCache({ searchInventory: mapPropsToKey(props) })
),
})
return connect(mapStateToProps, mapDispatchToProps)(Wrapper)
}
export default enhanceDrinkList
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Router } from 'tipsi-router'
import { isEqual } from 'lodash'
import { connect } from 'react-redux'
import { createSelector } from 'reselect'
import { userSelector, createStoreCartOrderSelector } from 'tipsi_api/selectors'
import {
loadStoreCart,
addInventoryToCart,
removeInventoryFromCart,
} from '../../actions/storeCarts'
import { createStoreCartStatusSelector } from '../../selectors'
import tabItems from '../../constants/storeTabItems'
import enhanceStoreSearchInput from './StoreSearchInput'
function enhanceStore(ComposedComponent, StoreSearchInput) {
const StoreSearchInputHOC = enhanceStoreSearchInput(StoreSearchInput)
class Wrapper extends Component {
static propTypes = {
// route props
title: PropTypes.string.isRequired,
storeId: PropTypes.number.isRequired,
searchQuery: PropTypes.string,
tabIndex: PropTypes.number,
// map state to props
user: PropTypes.object,
order: PropTypes.object,
isLoadingCart: PropTypes.bool.isRequired,
// map dispatch to props
loadStoreCart: PropTypes.func.isRequired,
addInventoryToCart: PropTypes.func.isRequired,
removeInventoryFromCart: PropTypes.func.isRequired,
}
static defaultProps = {
searchQuery: '',
tabIndex: 0,
user: undefined,
order: undefined,
}
state = {
tabIndex: this.props.tabIndex,
filtersVisible: false,
}
componentWillMount() {
Router.setTitle(this.props.title)
}
shouldComponentUpdate(nextProps, nextState) {
return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState)
}
loadStoreCart = () => {
if (!this.props.isLoadingCart) {
this.props.loadStoreCart({ storeId: this.props.storeId })
}
}
handleChangeTab = (tabIndex) => {
// updateRouteParams(this.props.navigator, { title: tabItems[tabIndex].title })
// Router.setTitle(tabItems[tabIndex].title)
this.setState({ tabIndex })
}
handleShowFilters = () => (
this.setState({ filtersVisible: true })
)
handleHideFilters = () => (
this.setState({ filtersVisible: false })
)
handleCheckoutButtonOnPress = () => {
// const { order: { id: orderId }, navigation } = this.props
// const navigatorApp = navigation.getNavigator('app')
// navigatorApp.push('Cart', { orderId })
console.log('Show cart')
}
addInventoryToCart = (inventoryId) => {
if (!this.props.user) {
Router.showModal(null, Router.routes.login, {
config: { navigationBar: { visible: false } },
})
return
}
this.props.addInventoryToCart({ storeId: this.props.storeId, inventoryId })
}
removeInventoryFromCart = inventoryId => (
this.props.removeInventoryFromCart({ storeId: this.props.storeId, inventoryId })
)
render() {
const StoreTabView = Router.routes.storeTabView.component
return (
<ComposedComponent
{...this.props}
{...this.state}
StoreSearchInputHOC={StoreSearchInputHOC}
StoreTabView={StoreTabView}
handleCheckoutButtonOnPress={this.handleCheckoutButtonOnPress}
handleChangeTab={this.handleChangeTab}
addInventoryToCart={this.addInventoryToCart}
removeInventoryFromCart={this.removeInventoryFromCart}
handleShowFilters={this.handleShowFilters}
handleHideFilters={this.handleHideFilters}
/>
)
}
}
const mapStateToProps = createSelector(
userSelector,
createStoreCartStatusSelector((state, props) => props.storeId),
createStoreCartOrderSelector((state, props) => props.storeId),
({ user }, { isLoadingCart }, order = {}) => ({ user, order, isLoadingCart })
)
const mapDispatchToProps = { loadStoreCart, addInventoryToCart, removeInventoryFromCart }
return connect(mapStateToProps, mapDispatchToProps)(Wrapper)
}
export default enhanceStore
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { debounce } from 'lodash'
import { changeSearchQuery, clearSearchQuery, STORE_SEARCH_KEY } from '../../actions'
function enhanceStoreSearchInput(ComposedComponent) {
class Wrapper extends Component {
static propTypes = {
query: PropTypes.string,
changeSearchQuery: PropTypes.func.isRequired,
clearSearchQuery: PropTypes.func.isRequired,
}
static defaultProps = {
query: '',
testId: 'storeSearchInput',
}
state = {
query: this.props.query,
}
componentWillUnmount() {
this.props.clearSearchQuery({ keys: STORE_SEARCH_KEY })
}
handleValueChange = (query) => {
this.setState({ query })
this.debouncedChangeQuery(query)
}
changeQuery = (query) => {
this.props.changeSearchQuery({ query, key: STORE_SEARCH_KEY })
}
debouncedChangeQuery = debounce(this.changeQuery, 600)
render() {
return (
<ComposedComponent
{...this.props}
{...this.state}
changeQuery={this.changeQuery}
handleValueChange={this.handleValueChange}
/>
)
}
}
return connect(null, { changeSearchQuery, clearSearchQuery })(Wrapper)
}
export default enhanceStoreSearchInput
import React, { Component } from 'react'
import { default as enhanceWineList } from './WineList'
import { default as enhanceDrinkList } from './DrinkList'
const tabs = {
Beer: {
drinkType: 'beer',
listLabel: 'Store Beers',
},
Other: {
drinkType: 'other',
listLabel: 'Other Drinks',
},
Spirits: {
drinkType: 'spirits',
listLabel: 'Store Spirits',
},
}
function enhanceStoreTabView(ComposedComponent) {
return class Wrapper extends Component {
tabContainer = {}
tabView = (routeKey, component) => {
if (routeKey === 'Wine') {
const wineListHOC = this.tabContainer[routeKey] || enhanceWineList(component)
this.tabContainer[routeKey] = wineListHOC
return wineListHOC
}
const tab = tabs[routeKey]
const drinkListHOC = this.tabContainer[routeKey] ||
enhanceDrinkList(component, tab.drinkType, tab.listLabel)
this.tabContainer[routeKey] = drinkListHOC
return drinkListHOC
}
render() {
return (
<ComposedComponent
{...this.props}
tabView={this.tabView}
/>
)
}
}
}
export default enhanceStoreTabView
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Router } from 'tipsi-router'
import { searchInventory, clearPaginationCache } from 'tipsi_api/actions'
import { wineListSelector } from '../../selectors'
import { convertFiltersToQuery } from '../../reducers/storeFilters'
function enhanceWineList(ComposedComponent) {
class Wrapper extends Component {
static propTypes = {
storeId: PropTypes.number.isRequired,
searchInventory: PropTypes.func.isRequired,
clearPaginationCache: PropTypes.func.isRequired,
nextPage: PropTypes.number,
searchQuery: PropTypes.string,
storeFilters: PropTypes.object,
}
static defaultProps = {
nextPage: undefined,
searchQuery: undefined,
storeFilters: undefined,
store: undefined,
orderProductsInventory: {},
orderProducts: {},
}
loadStoreWines = (page) => {
const { storeId, searchQuery: query, storeFilters } = this.props
const fields = {
inventory: 'id,price,wine,value_pick,staff_pick,special_price,' +
'special_price_on,special_price_amount,in_stock,pack_size,external_id',
wine: 'id,name,vintage,region,sub_regions,label_url,pro_rating,' +
'vintage_note,style_scoring',
fts: 'id,inventory,rank,wine',
country: 'id,name',
store: 'id,name',
pro_rating: 'shortcut,rating,name,rating_description',
winery: 'id,name',
producer: 'id,name,description',
region: 'name',
sub_region: 'name',
style: 'id,name,score',
}
if (this.lastSearchInventory) {
this.lastSearchInventory.cancel()
}
const key = `${storeId}/wines`
const filters = convertFiltersToQuery(storeFilters)
const props = { storeId, fields, key, query, ...filters }
if (page) {
props.page = page
}
this.lastSearchInventory = this.props.searchInventory(props)
}
clearSearchCache = () => {
this.props.clearPaginationCache({
searchInventory: `${this.props.storeId}/wines`,
})
}
handleOnRowPress = wineId => (
Router.push(null, Router.routes.itemDetails, {
storeId: this.props.storeId,
inventoryId: wineId,
itemType: 'wine',
title: 'Wine Details',
detailsType: 'inventory',
})
)
handleEndReached = () => {
if (this.props.nextPage) {
this.loadStoreWines(this.props.nextPage)
}
}
render() {
return (
<ComposedComponent
{...this.props}
loadStoreWines={this.loadStoreWines}
clearSearchCache={this.clearSearchCache}
handleEndReached={this.handleEndReached}
handleOnRowPress={this.handleOnRowPress}
/>
)
}
}
const mapDispatchToProps = { searchInventory, clearPaginationCache }
return connect(wineListSelector, mapDispatchToProps)(Wrapper)
}
export default enhanceWineList
export { default as enhanceStore} from './Store'
......@@ -6,3 +6,6 @@ export { enhanceItemDetails } from './ItemDetails'
export { enhanceLabelPreview } from './LabelPreview'
export { enhanceMangeReview } from './ManageReview'
export { enhanceItemReviews } from './ItemReviews'
export { enhanceStore } from './Store'
export { default as enhanceWineList } from './Store/WineList'
export { default as enhanceStoreTabView } from './Store/StoreTabView'
import { reduce, keys } from 'lodash'
import {
enhanceAppComponent,
enhanceStore,
enhanceStoreTabView,
enhanceWineList,
enhanceItemDetails,
enhanceLabelPreview,
enhanceMangeReview,
......@@ -14,6 +17,14 @@ const routesMap = {
path: '/',
component: enhanceAppComponent,
},
store: {
path: 'store',
component: enhanceStore,
},
storeTabView: {
path: 'storeTabView',
component: enhanceStoreTabView,
},
search: {
path: 'search',
component: enhanceSearch,
......
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