@ecomplus/storefront-components 1.0.0-beta.17 → 1.0.0-beta.171
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1224 -131
- package/README.md +9 -4
- package/all.js +3 -1
- package/dist/1.storefront-components.min.js +2 -0
- package/dist/1.storefront-components.min.js.map +1 -0
- package/dist/2.storefront-components.min.js +5 -0
- package/dist/2.storefront-components.min.js.map +1 -0
- package/dist/3.storefront-components.min.js +5 -0
- package/dist/3.storefront-components.min.js.map +1 -0
- package/dist/storefront-components.min.js +33 -12
- package/dist/storefront-components.min.js.map +1 -1
- package/package.json +19 -14
- package/src/APagination.vue +2 -0
- package/src/AShare.vue +2 -0
- package/src/AccountAddresses.vue +3 -0
- package/src/AccountForm.vue +3 -0
- package/src/AccountPoints.vue +3 -0
- package/src/BuyTogether.vue +3 -0
- package/src/EarnPointsProgress.vue +3 -0
- package/src/ItemCustomizations.vue +2 -0
- package/src/KitProductVariations.vue +3 -0
- package/src/PointsApplier.vue +2 -0
- package/src/ProductQuickview.vue +3 -0
- package/src/QuantitySelector.vue +3 -0
- package/src/RecommendedItems.vue +3 -0
- package/src/ShippingLine.vue +1 -0
- package/src/TheCart.vue +3 -0
- package/src/html/APagination.html +90 -0
- package/src/html/APrices.html +24 -4
- package/src/html/AShare.html +31 -0
- package/src/html/AccountAddresses.html +90 -0
- package/src/html/AccountForm.html +269 -0
- package/src/html/AccountPoints.html +39 -0
- package/src/html/AddressForm.html +9 -7
- package/src/html/BuyTogether.html +60 -0
- package/src/html/CartItem.html +86 -38
- package/src/html/CartQuickview.html +28 -5
- package/src/html/DiscountApplier.html +2 -2
- package/src/html/EarnPointsProgress.html +28 -0
- package/src/html/InputDate.html +1 -1
- package/src/html/InputDocNumber.html +1 -0
- package/src/html/InputPhone.html +1 -1
- package/src/html/InstantSearch.html +3 -3
- package/src/html/ItemCustomizations.html +14 -0
- package/src/html/KitProductVariations.html +92 -0
- package/src/html/LoginBlock.html +34 -32
- package/src/html/LoginModal.html +9 -4
- package/src/html/PaymentOption.html +7 -5
- package/src/html/PointsApplier.html +26 -0
- package/src/html/ProductCard.html +56 -8
- package/src/html/ProductGallery.html +21 -3
- package/src/html/ProductQuickview.html +64 -0
- package/src/html/ProductVariations.html +30 -3
- package/src/html/QuantitySelector.html +85 -0
- package/src/html/RecommendedItems.html +48 -0
- package/src/html/SearchEngine.html +100 -24
- package/src/html/ShippingCalculator.html +53 -3
- package/src/html/ShippingLine.html +5 -2
- package/src/html/TheAccount.html +43 -9
- package/src/html/TheCart.html +156 -0
- package/src/html/TheProduct.html +416 -138
- package/src/js/APagination.js +74 -0
- package/src/js/APicture.js +27 -7
- package/src/js/APrices.js +80 -41
- package/src/js/AShare.js +83 -0
- package/src/js/AccountAddresses.js +192 -0
- package/src/js/AccountForm.js +312 -0
- package/src/js/AccountPoints.js +63 -0
- package/src/js/AddressForm.js +80 -35
- package/src/js/BuyTogether.js +246 -0
- package/src/js/CartItem.js +67 -14
- package/src/js/CartQuickview.js +21 -2
- package/src/js/DiscountApplier.js +132 -42
- package/src/js/EarnPointsProgress.js +77 -0
- package/src/js/InputDate.js +8 -8
- package/src/js/InputDocNumber.js +20 -0
- package/src/js/ItemCustomizations.js +10 -0
- package/src/js/KitProductVariations.js +218 -0
- package/src/js/LoginBlock.js +14 -2
- package/src/js/LoginModal.js +17 -4
- package/src/js/PaymentOption.js +28 -1
- package/src/js/PointsApplier.js +110 -0
- package/src/js/ProductCard.js +97 -11
- package/src/js/ProductGallery.js +32 -12
- package/src/js/ProductQuickview.js +72 -0
- package/src/js/ProductVariations.js +76 -19
- package/src/js/QuantitySelector.js +175 -0
- package/src/js/RecommendedItems.js +178 -0
- package/src/js/SearchEngine.js +185 -55
- package/src/js/ShippingCalculator.js +157 -33
- package/src/js/ShippingLine.js +21 -5
- package/src/js/TheAccount.js +87 -6
- package/src/js/TheCart.js +146 -0
- package/src/js/TheProduct.js +387 -43
- package/src/js/helpers/add-idle-callback.js +7 -0
- package/src/js/helpers/check-form-validity.js +3 -0
- package/src/js/helpers/favorite-products.js +24 -0
- package/src/js/helpers/scroll-to-element.js +10 -0
- package/src/js/helpers/sort-apps.js +14 -0
- package/src/js/helpers/wait-storefront-info.js +21 -0
- package/src/scss/APicture.scss +2 -0
- package/src/scss/APrices.scss +13 -1
- package/src/scss/AccountAddresses.scss +27 -0
- package/src/scss/AccountForm.scss +5 -0
- package/src/scss/AccountPoints.scss +17 -0
- package/src/scss/BuyTogether.scss +38 -0
- package/src/scss/CartItem.scss +17 -1
- package/src/scss/EarnPointsProgress.scss +6 -0
- package/src/scss/InstantSearch.scss +1 -0
- package/src/scss/KitProductVariations.scss +72 -0
- package/src/scss/LoginBlock.scss +5 -0
- package/src/scss/PaymentOption.scss +10 -1
- package/src/scss/ProductCard.scss +66 -28
- package/src/scss/ProductGallery.scss +4 -2
- package/src/scss/ProductQuickview.scss +36 -0
- package/src/scss/ProductVariations.scss +20 -4
- package/src/scss/QuantitySelector.scss +39 -0
- package/src/scss/RecommendedItems.scss +28 -0
- package/src/scss/SearchEngine.scss +9 -5
- package/src/scss/ShippingCalculator.scss +30 -1
- package/src/scss/ShippingLine.scss +20 -0
- package/src/scss/TheAccount.scss +4 -0
- package/src/scss/TheCart.scss +54 -0
- package/src/scss/TheProduct.scss +146 -1
- package/webpack.config.js +20 -6
package/src/js/SearchEngine.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
+
i19all,
|
|
3
|
+
i19asOf,
|
|
2
4
|
i19brands,
|
|
3
5
|
i19categories,
|
|
4
6
|
i19clearFilters,
|
|
@@ -9,21 +11,31 @@ import {
|
|
|
9
11
|
i19highestPrice,
|
|
10
12
|
i19itemsFound,
|
|
11
13
|
i19lowestPrice,
|
|
14
|
+
i19name,
|
|
12
15
|
i19noResultsFor,
|
|
13
16
|
i19popularProducts,
|
|
17
|
+
i19price,
|
|
14
18
|
i19refineSearch,
|
|
19
|
+
i19releases,
|
|
15
20
|
i19relevance,
|
|
16
21
|
i19results,
|
|
17
22
|
i19sales,
|
|
18
23
|
i19searchAgain,
|
|
19
24
|
i19searchingFor,
|
|
20
25
|
i19searchOfflineErrorMsg,
|
|
21
|
-
i19sort
|
|
26
|
+
i19sort,
|
|
27
|
+
i19upTo
|
|
22
28
|
} from '@ecomplus/i18n'
|
|
23
29
|
|
|
24
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
i18n,
|
|
32
|
+
formatMoney
|
|
33
|
+
} from '@ecomplus/utils'
|
|
34
|
+
|
|
25
35
|
import lozad from 'lozad'
|
|
26
36
|
import EcomSearch from '@ecomplus/search-engine'
|
|
37
|
+
import { Portal } from '@linusborg/vue-simple-portal'
|
|
38
|
+
import scrollToElement from './helpers/scroll-to-element'
|
|
27
39
|
import ABackdrop from '../ABackdrop.vue'
|
|
28
40
|
import ProductCard from '../ProductCard.vue'
|
|
29
41
|
|
|
@@ -44,6 +56,7 @@ export default {
|
|
|
44
56
|
name: 'SearchEngine',
|
|
45
57
|
|
|
46
58
|
components: {
|
|
59
|
+
Portal,
|
|
47
60
|
ABackdrop,
|
|
48
61
|
ProductCard
|
|
49
62
|
},
|
|
@@ -63,6 +76,7 @@ export default {
|
|
|
63
76
|
isFixedBrands: Boolean,
|
|
64
77
|
isFixedCategories: Boolean,
|
|
65
78
|
defaultSort: String,
|
|
79
|
+
defaultFilters: Object,
|
|
66
80
|
autoFixScore: {
|
|
67
81
|
type: Number,
|
|
68
82
|
default: 0.6
|
|
@@ -79,10 +93,15 @@ export default {
|
|
|
79
93
|
type: Boolean,
|
|
80
94
|
default: true
|
|
81
95
|
},
|
|
96
|
+
loadMoreSelector: String,
|
|
82
97
|
canRetry: {
|
|
83
98
|
type: Boolean,
|
|
84
99
|
default: true
|
|
85
100
|
},
|
|
101
|
+
canShowItems: {
|
|
102
|
+
type: Boolean,
|
|
103
|
+
default: true
|
|
104
|
+
},
|
|
86
105
|
productCardProps: Object,
|
|
87
106
|
gridsData: {
|
|
88
107
|
type: Array,
|
|
@@ -103,6 +122,9 @@ export default {
|
|
|
103
122
|
noResultsTerm: '',
|
|
104
123
|
keepNoResultsTerm: false,
|
|
105
124
|
filters: [],
|
|
125
|
+
priceRange: {},
|
|
126
|
+
priceOptions: [],
|
|
127
|
+
hasSetPriceRange: false,
|
|
106
128
|
lastSelectedFilter: null,
|
|
107
129
|
selectedOptions: {},
|
|
108
130
|
selectedSortOption: null,
|
|
@@ -110,6 +132,7 @@ export default {
|
|
|
110
132
|
lastRequestId: null,
|
|
111
133
|
isScheduled: false,
|
|
112
134
|
isLoadingMore: false,
|
|
135
|
+
mustSkipLoadMore: false,
|
|
113
136
|
hasNetworkError: false,
|
|
114
137
|
popularItems: [],
|
|
115
138
|
hasSetPopularItems: false,
|
|
@@ -119,6 +142,7 @@ export default {
|
|
|
119
142
|
},
|
|
120
143
|
|
|
121
144
|
computed: {
|
|
145
|
+
i19all: () => i18n(i19all),
|
|
122
146
|
i19clearFilters: () => i18n(i19clearFilters),
|
|
123
147
|
i19closeFilters: () => i18n(i19closeFilters),
|
|
124
148
|
i19didYouMean: () => i18n(i19didYouMean),
|
|
@@ -127,8 +151,9 @@ export default {
|
|
|
127
151
|
i19itemsFound: () => i18n(i19itemsFound),
|
|
128
152
|
i19noResultsFor: () => i18n(i19noResultsFor),
|
|
129
153
|
i19popularProducts: () => i18n(i19popularProducts),
|
|
130
|
-
|
|
154
|
+
i19price: () => i18n(i19price),
|
|
131
155
|
i19refineSearch: () => i18n(i19refineSearch),
|
|
156
|
+
i19relevance: () => i18n(i19relevance),
|
|
132
157
|
i19results: () => i18n(i19results),
|
|
133
158
|
i19searchAgain: () => i18n(i19searchAgain),
|
|
134
159
|
i19searchingFor: () => i18n(i19searchingFor),
|
|
@@ -158,6 +183,12 @@ export default {
|
|
|
158
183
|
}, {
|
|
159
184
|
value: 'highest_price',
|
|
160
185
|
label: i18n(i19highestPrice)
|
|
186
|
+
}, {
|
|
187
|
+
value: 'news',
|
|
188
|
+
label: i18n(i19releases)
|
|
189
|
+
}, {
|
|
190
|
+
value: 'slug',
|
|
191
|
+
label: i18n(i19name)
|
|
161
192
|
}
|
|
162
193
|
],
|
|
163
194
|
|
|
@@ -172,7 +203,10 @@ export default {
|
|
|
172
203
|
|
|
173
204
|
isNavVisible () {
|
|
174
205
|
return this.hasSearched && this.isFilterable &&
|
|
175
|
-
(this.isSearching ||
|
|
206
|
+
(this.isSearching ||
|
|
207
|
+
this.totalSearchResults > 8 ||
|
|
208
|
+
this.hasSelectedOptions ||
|
|
209
|
+
this.hasSetPriceRange)
|
|
176
210
|
},
|
|
177
211
|
|
|
178
212
|
isResultsVisible () {
|
|
@@ -181,7 +215,8 @@ export default {
|
|
|
181
215
|
|
|
182
216
|
hasFilters () {
|
|
183
217
|
return this.hasSelectedOptions ||
|
|
184
|
-
this.filters.find(({ options }) => options.length)
|
|
218
|
+
this.filters.find(({ options }) => options.length) ||
|
|
219
|
+
this.hasSetPriceRange
|
|
185
220
|
},
|
|
186
221
|
|
|
187
222
|
suggestedItems () {
|
|
@@ -191,10 +226,18 @@ export default {
|
|
|
191
226
|
loadObserver () {
|
|
192
227
|
return this.canLoadMore && lozad('#search-engine-load-more', {
|
|
193
228
|
load: () => {
|
|
194
|
-
this.
|
|
195
|
-
|
|
229
|
+
if (!this.mustSkipLoadMore) {
|
|
230
|
+
this.mustSkipLoadMore = this.isLoadingMore = true
|
|
231
|
+
this.fetchItems()
|
|
232
|
+
}
|
|
196
233
|
}
|
|
197
234
|
})
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
pageAnchorIndex () {
|
|
238
|
+
const count = this.suggestedItems.length
|
|
239
|
+
const rest = count % this.pageSize
|
|
240
|
+
return (rest === 0 ? count - this.pageSize : count - rest) - 1
|
|
198
241
|
}
|
|
199
242
|
},
|
|
200
243
|
|
|
@@ -208,7 +251,7 @@ export default {
|
|
|
208
251
|
ecomSearch.setPageNumber(this.page + Math.ceil(this.resultItems.length / this.pageSize))
|
|
209
252
|
}
|
|
210
253
|
const fetching = ecomSearch.setPageSize(this.pageSize).fetch()
|
|
211
|
-
.then(
|
|
254
|
+
.then(result => {
|
|
212
255
|
if (this.lastRequestId === requestId) {
|
|
213
256
|
this.hasNetworkError = false
|
|
214
257
|
if (!isPopularItems) {
|
|
@@ -219,6 +262,7 @@ export default {
|
|
|
219
262
|
this.hasSetPopularItems = true
|
|
220
263
|
this.popularItems = ecomSearch.getItems()
|
|
221
264
|
}
|
|
265
|
+
return result
|
|
222
266
|
})
|
|
223
267
|
.catch(err => {
|
|
224
268
|
console.error(err)
|
|
@@ -232,9 +276,15 @@ export default {
|
|
|
232
276
|
})
|
|
233
277
|
.finally(() => {
|
|
234
278
|
this.countOpenRequests--
|
|
235
|
-
this.isLoadingMore
|
|
279
|
+
if (this.isLoadingMore) {
|
|
280
|
+
this.isLoadingMore = false
|
|
281
|
+
this.$nextTick(() => setTimeout(() => {
|
|
282
|
+
this.mustSkipLoadMore = false
|
|
283
|
+
this.loadObserver.observe()
|
|
284
|
+
}, 300))
|
|
285
|
+
}
|
|
236
286
|
})
|
|
237
|
-
this.$emit('fetch', { ecomSearch, fetching })
|
|
287
|
+
this.$emit('fetch', { ecomSearch, fetching, isPopularItems })
|
|
238
288
|
},
|
|
239
289
|
|
|
240
290
|
updateFilters () {
|
|
@@ -256,7 +306,8 @@ export default {
|
|
|
256
306
|
options,
|
|
257
307
|
isSpec
|
|
258
308
|
}
|
|
259
|
-
const optionsList = !this.selectedOptions[filter]
|
|
309
|
+
const optionsList = !this.selectedOptions[filter]
|
|
310
|
+
? []
|
|
260
311
|
: this.selectedOptions[filter]
|
|
261
312
|
.filter(option => options.find(({ key }) => key === option))
|
|
262
313
|
this.$set(this.selectedOptions, filter, optionsList)
|
|
@@ -265,46 +316,75 @@ export default {
|
|
|
265
316
|
}
|
|
266
317
|
addFilter('Brands', this.ecomSearch.getBrands())
|
|
267
318
|
addFilter('Categories', this.ecomSearch.getCategories())
|
|
268
|
-
this.ecomSearch.getSpecs().forEach(({ key, options }
|
|
319
|
+
this.ecomSearch.getSpecs().forEach(({ key, options }) => {
|
|
269
320
|
addFilter(key, options, true)
|
|
270
321
|
})
|
|
271
322
|
this.filters = this.filters.filter((_, i) => updatedFilters.includes(i))
|
|
272
323
|
this.searchFilterId = Date.now()
|
|
273
324
|
},
|
|
274
325
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
326
|
+
updatePriceOptions () {
|
|
327
|
+
this.priceRange = this.ecomSearch.getPriceRange()
|
|
328
|
+
if (Math.round(this.priceRange.min) < Math.round(this.priceRange.avg)) {
|
|
329
|
+
const price1 = Math.ceil(Math.max(this.priceRange.min * 1.5, this.priceRange.avg / 2))
|
|
330
|
+
const price2 = Math.ceil(Math.min(this.priceRange.max / 1.5, this.priceRange.avg * 2))
|
|
331
|
+
if (price1 !== price2) {
|
|
332
|
+
this.priceOptions = [Math.min(price1, price2), Math.max(price1, price2), null]
|
|
333
|
+
.map((max, i, prices) => {
|
|
334
|
+
const min = prices[i - 1]
|
|
335
|
+
return {
|
|
336
|
+
min,
|
|
337
|
+
max,
|
|
338
|
+
label: !min
|
|
339
|
+
? `${i18n(i19upTo)} ${formatMoney(max)}`
|
|
340
|
+
: i < 2
|
|
341
|
+
? `${formatMoney(min)} - ${formatMoney(max)}`
|
|
342
|
+
: `${i18n(i19asOf)} ${formatMoney(min)}`
|
|
343
|
+
}
|
|
344
|
+
})
|
|
345
|
+
return
|
|
292
346
|
}
|
|
293
|
-
})
|
|
294
|
-
if (!this.keepNoResultsTerm) {
|
|
295
|
-
this.noResultsTerm = ''
|
|
296
|
-
} else {
|
|
297
|
-
this.keepNoResultsTerm = false
|
|
298
347
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
348
|
+
this.priceOptions = []
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
handleSuggestions () {
|
|
352
|
+
if (this.term) {
|
|
353
|
+
const { ecomSearch } = this
|
|
354
|
+
const term = this.term.toLowerCase()
|
|
355
|
+
let suggestTerm = term
|
|
356
|
+
let canAutoFix = false
|
|
357
|
+
this.suggestedTerm = ''
|
|
358
|
+
ecomSearch.getTermSuggestions().forEach(({ options, text }) => {
|
|
359
|
+
if (options.length) {
|
|
360
|
+
const opt = options[0]
|
|
361
|
+
const optTerm = opt.text.toLowerCase()
|
|
362
|
+
if (
|
|
363
|
+
!this.totalSearchResults &&
|
|
364
|
+
this.autoFixScore > 0 &&
|
|
365
|
+
opt.score >= this.autoFixScore &&
|
|
366
|
+
optTerm.indexOf(term) === -1
|
|
367
|
+
) {
|
|
368
|
+
canAutoFix = true
|
|
369
|
+
}
|
|
370
|
+
suggestTerm = suggestTerm.replace(new RegExp(text, 'i'), optTerm)
|
|
371
|
+
}
|
|
372
|
+
})
|
|
373
|
+
if (!this.keepNoResultsTerm) {
|
|
374
|
+
this.noResultsTerm = ''
|
|
304
375
|
} else {
|
|
305
|
-
this.
|
|
376
|
+
this.keepNoResultsTerm = false
|
|
377
|
+
}
|
|
378
|
+
if (suggestTerm !== term) {
|
|
379
|
+
if (canAutoFix) {
|
|
380
|
+
this.noResultsTerm = term
|
|
381
|
+
this.keepNoResultsTerm = true
|
|
382
|
+
this.$emit('update:term', suggestTerm)
|
|
383
|
+
} else {
|
|
384
|
+
this.suggestedTerm = suggestTerm
|
|
385
|
+
}
|
|
386
|
+
ecomSearch.history.shift()
|
|
306
387
|
}
|
|
307
|
-
ecomSearch.history.shift()
|
|
308
388
|
}
|
|
309
389
|
},
|
|
310
390
|
|
|
@@ -315,6 +395,17 @@ export default {
|
|
|
315
395
|
? this.resultItems.concat(ecomSearch.getItems())
|
|
316
396
|
: ecomSearch.getItems()
|
|
317
397
|
this.updateFilters()
|
|
398
|
+
if (!this.hasSearched && this.defaultFilters) {
|
|
399
|
+
for (const filter in this.defaultFilters) {
|
|
400
|
+
const options = this.defaultFilters[filter]
|
|
401
|
+
if (Array.isArray(options)) {
|
|
402
|
+
options.forEach(option => this.setFilterOption(filter, option, true))
|
|
403
|
+
} else if (typeof options === 'string') {
|
|
404
|
+
this.setFilterOption(filter, options, true)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
this.updatePriceOptions()
|
|
318
409
|
this.handleSuggestions()
|
|
319
410
|
if (!this.totalSearchResults && this.hasPopularItems && !this.hasSetPopularItems) {
|
|
320
411
|
this.fetchItems(false, true)
|
|
@@ -349,7 +440,8 @@ export default {
|
|
|
349
440
|
|
|
350
441
|
toggleFilters (isVisible) {
|
|
351
442
|
this.isAsideVisible = typeof isVisible === 'boolean'
|
|
352
|
-
? isVisible
|
|
443
|
+
? isVisible
|
|
444
|
+
: !this.isAsideVisible
|
|
353
445
|
},
|
|
354
446
|
|
|
355
447
|
getFilterLabel (filter) {
|
|
@@ -409,23 +501,53 @@ export default {
|
|
|
409
501
|
}
|
|
410
502
|
},
|
|
411
503
|
|
|
504
|
+
handlePriceInputs () {
|
|
505
|
+
const { inputMinPrice, inputMaxPrice } = this.$refs
|
|
506
|
+
const min = Number(inputMinPrice.value) || null
|
|
507
|
+
const max = Number(inputMaxPrice.value) || null
|
|
508
|
+
if ((min && !max) || min <= max) {
|
|
509
|
+
this.setPriceRange(min, max)
|
|
510
|
+
}
|
|
511
|
+
inputMinPrice.value = (min || '')
|
|
512
|
+
inputMaxPrice.value = (max || '')
|
|
513
|
+
},
|
|
514
|
+
|
|
515
|
+
setPriceRange (min, max) {
|
|
516
|
+
if (
|
|
517
|
+
(min && min !== this.priceRange.min) ||
|
|
518
|
+
(max && max !== this.priceRange.max)
|
|
519
|
+
) {
|
|
520
|
+
this.hasSetPriceRange = true
|
|
521
|
+
} else if (this.hasSetPriceRange) {
|
|
522
|
+
this.hasSetPriceRange = false
|
|
523
|
+
} else {
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
this.ecomSearch.setPriceRange(min, max)
|
|
527
|
+
this.scheduleFetch()
|
|
528
|
+
},
|
|
529
|
+
|
|
412
530
|
setFilterOption (filter, option, isSet) {
|
|
413
531
|
const { selectedOptions } = this
|
|
414
532
|
const optionsList = selectedOptions[filter]
|
|
415
|
-
if (
|
|
416
|
-
this.lastSelectedFilter = filter
|
|
417
|
-
optionsList.push(option)
|
|
418
|
-
} else {
|
|
533
|
+
if (optionsList) {
|
|
419
534
|
const optionIndex = optionsList.indexOf(option)
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
535
|
+
if (isSet) {
|
|
536
|
+
if (optionIndex === -1) {
|
|
537
|
+
this.lastSelectedFilter = filter
|
|
538
|
+
optionsList.push(option)
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
if (optionIndex > -1) {
|
|
542
|
+
optionsList.splice(optionIndex, 1)
|
|
543
|
+
}
|
|
544
|
+
if (!optionsList.length && this.lastSelectedFilter === filter) {
|
|
545
|
+
this.lastSelectedFilter = null
|
|
546
|
+
}
|
|
425
547
|
}
|
|
548
|
+
this.updateSearchFilter(filter)
|
|
549
|
+
this.scheduleFetch()
|
|
426
550
|
}
|
|
427
|
-
this.updateSearchFilter(filter)
|
|
428
|
-
this.scheduleFetch()
|
|
429
551
|
},
|
|
430
552
|
|
|
431
553
|
clearFilters () {
|
|
@@ -442,7 +564,11 @@ export default {
|
|
|
442
564
|
setSortOrder (sort) {
|
|
443
565
|
this.selectedSortOption = sort
|
|
444
566
|
this.ecomSearch.setSortOrder(sort)
|
|
445
|
-
this.
|
|
567
|
+
if (this.page > 1) {
|
|
568
|
+
this.page = 1
|
|
569
|
+
} else {
|
|
570
|
+
this.scheduleFetch()
|
|
571
|
+
}
|
|
446
572
|
}
|
|
447
573
|
},
|
|
448
574
|
|
|
@@ -465,7 +591,11 @@ export default {
|
|
|
465
591
|
isSearching (isSearching) {
|
|
466
592
|
if (!isSearching && this.loadObserver) {
|
|
467
593
|
this.$nextTick(() => {
|
|
468
|
-
this.
|
|
594
|
+
if (!this.mustSkipLoadMore) {
|
|
595
|
+
this.loadObserver.observe()
|
|
596
|
+
} else {
|
|
597
|
+
setTimeout(() => scrollToElement(this.$refs.pageAnchor[0], 40), 100)
|
|
598
|
+
}
|
|
469
599
|
})
|
|
470
600
|
}
|
|
471
601
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
i19add$1ToEarn,
|
|
2
3
|
i19calculateShipping,
|
|
4
|
+
i19freeShipping,
|
|
3
5
|
i19zipCode
|
|
4
6
|
} from '@ecomplus/i18n'
|
|
5
7
|
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
} from '@ecomplus/utils'
|
|
12
14
|
|
|
13
15
|
import { modules } from '@ecomplus/client'
|
|
16
|
+
import sortApps from './helpers/sort-apps'
|
|
14
17
|
import CleaveInput from 'vue-cleave-component'
|
|
15
18
|
import ShippingLine from '../ShippingLine.vue'
|
|
16
19
|
|
|
@@ -25,6 +28,7 @@ const reduceItemBody = itemOrProduct => {
|
|
|
25
28
|
'sku',
|
|
26
29
|
'name',
|
|
27
30
|
'quantity',
|
|
31
|
+
'inventory',
|
|
28
32
|
'currency_id',
|
|
29
33
|
'currency_symbol',
|
|
30
34
|
'price',
|
|
@@ -75,26 +79,62 @@ export default {
|
|
|
75
79
|
default () {
|
|
76
80
|
return {}
|
|
77
81
|
}
|
|
82
|
+
},
|
|
83
|
+
skipAppIds: Array,
|
|
84
|
+
shippingAppsSort: {
|
|
85
|
+
type: Array,
|
|
86
|
+
default () {
|
|
87
|
+
return window.ecomShippingApps || []
|
|
88
|
+
}
|
|
78
89
|
}
|
|
79
90
|
},
|
|
80
91
|
|
|
81
92
|
data () {
|
|
82
93
|
return {
|
|
83
94
|
localZipCode: null,
|
|
95
|
+
localShippedItems: [],
|
|
96
|
+
amountSubtotal: null,
|
|
84
97
|
shippingServices: [],
|
|
85
98
|
selectedService: null,
|
|
86
|
-
|
|
99
|
+
hasPaidOption: false,
|
|
100
|
+
freeFromValue: null,
|
|
101
|
+
isScheduled: false,
|
|
102
|
+
retryTimer: null,
|
|
103
|
+
isWaiting: false,
|
|
104
|
+
hasCalculated: false
|
|
87
105
|
}
|
|
88
106
|
},
|
|
89
107
|
|
|
90
108
|
computed: {
|
|
109
|
+
i19add$1ToEarn: () => i18n(i19add$1ToEarn),
|
|
91
110
|
i19calculateShipping: () => i18n(i19calculateShipping),
|
|
92
111
|
i19zipCode: () => i18n(i19zipCode),
|
|
112
|
+
i19freeShipping: () => i18n(i19freeShipping).toLowerCase(),
|
|
93
113
|
|
|
94
114
|
cleaveOptions () {
|
|
95
115
|
return this.countryCode === 'BR'
|
|
96
116
|
? { blocks: [5, 3], delimiter: '-' }
|
|
97
117
|
: { blocks: [30] }
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
freeFromPercentage () {
|
|
121
|
+
return this.hasPaidOption && this.amountSubtotal < this.freeFromValue
|
|
122
|
+
? Math.round(this.amountSubtotal * 100 / this.freeFromValue)
|
|
123
|
+
: null
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
productionDeadline () {
|
|
127
|
+
let maxDeadline = 0
|
|
128
|
+
this.shippedItems.forEach(item => {
|
|
129
|
+
if (item.quantity && item.production_time) {
|
|
130
|
+
const { days, cumulative } = item.production_time
|
|
131
|
+
const itemDeadline = cumulative ? days * item.quantity : days
|
|
132
|
+
if (itemDeadline > maxDeadline) {
|
|
133
|
+
maxDeadline = itemDeadline
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
return maxDeadline
|
|
98
138
|
}
|
|
99
139
|
},
|
|
100
140
|
|
|
@@ -105,56 +145,115 @@ export default {
|
|
|
105
145
|
this.$emit('update:zip-code', this.localZipCode)
|
|
106
146
|
},
|
|
107
147
|
|
|
108
|
-
parseShippingOptions (shippingResult = [], isRetry) {
|
|
148
|
+
parseShippingOptions (shippingResult = [], isRetry = false) {
|
|
149
|
+
this.freeFromValue = null
|
|
109
150
|
this.shippingServices = []
|
|
110
|
-
let canRetry
|
|
111
151
|
if (shippingResult.length) {
|
|
112
152
|
shippingResult.forEach(appResult => {
|
|
113
153
|
const { validated, error, response } = appResult
|
|
114
|
-
if (validated
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
154
|
+
if (!validated || error) {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if (
|
|
158
|
+
this.skipAppIds &&
|
|
159
|
+
this.skipAppIds.includes(appResult.app_id) &&
|
|
160
|
+
shippingResult.filter(({ app_id: appId }) => !this.skipAppIds.includes(appId)).length
|
|
161
|
+
) {
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
response.shipping_services.forEach(service => {
|
|
165
|
+
this.shippingServices.push({
|
|
166
|
+
app_id: appResult.app_id,
|
|
167
|
+
...service
|
|
120
168
|
})
|
|
121
|
-
}
|
|
122
|
-
|
|
169
|
+
})
|
|
170
|
+
const freeShippingFromValue = response.free_shipping_from_value
|
|
171
|
+
if (
|
|
172
|
+
freeShippingFromValue &&
|
|
173
|
+
(!this.freeFromValue || this.freeFromValue > freeShippingFromValue)
|
|
174
|
+
) {
|
|
175
|
+
this.freeFromValue = freeShippingFromValue
|
|
123
176
|
}
|
|
124
177
|
})
|
|
125
178
|
if (!this.shippingServices.length) {
|
|
126
|
-
if (
|
|
179
|
+
if (!isRetry) {
|
|
127
180
|
this.fetchShippingServices(true)
|
|
181
|
+
} else {
|
|
182
|
+
this.scheduleRetry()
|
|
128
183
|
}
|
|
129
184
|
} else {
|
|
185
|
+
this.shippingServices = this.shippingServices.sort((a, b) => {
|
|
186
|
+
const priceDiff = a.shipping_line.total_price - b.shipping_line.total_price
|
|
187
|
+
return priceDiff < 0
|
|
188
|
+
? -1
|
|
189
|
+
: priceDiff > 0
|
|
190
|
+
? 1
|
|
191
|
+
: a.shipping_line.delivery_time && b.shipping_line.delivery_time &&
|
|
192
|
+
a.shipping_line.delivery_time.days < b.shipping_line.delivery_time.days
|
|
193
|
+
? -1
|
|
194
|
+
: 1
|
|
195
|
+
})
|
|
130
196
|
this.setSelectedService(0)
|
|
197
|
+
this.hasPaidOption = Boolean(this.shippingServices.find(service => {
|
|
198
|
+
return service.shipping_line.total_price || service.shipping_line.price
|
|
199
|
+
}))
|
|
200
|
+
if (Array.isArray(this.shippingAppsSort) && this.shippingAppsSort.length) {
|
|
201
|
+
this.shippingServices = sortApps(this.shippingServices, this.shippingAppsSort)
|
|
202
|
+
}
|
|
131
203
|
}
|
|
132
204
|
}
|
|
133
205
|
},
|
|
134
206
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
...this.shippingData,
|
|
141
|
-
to: {
|
|
142
|
-
zip: this.localZipCode,
|
|
143
|
-
...this.shippingData.to
|
|
207
|
+
scheduleRetry (timeout = 10000) {
|
|
208
|
+
clearTimeout(this.retryTimer)
|
|
209
|
+
this.retryTimer = setTimeout(() => {
|
|
210
|
+
if (this.localZipCode && !this.shippingServices.length && this.shippedItems.length) {
|
|
211
|
+
this.fetchShippingServices(true)
|
|
144
212
|
}
|
|
213
|
+
}, timeout)
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
fetchShippingServices (isRetry) {
|
|
217
|
+
if (!this.isScheduled) {
|
|
218
|
+
this.isScheduled = true
|
|
219
|
+
setTimeout(() => {
|
|
220
|
+
this.isScheduled = false
|
|
221
|
+
const { storeId } = this
|
|
222
|
+
let url = '/calculate_shipping.json'
|
|
223
|
+
if (this.skipAppIds && this.skipAppIds.length) {
|
|
224
|
+
url += '?skip_ids='
|
|
225
|
+
this.skipAppIds.forEach((appId, i) => {
|
|
226
|
+
if (i > 0) url += ','
|
|
227
|
+
url += `${appId}`
|
|
228
|
+
})
|
|
229
|
+
}
|
|
230
|
+
const method = 'POST'
|
|
231
|
+
const data = {
|
|
232
|
+
...this.shippingData,
|
|
233
|
+
to: {
|
|
234
|
+
zip: this.localZipCode,
|
|
235
|
+
...this.shippingData.to
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (this.localShippedItems.length) {
|
|
239
|
+
data.items = this.localShippedItems
|
|
240
|
+
data.subtotal = this.amountSubtotal
|
|
241
|
+
}
|
|
242
|
+
this.isWaiting = true
|
|
243
|
+
modules({ url, method, storeId, data })
|
|
244
|
+
.then(({ data }) => this.parseShippingOptions(data.result, isRetry))
|
|
245
|
+
.catch(err => {
|
|
246
|
+
if (!isRetry) {
|
|
247
|
+
this.scheduleRetry(4000)
|
|
248
|
+
}
|
|
249
|
+
console.error(err)
|
|
250
|
+
})
|
|
251
|
+
.finally(() => {
|
|
252
|
+
this.hasCalculated = true
|
|
253
|
+
this.isWaiting = false
|
|
254
|
+
})
|
|
255
|
+
}, this.hasCalculated ? 150 : 50)
|
|
145
256
|
}
|
|
146
|
-
if (this.shippedItems.length) {
|
|
147
|
-
data.items = this.shippedItems.map(reduceItemBody)
|
|
148
|
-
const itemsToSubtotal = (subtotal, item) => subtotal + getPrice(item) * item.quantity
|
|
149
|
-
data.subtotal = data.items.reduce(itemsToSubtotal, 0)
|
|
150
|
-
}
|
|
151
|
-
this.isWaiting = true
|
|
152
|
-
modules({ url, method, storeId, data })
|
|
153
|
-
.then(({ data }) => this.parseShippingOptions(data.result, isRetry))
|
|
154
|
-
.catch(console.error)
|
|
155
|
-
.finally(() => {
|
|
156
|
-
this.isWaiting = false
|
|
157
|
-
})
|
|
158
257
|
},
|
|
159
258
|
|
|
160
259
|
submitZipCode () {
|
|
@@ -174,6 +273,27 @@ export default {
|
|
|
174
273
|
},
|
|
175
274
|
|
|
176
275
|
watch: {
|
|
276
|
+
shippedItems: {
|
|
277
|
+
handler () {
|
|
278
|
+
setTimeout(() => {
|
|
279
|
+
this.localShippedItems = this.shippedItems.map(reduceItemBody)
|
|
280
|
+
const { amountSubtotal } = this
|
|
281
|
+
this.amountSubtotal = this.shippedItems.reduce((subtotal, item) => {
|
|
282
|
+
return subtotal + getPrice(item) * item.quantity
|
|
283
|
+
}, 0)
|
|
284
|
+
if (
|
|
285
|
+
this.hasCalculated &&
|
|
286
|
+
(this.canSelectServices || amountSubtotal !== this.amountSubtotal ||
|
|
287
|
+
(!this.shippingServices.length && !this.isWaiting))
|
|
288
|
+
) {
|
|
289
|
+
this.fetchShippingServices()
|
|
290
|
+
}
|
|
291
|
+
}, 50)
|
|
292
|
+
},
|
|
293
|
+
deep: true,
|
|
294
|
+
immediate: true
|
|
295
|
+
},
|
|
296
|
+
|
|
177
297
|
localZipCode (zipCode) {
|
|
178
298
|
if (this.countryCode === 'BR' && zipCode.replace(/\D/g, '').length === 8) {
|
|
179
299
|
this.submitZipCode()
|
|
@@ -189,6 +309,10 @@ export default {
|
|
|
189
309
|
immediate: true
|
|
190
310
|
},
|
|
191
311
|
|
|
312
|
+
skipAppIds () {
|
|
313
|
+
this.fetchShippingServices()
|
|
314
|
+
},
|
|
315
|
+
|
|
192
316
|
shippingResult: {
|
|
193
317
|
handler (result) {
|
|
194
318
|
if (result.length) {
|