@ecomplus/storefront-components
Version:
Vue components for E-Com Plus Storefront
179 lines (166 loc) • 4.14 kB
JavaScript
import {
i19add,
i19seeMore,
i19weRecommendToYou
} from '@ecomplus/i18n'
import {
i18n,
recommendedIds as getRecommendedIds
} from '@ecomplus/utils'
import { graphs } from '@ecomplus/client'
import EcomSearch from '@ecomplus/search-engine'
import ecomCart from '@ecomplus/shopping-cart'
import { isMobile } from '@ecomplus/storefront-twbs'
import addIdleCallback from './helpers/add-idle-callback'
import ProductCard from '../ProductCard.vue'
export default {
name: 'RecommendedItems',
components: {
ProductCard
},
props: {
pageSize: {
type: Number,
default: !isMobile ? 4 : 2
},
sortOrder: {
type: String,
default: 'sales'
},
canLoadMore: {
type: Boolean,
default: true
},
rowClassName: {
type: String,
default: 'row no-gutters'
},
colClassName: {
type: String,
default: 'col-6 col-md-4 col-lg-3'
},
productCardProps: {
type: Object,
default () {
return {
isSmall: true,
buyText: i18n(i19add),
installmentsOption: {},
discountOption: {}
}
}
},
ecomCart: {
type: Object,
default () {
return ecomCart
}
},
productIds: {
type: Array,
default () {
return []
}
},
defaultMatchType: {
type: String,
default: (typeof window === 'object' && window.ecomRecommendationsType) || 'recommended'
}
},
data () {
return {
ecomSearch: new EcomSearch()
.mergeFilter({
range: {
quantity: {
gt: 0
}
}
})
.mergeFilter({
term: {
available: true
}
}),
pageNumber: 1,
items: []
}
},
computed: {
i19seeMore: () => i18n(i19seeMore),
i19weRecommendToYou: () => i18n(i19weRecommendToYou)
},
methods: {
fetchItems () {
delete this.ecomSearch.dsl.aggs
this.ecomSearch.setPageNumber(this.pageNumber).fetch().then(() => {
this.items = this.items.concat(this.ecomSearch.getItems())
this.totalCount = this.ecomSearch.getTotalCount()
if (this.totalCount) {
this.$emit('recommend-items', {
items: this.items,
totalCount: this.totalCount
})
}
}).finally(() => {
this.$emit('fetched')
})
}
},
created () {
const fetchRecommendations = (matchType = this.defaultMatchType) => {
const promises = []
const items = this.ecomCart.data.items.sort((a, b) => a.quantity > b.quantity ? -1 : 1)
for (let i = 0; i < items.length && i <= 4; i++) {
promises.push(graphs({ url: `/products/${items[i].product_id}/${matchType}.json` }))
}
Promise.allSettled(promises).then(results => {
const productIds = []
results.forEach(({ status, value }) => {
if (status === 'fulfilled') {
getRecommendedIds(value.data).forEach(productId => {
if (
!productIds.includes(productId) &&
!this.ecomCart.data.items.find(item => item.product_id === productId)
) {
productIds.push(productId)
}
})
}
})
if (productIds.length) {
this.ecomSearch.setProductIds(productIds.slice(0, 24))
this.fetchItems()
} else if (matchType === 'recommended') {
fetchRecommendations('related')
}
})
}
if (this.productIds.length) {
this.ecomSearch.setProductIds(this.productIds)
this.totalCount = this.items.length
this.fetchItems()
} else {
addIdleCallback(() => {
fetchRecommendations()
})
}
},
watch: {
pageSize: {
handler (pageSize) {
this.ecomSearch.setPageSize(pageSize)
},
immediate: true
},
sortOrder: {
handler (sortOrder) {
this.ecomSearch.setSortOrder(sortOrder)
},
immediate: true
},
pageNumber () {
this.fetchItems()
}
}
}