@mezereon/ui-shopify
Version:
Shopify UI components for Mezereon Search & Filter
225 lines (209 loc) • 6.69 kB
JavaScript
import { mapState, mapGetters } from 'vuex'
import mz from '@mezereon/tracking'
import { convertCurrency, isAbsoluteUrl } from '@/helpers'
export default {
data() {
return {
loading: true,
apiUrl: mz.config.search.url,
searchKey: mz.config.search.key,
cookieless: mz.config.cookieless
}
},
computed: {
...mapState('search', [
'pageId',
'queryId',
'segments',
'keyword',
'page',
'sort',
'pageSize',
'selections',
'filters',
'aggregations',
'hits',
'layout',
'primaryKey',
'context',
'queryParam',
'pagination',
'redirect'
]),
...mapGetters('search', ['getFacetBanners', 'getQuery'])
},
async created() {
const store = this.$store
if (this.$bus) this.$bus.on('run-query', this.doSearch)
store.dispatch('api/setApiUrl', this.apiUrl, { root: true })
store.dispatch('api/setSearchKey', this.searchKey, { root: true })
await this.$store.dispatch('search/loadConfig', {}, { root: true })
// define queryParam and register query state change handler
this.$queryState.setQueryParam(this.queryParam)
this.$queryState.onChange(this.queryStateChange)
// run initial query
this.queryStateChange(this.$queryState.parseUrl())
},
async mounted() {
// initial query is executed only when #mz-app is on the page
const app = document.querySelector('#mz-app')
if (!app) {
this.loading = false
return
}
},
methods: {
pushState(pagination) {
if (pagination.current_page == 1) {
return true
}
if (
pagination.pagingType === 'more' ||
pagination.pagingType == 'infinite'
) {
return false
}
return true
},
queryStateChange(state) {
this.loading = true
// use sort and pageSize from cookies when undefined
if (!this.cookieless || !this.cookieless.sort) {
state.sort = state.sort || this.$cookies.get('sort')
}
state.pageSize = state.pageSize || this.$cookies.get('pageSize')
this.$store.dispatch('search/setState', state, { root: true })
this.runQuery(false)
},
doSearch: function () {
this.runQuery(true)
},
runQuery: function (push) {
const query = {
filter: this.context.filter,
pageUrl: this.context.pageUrl,
pageId: this.pageId,
keyword: this.keyword,
page: this.page,
sort: this.sort,
pageSize: this.pageSize,
filters: this.filters
}
if (this.context.handle) {
query['handle'] = this.context.handle
}
if (this.context.currency) {
query['currency'] = this.context.currency
}
if (this.context.country) {
query['country'] = this.context.country
}
if (this.context.themeId) {
query['themeId'] = this.context.themeId
}
// inject special tags e.g. not-first-page
let tags = this.context.tags || []
if (this.page > 1 && !tags.includes('not-first-page')) {
tags.push('not-first-page')
}
if (this.page == 1 && tags.includes('not-first-page')) {
tags = tags.filter((tag) => tag !== 'not-first-page')
}
const context = {
visitId: mz ? mz.getVisitId() : '',
visitorId: mz ? mz.getVisitorId() : '',
tags
}
this.$store
.dispatch('search/runQuery', { query, context }, { root: true })
.then(() => {
// hide loader
this.loading = false
// push to history
if (push) {
this.$queryState.push(this.getQuery())
}
if (this.pushState(this.pagination)) {
if (this.$scrollTo) {
if (mz && mz.config && mz.config.scroll) {
if (!mz.config.scroll.disabled) {
this.$scrollTo(
mz.config.scroll.element || 'body',
mz.config.scroll.duration || 300
)
}
} else {
this.$scrollTo(300)
}
}
}
// update title tag
if (this.context.tags && this.context.tags.includes('search')) {
if (this.keyword) {
document.title = `${this.keyword} - ${this.context.shopName}`
} else {
document.title = `${this.context.pageTitle} - ${this.context.shopName}`
}
}
if (push) {
convertCurrency('.money')
// emit after-query event needed for custom handlers i.e. custom multi-currency
if (this.$bus) this.$bus.emit('after-query')
} else {
// emit after-initial-query event needed for custom handlers i.e. custom multi-currency
if (this.$bus) this.$bus.emit('after-initial-query')
}
if (this.$bus) this.$bus.emit('lazy-load-reset')
const self = this
this.$nextTick(() => {
if (self.$bus) self.$bus.emit('after-update')
// trigger quick view update (qikify)
if (document) {
document.dispatchEvent(new CustomEvent('qview-grid-updated'))
}
})
if (mz && mz.track && this.hits) {
// retrieve top 10 unique ids from results for ML
const uids = []
for (let i = 0; i < 10 && i < this.hits.items.length; i++) {
uids.push(this.hits.items[i].item[this.hits.primaryKey])
}
const banners = []
if (this.hits.banners) {
for (const [k, v] of Object.entries(this.hits.banners)) {
if (v === null) {
continue
}
banners.push({ zone: k, id: v.id })
}
}
mz.track('query', {
queryId: this.queryId,
query: query,
segments: this.segments,
context: context,
total: this.hits.total,
banners: banners,
uids: uids,
redirect: this.redirect
})
}
if (this.redirect) {
let redirect = this.redirect
if (isAbsoluteUrl(redirect)) {
window.location.replace(redirect)
return
}
if (mz && mz.context && mz.context.root) {
redirect = `${mz.context.root}${redirect}`
}
window.location.replace(redirect)
return
}
})
.catch(() => {
this.loading = false
})
}
}
}