Skip to content

Instantly share code, notes, and snippets.

@bhargav2496
Created October 6, 2019 06:16
Show Gist options
  • Save bhargav2496/b641ed2dd7ffb334c2b19d52d8748560 to your computer and use it in GitHub Desktop.
Save bhargav2496/b641ed2dd7ffb334c2b19d52d8748560 to your computer and use it in GitHub Desktop.
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import _ from 'lodash'
import { Trans } from 'react-i18next'
import config from 'config'
import {
ProductGrid, QuickView, FilterDropdown, Pagination, LeftColumn, Spinner,
} from 'components'
import { withRouter } from 'react-router-dom'
import { user_role, component_price } from '../../../domain/configHandler/ssoUrls'
import {
getSubstring,
capsFirst,
handleGetToken,
setBrandFilter,
getBrandFilter,
resetBrandFilter,
setCategoryFilter,
getCategoryFilter,
resetCategoryFilter,
setDeviceFilter,
getDeviceFilter,
resetDeviceFilter,
hasAccesToPrice,
setOfferfilter,
} from '../../../domain/helper'
import ApiService from '../../../services/ApiService'
import CustomApiService from '../../../services/CustomApiService'
import TotalCountApiService from '../../../services/TotalCountApiService'
import { UrlParserForProductListing } from '../../../domain/UrlParser'
import { sellerProductCurrency } from '../../../domain/configHandler/bestSeller'
import {
productPerPage,
noProductFOund,
categoryRouter,
brandRouter,
offerRouter,
defaultProductEndPoint,
customProductEndPoint,
quickView,
categoryJunctionTableEndpint,
offerJunctionTableEndpint,
productPerRow,
totalProductCountText,
selectedProductCountText,
} from '../../../domain/configHandler/productListing'
import {
Rightsidebar, BreadCrumbBar, TotalCount, BreadCrumb, Sort, Row, NoProduct, Leftsidebar,
} from './style'
let sortValue = 'name'
let categoryProductIds = []
let deviceProductIds = []
let offerProductIds = []
let refinedCategory = ''
let refinedBrand = ''
let refinedOffer = ''
let params
let totalProduct = 0
let items
let startProduct
let endProduct
class ProductListing extends PureComponent {
state = {
quickViewIndex: null,
}
startLimit = 0
endLimit = productPerPage()
componentDidMount() {
let loc = ''
/* This is when user manually change from the URL i.e. when URL is not Clicked from Menu */
const manualUrlChange = window.location.href
this.getTotalCountOfProduct()
/* When URL is changed from Menu */
this.props.history.listen((location) => {
loc = UrlParserForProductListing(location.pathname)
if (loc.length > 1) {
this.functionCallHandlerOnUrlChange(loc)
} else {
/* If user clicked on category/offer i.e user wants to see all products of category/offer */
refinedCategory = ''
refinedOffer = ''
refinedBrand = ''
resetCategoryFilter()
resetBrandFilter()
this.loadProduct()
}
})
if (manualUrlChange.length > 0) {
loc = UrlParserForProductListing(manualUrlChange)
if (loc.length > 1) {
this.functionCallHandlerOnUrlChange(loc)
} else {
/* If user clicked on category/offer i.e user wants to see all products of category/offer by hitting URL manually */
refinedCategory = ''
refinedOffer = ''
refinedBrand = ''
resetCategoryFilter()
resetBrandFilter()
this.loadProduct()
}
}
this.loadProduct()
}
/* Based on URL parsing condition function is called */
functionCallHandlerOnUrlChange = (loc) => {
const [firstParam, secondParam] = loc
/* If the url is baseurl/category */
if (firstParam === categoryRouter()) {
refinedCategory = secondParam
refinedOffer = ''
refinedBrand = ''
resetCategoryFilter()
resetBrandFilter()
this.getProductIdByCategoryId(refinedCategory)
/* If the url is baseurl/brand */
} else if (firstParam === brandRouter()) {
refinedCategory = ''
refinedOffer = ''
refinedBrand = secondParam
resetBrandFilter()
resetCategoryFilter()
resetDeviceFilter()
setBrandFilter(refinedBrand)
this.loadProduct()
/* If the url is baseurl/offer */
} else if (firstParam === offerRouter()) {
refinedCategory = ''
refinedOffer = secondParam
refinedBrand = ''
resetBrandFilter()
resetCategoryFilter()
this.getProductIdByOffer()
}
}
/* The custom endpoint is not returning total count by sending meta.
Calling default product service for getting total count */
getTotalCountOfProduct = async () => {
const apiUrl = defaultProductEndPoint()
const token = handleGetToken()
const params = {
access_token: token,
fields: '*.*',
meta: '*',
}
totalProduct = await TotalCountApiService({ url: apiUrl, params })
}
// Calling API for getting data
loadProduct = async () => {
const apiUrl = customProductEndPoint()
/* Filters */
/* If all filters are applied together */
if (
categoryProductIds.length > 0
&& getBrandFilter().length === 0
&& deviceProductIds.length === 0
&& offerProductIds.length === 0
) {
params = this.formCategoryFilterParam()
} else if (
getBrandFilter() === null
|| (getBrandFilter() === ''
&& categoryProductIds.length === 0
&& deviceProductIds.length === 0
&& offerProductIds.length === 0)
) {
params = this.formDefaultParam()
} else if (
(getBrandFilter() !== null && getBrandFilter().length > 0 && getCategoryFilter() === '')
|| (getCategoryFilter() !== '' && getDeviceFilter() === '')
) {
params = this.formBrandFilterParam()
items = await CustomApiService({ url: apiUrl, params })
this.props.onSave(items)
this.setState({
totalProduct: items.length,
})
} else if (
getBrandFilter() !== null
&& (getBrandFilter().length > 0 || getBrandFilter().length === 1)
&& getCategoryFilter().length > 0
&& deviceProductIds.length === 0
) {
params = this.formCategoryAndBrandParam()
items = await CustomApiService({ url: apiUrl, params })
this.props.onSave(items)
} else if (
getBrandFilter() !== null
&& getBrandFilter().length > 0
&& deviceProductIds.length > 0
&& categoryProductIds.length === 0
) {
params = this.formDeviceAndBrandParam()
} else if (offerProductIds.length > 0 && deviceProductIds.length === 0) {
/* If offer is clicked from URL */
params = this.formOfferParam()
items = await CustomApiService({ url: apiUrl, params })
this.props.onSave(items)
} else if (deviceProductIds.length > 0) {
params = this.formDeviceFilterParam()
items = await CustomApiService({ url: apiUrl, params })
this.props.onSave(items)
}
items = await CustomApiService({ url: apiUrl, params })
this.props.onSave(items)
this.setState({
totalProduct: items.length,
})
}
/* default params i.e if no value is selected */
formDefaultParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
meta: '*',
'filter[channel.slug][eq]': user_role(),
offset: this.startLimit,
limit: this.endLimit + 6,
}
return params
}
/* params for all filters */
formAllFilterParam = () => {
params = ''
params = {
// sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[manufacturer.slug][in]': getBrandFilter(),
'filter[id][in]': `${getCategoryFilter()},${getDeviceFilter()}`,
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: this.endLimit,
}
return params
}
/* params for brand filter */
formBrandFilterParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[manufacturer.slug][eq]': getBrandFilter(),
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: 25,
}
return params
}
/* Params for category filter */
formCategoryFilterParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[id][in]': getCategoryFilter(),
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: 25,
}
return params
}
/* Params for device filter */
formDeviceFilterParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[id][in]': getDeviceFilter(),
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: 25,
}
return params
}
/* params for category and brand */
formCategoryAndBrandParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[manufacturer.slug][in]': getBrandFilter(),
'filter[id][in]': getCategoryFilter(),
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: 25,
}
return params
}
/* Param for device and brand */
formDeviceAndBrandParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[id][in]': getDeviceFilter(),
'filter[manufacturer.slug][in]': getBrandFilter(),
'filter[channel.slug][eq]': user_role(),
meta: '*',
offset: this.startLimit,
limit: 25,
}
return params
}
/* Params for offer */
formOfferParam = () => {
params = ''
params = {
sort: sortValue,
access_token: handleGetToken(),
fields: '*.*',
'filter[id][in]': offerProductIds.toString(),
'filter[channel.slug][eq]': user_role(),
offset: this.startLimit,
limit: 25,
}
return params
}
// Method for showing quick view in product grid
quickView = (index) => {
if (quickView() === 'enabled') {
this.setState({
quickViewIndex: index,
})
} else {
this.setState({
quickViewIndex: false,
})
}
}
// Method for removing quick view from product grid
removeQuickViewOnMouseOut = () => {
this.setState({
quickViewIndex: false,
})
}
// Sort product list with dropdown
filterDropdown = async (value) => {
sortValue = value
this.loadProduct()
}
// Get product Id from junction table for category for M2M mapping
getProductIdByCategoryId = async (target) => {
if (target.value) {
setCategoryFilter(target.value)
const apiUrl = categoryJunctionTableEndpint()
const token = handleGetToken()
const params = {
access_token: token,
fields: '*.*',
'filter[category_id.slug][eq]': getCategoryFilter(),
}
const getProductId = await ApiService({ url: apiUrl, params })
const newFilterArray = []
_.map(getProductId, (product) => {
if (
product.product_id.id !== null
&& !categoryProductIds.includes(product.product_id.id)
&& target.checked === true
) {
categoryProductIds.push(product.product_id.id)
} else if (
product.product_id !== null
&& categoryProductIds.includes(product.product_id.id)
&& target.checked === false
) {
newFilterArray.push(product.product_id.id)
} else if (product.product_id !== null) {
categoryProductIds.push(product.product_id.id)
}
})
if (newFilterArray.length > 0 && categoryProductIds.length > 0) {
const intersectionResult = _.intersection(categoryProductIds, newFilterArray)
categoryProductIds = [...intersectionResult]
}
setCategoryFilter(categoryProductIds)
this.loadProduct()
}
if (target) {
setCategoryFilter(target)
const apiUrl = categoryJunctionTableEndpint()
const token = handleGetToken()
const params = {
access_token: token,
fields: '*.*',
'filter[category_id.slug][eq]': getCategoryFilter(),
}
const getProductId = await ApiService({ url: apiUrl, params })
const newFilterArray = []
_.map(getProductId, (product) => {
if (product.product_id.id !== null && !categoryProductIds.includes(product.product_id.id)) {
categoryProductIds.push(product.product_id.id)
} else if (product.product_id !== null && categoryProductIds.includes(product.product_id.id)) {
newFilterArray.push(product.product_id.id)
} else if (product.product_id !== null) {
categoryProductIds.push(product.product_id.id)
}
})
if (newFilterArray.length > 0 && categoryProductIds.length > 0) {
const intersectionResult = _.intersection(categoryProductIds, newFilterArray)
categoryProductIds = [...intersectionResult]
}
setCategoryFilter(categoryProductIds)
this.loadProduct()
}
}
// Get product Id from junction table for offer for M2M mapping
getProductIdByOffer = async () => {
const apiUrl = offerJunctionTableEndpint()
const token = handleGetToken()
const params = {
access_token: token,
fields: '*.*',
'filter[offer_id.slug][in]': refinedOffer,
}
const getProductId = await ApiService({ url: apiUrl, params })
offerProductIds = []
_.map(getProductId, (product) => {
if (product.product_id !== null) {
offerProductIds.push(product.product_id.id)
}
})
setOfferfilter(offerProductIds)
this.loadProduct()
}
// Get product Id from junction table for device for M2M mapping and store it into localstorage
getProductIdByDeviceId = async (target) => {
if (target !== undefined) {
if (target.value.length > 0 && target.checked === true) {
setDeviceFilter(target.value)
}
}
const apiUrl = config.left_filter.end_points.DEVIJUNCPROD
const token = handleGetToken()
const params = {
access_token: token,
fields: '*.*',
// 'filter[channel.slug][eq]': 'ws',
'filter[device_id.name][in]': getDeviceFilter(),
}
const getProductId = await ApiService({ url: apiUrl, params })
const newFilterArray = []
_.map(getProductId, (product) => {
if (product.product_id !== null && !deviceProductIds.includes(product.product_id.id) && target.checked === true) {
deviceProductIds.push(product.product_id.id)
} else if (
product.product_id !== null
&& deviceProductIds.includes(product.product_id.id)
&& target.checked === false
) {
newFilterArray.push(product.product_id.id)
}
})
if (newFilterArray.length > 1 && deviceProductIds.length > 0) {
const intersectionResult = _.intersection(deviceProductIds, newFilterArray)
deviceProductIds = [...intersectionResult]
}
setDeviceFilter(deviceProductIds)
this.loadProduct()
}
/* Page click handler method of pagination */
handlePageChange = (data) => {
const { selected } = data
this.startLimit = Math.ceil(selected * productPerPage())
this.endLimit = Math.ceil(productPerPage())
startProduct = Math.ceil(selected * productPerPage())
endProduct = Math.ceil(startProduct + productPerPage())
this.setState(() => {
this.loadProduct()
})
}
showPrice = (itemvalue, value) => {
if (itemvalue.prices != null && hasAccesToPrice(value, component_price()) === true) {
return itemvalue.prices[0].dealer_price
}
if (hasAccesToPrice(value, component_price()) === false) {
return itemvalue.prices[0].price_rrp
}
if (itemvalue.prices != null && hasAccesToPrice(value, component_price()) === null) {
return (
<div>
<span>
{' '}
RRP
{' '}
{itemvalue.prices[0].dealer_price}
{' '}
{sellerProductCurrency()}
{' '}
/ UVP
{' '}
{itemvalue.prices[0].price_rrp}
{' '}
{sellerProductCurrency()}
{' '}
</span>
</div>
)
}
return <Spinner />
}
render() {
let productItems = null
let pagination
if (typeof this.props.categoryProduct !== 'undefined' && Array.isArray(this.props.categoryProduct)) {
pagination = (
<Pagination
perPage={
this.props.categoryProduct.length > productPerPage() ? productPerPage() : this.props.categoryProduct.length
}
handlePageClick={this.handlePageChange}
data={this.props.categoryProduct}
pageCount={this.state ? this.state.totalProduct / productPerPage() : totalProduct / productPerPage()}
/>
)
productItems = _.map(this.props.categoryProduct, (item, index) => {
const offerFlag = item && item.offer && item.offer[0] ? item.offer[0].status : false
const bsClass = `col-xs-12 col-sm-6 col-md-${productPerRow()} col-lg-${productPerRow()}`
return (
<div className={bsClass} key={index}>
<ProductGrid
eTriggered={this.getFilterValue}
title={getSubstring(item.name, 0, 18)}
price={this.showPrice(item, this.props.useracces.role.acces)}
image={item.images !== null ? item.images[0].thumbnails : 'No image'}
button={<Trans>{capsFirst(config.product_list.button_text)}</Trans>}
productId={item.id}
link={item.id}
currency={config.product_list.currency}
hover={() => this.quickView(index)}
hoverOut={() => this.removeQuickViewOnMouseOut()}
quickViewLink={item.id}
clicked={item}
articleNumber={item.article_number}
strikeOut={item.discount}
createdDate={item.created_on}
dealFlag={offerFlag}
/>
{this.state.quickViewIndex === index ? (
<QuickView
buttonName={capsFirst(config.product_list.quick_view_button_text)}
mouseIn={() => this.quickView(index)}
mouseOut={() => this.removeQuickViewOnMouseOut()}
/>
) : null}
</div>
)
})
} else {
productItems = (
<NoProduct>
{' '}
&apos;
{noProductFOund()}
&apos;
{' '}
</NoProduct>
)
}
return (
<div>
<Leftsidebar>
<LeftColumn
brandClicked={this.loadProduct}
catClicked={event => this.getProductIdByCategoryId(event.target)}
deviceClick={event => this.getProductIdByDeviceId(event.target)}
/>
</Leftsidebar>
<Rightsidebar>
<BreadCrumbBar>
<BreadCrumb>
<TotalCount>
{<Trans>{totalProductCountText()}</Trans>}
: (
{typeof startProduct !== 'undefined' ? startProduct + 1 : 1}
{' - '}
{typeof endProduct !== 'undefined' ? endProduct : this.state.totalProduct}
,
{<Trans>{selectedProductCountText()}</Trans>}
{' '}
{totalProduct !== undefined || totalProduct !== '' || this.state.totalProduct !== ''
? this.state.totalProduct
: totalProduct}
)
</TotalCount>
<Sort>
<FilterDropdown clicked={event => this.filterDropdown(event.target.value)} />
</Sort>
</BreadCrumb>
</BreadCrumbBar>
<Row className="row">{productItems}</Row>
{pagination}
</Rightsidebar>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
categoryProduct: state.categoryProduct.categoryProduct,
useracces: state,
}
}
const mapDispatchToProps = (dispatch) => {
return {
onSave: (categoryProduct) => {
dispatch({
type: 'STORE_CATPRODUCT',
payload: categoryProduct,
})
},
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(withRouter(ProductListing))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment