wickes-css2 2.111.0-develop.5 → 2.111.0-dont-forget-widget.2

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.
Files changed (54) hide show
  1. package/Readme.md +1 -1
  2. package/build/css/pdp-main-before-combine.css +1 -1
  3. package/build/css/pdp-main-non-critical.css +1 -1
  4. package/build/css/pdp-main.css +1 -1
  5. package/build/js/basket.min.js +1 -1
  6. package/build/js/bloomreach-widget.min.js +1 -1
  7. package/build/js/bundle.min.js +1 -1
  8. package/build/js/checkout.min.js +1 -1
  9. package/build/js/emulation.min.js +689 -54
  10. package/build/js/general.bundle.min.js +1 -1
  11. package/build/js/merged-checkout.min.js +1 -1
  12. package/build/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +223 -0
  13. package/build/js/page/bloomreach-widget/bloomreach-widget.js +319 -0
  14. package/build/js/page/{bloomreach-widget.js → bloomreach-widget/complete-your-project-widget.js} +214 -387
  15. package/build/js/page/bloomreach-widget/dont-forget-widget.js +33 -0
  16. package/build/js/page/bloomreach-widget/why-not-add-widget.js +30 -0
  17. package/build/js/pdp.bundle.min.js +1 -1
  18. package/build/js/plp.bundle.min.js +1 -1
  19. package/build/js/project-list.min.js +1 -1
  20. package/package.json +1 -1
  21. package/src/components/bloomreach/complete-card.hbs +4 -32
  22. package/src/components/bloomreach/complete-your-project-skeleton.hbs +21 -0
  23. package/src/components/bloomreach/complete-your-project.hbs +4 -21
  24. package/src/components/bloomreach/why-not-add-card-skeleton.hbs +14 -0
  25. package/src/components/bloomreach/why-not-add-card.hbs +86 -0
  26. package/src/components/bloomreach/why-not-add-content.hbs +41 -0
  27. package/src/components/bloomreach/why-not-add-skeleton.hbs +9 -0
  28. package/src/components/bloomreach/why-not-add.hbs +4 -0
  29. package/src/components/pdp-price-actions.hbs +2 -2
  30. package/src/components/price-block-v2.hbs +2 -0
  31. package/src/components/reviews-rating.hbs +22 -0
  32. package/src/js/components/general/cart-slider.js +5 -0
  33. package/src/js/emulation/bloomreach-widget-loading.js +2 -2
  34. package/src/js/emulation/complete-your-project-loading.js +16 -0
  35. package/src/js/emulation/dont-forget-loading.js +18 -0
  36. package/src/js/emulation/mock.js +611 -3
  37. package/src/js/emulation/why-not-add-loading.js +16 -0
  38. package/src/js/emulation/why-not-add.js +28 -0
  39. package/src/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +223 -0
  40. package/src/js/page/bloomreach-widget/bloomreach-widget.js +319 -0
  41. package/src/js/page/{bloomreach-widget.js → bloomreach-widget/complete-your-project-widget.js} +214 -387
  42. package/src/js/page/bloomreach-widget/dont-forget-widget.js +33 -0
  43. package/src/js/page/bloomreach-widget/why-not-add-widget.js +30 -0
  44. package/src/page_product-details-bloomreach.html +1 -1
  45. package/src/page_product-details-with-global-search-v2.html +2 -1
  46. package/src/page_product-details-with-why-not-add-single.html +131 -0
  47. package/src/scss/components/bloomreach/_bloomreach.scss +3 -0
  48. package/src/scss/components/bloomreach/_complete-card.scss +0 -38
  49. package/src/scss/components/bloomreach/_reviews.scss +60 -0
  50. package/src/scss/components/bloomreach/_why-not-add-card.scss +270 -0
  51. package/src/scss/components/bloomreach/_why-not-add.scss +172 -0
  52. package/src/sitemap.html +10 -4
  53. package/src/components/.DS_Store +0 -0
  54. package/src/js/page/.DS_Store +0 -0
@@ -0,0 +1,223 @@
1
+ import { createLoadingButton } from '../utils/create-loading-button';
2
+
3
+ export function createBloomreachRecommendationCarouselWidget(config) {
4
+ const state = {
5
+ products: [],
6
+ sliders: [],
7
+ loadingButton: null,
8
+ };
9
+
10
+ return {
11
+ ADD_TO_CART_EVENT: config.addToCartEvent || 'addToCart',
12
+
13
+ el: {
14
+ cta: '.why-not-add-card__cta',
15
+ next: '[data-why-not-add-next]',
16
+ pagination: '[data-why-not-add-pagination]',
17
+ prev: '[data-why-not-add-prev]',
18
+ root: '[data-why-not-add]',
19
+ slider: '[data-why-not-add-slider]',
20
+ widgetContainer: config.widgetContainer,
21
+ },
22
+
23
+ skeletonTemplate: config.skeletonTemplate,
24
+
25
+ getContainers() {
26
+ return $(this.el.widgetContainer);
27
+ },
28
+
29
+ hide() {
30
+ this.getContainers().empty().hide();
31
+ },
32
+
33
+ normalizeProducts(payloadData) {
34
+ return Wick.BloomreachWidget.normalizePayload(payloadData)
35
+ .map(function (item) {
36
+ return item.baseProduct || item;
37
+ })
38
+ .filter(function (product) {
39
+ return config.isEligibleProduct ? config.isEligibleProduct(product) : true;
40
+ })
41
+ .slice(0, 5);
42
+ },
43
+
44
+ renderWidget($container, payloadData) {
45
+ const products = this.normalizeProducts(payloadData);
46
+
47
+ if (!products.length) {
48
+ $container.empty().hide();
49
+ return;
50
+ }
51
+
52
+ state.products = products;
53
+
54
+ $container
55
+ .html(
56
+ config.template({
57
+ title: config.title,
58
+ modifier: config.modifier,
59
+ products: products.map(function (product) {
60
+ return {
61
+ ...Wick.BloomreachWidget.getProductRenderData(product),
62
+ addToCartError: config.addToCartError,
63
+ };
64
+ }),
65
+ isSingleProduct: products.length === 1,
66
+ })
67
+ )
68
+ .show();
69
+ },
70
+
71
+ destroySliders() {
72
+ state.sliders.forEach(function (slider) {
73
+ if (slider && slider.destroy) {
74
+ slider.destroy(true, true);
75
+ }
76
+ });
77
+
78
+ state.sliders = [];
79
+ },
80
+
81
+ initSliders($root) {
82
+ this.destroySliders();
83
+
84
+ $root.find(this.el.slider).each((index, sliderEl) => {
85
+ const $slider = $(sliderEl);
86
+ const $widget = $slider.closest(this.el.root);
87
+ const slidesCount = $slider.find('.swiper-slide').length;
88
+
89
+ if (slidesCount <= 1) {
90
+ return;
91
+ }
92
+
93
+ const slider = new Swiper(sliderEl, {
94
+ roundLengths: true,
95
+ slidesPerView: 1,
96
+ spaceBetween: 12,
97
+ watchOverflow: true,
98
+ navigation: {
99
+ nextEl: $widget.find(this.el.next)[0],
100
+ prevEl: $widget.find(this.el.prev)[0],
101
+ disabledClass: 'why-not-add__arrow--disabled',
102
+ },
103
+ pagination: {
104
+ el: $widget.find(this.el.pagination)[0],
105
+ clickable: true,
106
+ renderBullet(index, className) {
107
+ return `<button class="${className}" type="button" aria-label="Go to slide ${
108
+ index + 1
109
+ }"></button>`;
110
+ },
111
+ bulletClass: 'why-not-add__pagination-item',
112
+ bulletActiveClass: 'why-not-add__pagination-item--active',
113
+ },
114
+ });
115
+
116
+ state.sliders.push(slider);
117
+ });
118
+ },
119
+
120
+ setCardAdded($card) {
121
+ const $button = $card.find(this.el.cta);
122
+
123
+ $card.addClass('why-not-add-card--added');
124
+ $button.prop('disabled', true);
125
+ $button.find('i').attr('class', config.successIcon || 'fas fa-check');
126
+ },
127
+
128
+ setCardFailed($card) {
129
+ const $button = $card.find(this.el.cta);
130
+
131
+ $card.addClass('why-not-add-card--failed');
132
+ $button.prop('disabled', true);
133
+ $button.find('i').attr('class', config.failureIcon || 'fas fa-shopping-basket');
134
+ $card.find('.why-not-add-card__error').removeClass('d-none');
135
+ },
136
+
137
+ bindAddToCart($root) {
138
+ $root.off(`click.${config.namespace}`, this.el.cta);
139
+ $root.on(`click.${config.namespace}`, this.el.cta, event => {
140
+ event.preventDefault();
141
+
142
+ const $button = $(event.currentTarget);
143
+ const $card = $button.closest('.why-not-add-card');
144
+ const productCode = $card.attr('data-product-code');
145
+
146
+ if (
147
+ !productCode ||
148
+ $button.prop('disabled') ||
149
+ state.loadingButton.isLoading($button)
150
+ ) {
151
+ return;
152
+ }
153
+
154
+ state.loadingButton.start($button);
155
+
156
+ Wick.BloomreachWidget.dispatchWidgetEvent(this.ADD_TO_CART_EVENT, {
157
+ productCode,
158
+ })
159
+ .then(() => {
160
+ state.loadingButton.stop($button);
161
+
162
+ if (config.disableAfterSuccess) {
163
+ this.setCardAdded($card);
164
+ }
165
+
166
+ if (Wick.MiniBasketSliderFE) {
167
+ Wick.MiniBasketSliderFE.isMiniBasketLoaded = false;
168
+ }
169
+ })
170
+ .catch(() => {
171
+ state.loadingButton.stop($button);
172
+
173
+ if (config.disableAfterFailure) {
174
+ this.setCardFailed($card);
175
+ }
176
+ });
177
+ });
178
+ },
179
+
180
+ bindVatToggle() {
181
+ if (Wick.BloomreachWidget.bindVatToggle) {
182
+ Wick.BloomreachWidget.bindVatToggle(`${config.namespace}VatToggle`);
183
+ }
184
+ },
185
+
186
+ initRenderedWidget($container) {
187
+ const $root = $container.find(this.el.root);
188
+
189
+ if (!$root.length) {
190
+ return;
191
+ }
192
+
193
+ if (!state.loadingButton) {
194
+ state.loadingButton = createLoadingButton({
195
+ text: Wick.BloomreachWidget.el.loadingButtonText,
196
+ loader: Wick.BloomreachWidget.el.loadingButtonLoader,
197
+ });
198
+ }
199
+
200
+ Wick.BloomreachWidget.drawRating($root);
201
+ this.initSliders($root);
202
+ this.bindAddToCart($root);
203
+ this.bindVatToggle();
204
+ Wick.BloomreachWidget.reapplyVatDisplay();
205
+ },
206
+
207
+ init(payloadData) {
208
+ const $containers = this.getContainers();
209
+
210
+ if (!payloadData || !Wick.BloomreachWidget.hasRecommendations(payloadData)) {
211
+ this.hide();
212
+ return;
213
+ }
214
+
215
+ $containers.each((index, container) => {
216
+ const $container = $(container);
217
+
218
+ this.renderWidget($container, payloadData);
219
+ this.initRenderedWidget($container);
220
+ });
221
+ },
222
+ };
223
+ }
@@ -0,0 +1,319 @@
1
+ var Wick = window.Wick || {};
2
+
3
+ import { createEvent } from '../utils/create-event';
4
+ import CompleteYourProjectWidget from './complete-your-project-widget';
5
+ import WhyNotAddWidget from './why-not-add-widget';
6
+ import DontForgetWidget from './dont-forget-widget';
7
+
8
+ Wick.BloomreachWidget = {
9
+ widgets: {},
10
+
11
+ el: {
12
+ loadingButtonText: '.loading-button__text',
13
+ loadingButtonLoader: '.loading-button__loader',
14
+ ratingOverlay: '.rating-overlay',
15
+ starOverlay: '.star-overlay',
16
+ vatInc: '.including-vat-inherit',
17
+ vatExc: '.excluding-vat-inherit',
18
+ },
19
+
20
+ badgeColorMap: {
21
+ blue: '#019ee3',
22
+ gray: '#3e3e3e',
23
+ green: '#9acd32',
24
+ red: '#cf000f',
25
+ yellow: '#f7ca18',
26
+ },
27
+
28
+ getBadgeColor(color) {
29
+ if (!color) {
30
+ return '';
31
+ }
32
+
33
+ return Wick.BloomreachWidget.badgeColorMap[color] || color;
34
+ },
35
+
36
+ getBadge(product) {
37
+ if (!product) {
38
+ return null;
39
+ }
40
+
41
+ const promotion = product.potentialPromotions && product.potentialPromotions[0];
42
+ const promotionAttributes = promotion && promotion.customAttributes;
43
+
44
+ if (promotionAttributes && promotionAttributes.overlayText) {
45
+ return {
46
+ text: promotionAttributes.overlayText,
47
+ textColor: Wick.BloomreachWidget.getBadgeColor(
48
+ promotionAttributes.overlayTextColor
49
+ ),
50
+ color: Wick.BloomreachWidget.getBadgeColor(
51
+ promotionAttributes.overlayBackgroundColor
52
+ ),
53
+ };
54
+ }
55
+
56
+ if (product.badge && product.badge.text) {
57
+ return {
58
+ ...product.badge,
59
+ textColor: Wick.BloomreachWidget.getBadgeColor(product.badge.textColor),
60
+ color: Wick.BloomreachWidget.getBadgeColor(product.badge.color),
61
+ };
62
+ }
63
+
64
+ return product.badge || null;
65
+ },
66
+
67
+ registerWidgets(widgetList) {
68
+ widgetList.forEach(function ({ type, widget }) {
69
+ Wick.BloomreachWidget.widgets[type] = widget;
70
+ });
71
+ },
72
+
73
+ getWidget(type) {
74
+ return Wick.BloomreachWidget.widgets[type];
75
+ },
76
+
77
+ getWidgetContainers(type) {
78
+ const widget = Wick.BloomreachWidget.getWidget(type);
79
+ const selector = widget && widget.el && widget.el.widgetContainer;
80
+
81
+ return selector ? $(selector) : $();
82
+ },
83
+
84
+ showSkeleton(type) {
85
+ const widget = Wick.BloomreachWidget.getWidget(type);
86
+ const $containers = Wick.BloomreachWidget.getWidgetContainers(type);
87
+
88
+ if (!widget || typeof widget.skeletonTemplate !== 'function' || !$containers.length) {
89
+ return;
90
+ }
91
+
92
+ $containers.each(function () {
93
+ $(this).html(widget.skeletonTemplate()).show();
94
+ });
95
+ },
96
+
97
+ init(type, payloadData) {
98
+ const widget = Wick.BloomreachWidget.getWidget(type);
99
+
100
+ if (!widget || typeof widget.init !== 'function') {
101
+ return;
102
+ }
103
+
104
+ widget.init(payloadData, Wick.BloomreachWidget);
105
+ },
106
+
107
+ normalizePayload(payloadData) {
108
+ if (Array.isArray(payloadData)) {
109
+ return payloadData;
110
+ }
111
+
112
+ if (payloadData && Array.isArray(payloadData.recommendedProducts)) {
113
+ return payloadData.recommendedProducts;
114
+ }
115
+
116
+ return [];
117
+ },
118
+
119
+ hasRecommendations(payloadData) {
120
+ return Wick.BloomreachWidget.normalizePayload(payloadData).length > 0;
121
+ },
122
+
123
+ getDisplayPrice(product) {
124
+ return product.displayPrice || product.price || {};
125
+ },
126
+
127
+ getDisplayPriceExcVat(product) {
128
+ return product.displayPriceExclusiveVat || product.priceExclusiveVat || null;
129
+ },
130
+
131
+ getPriceValue(price) {
132
+ return price && typeof price.value === 'number' ? price.value : 0;
133
+ },
134
+
135
+ getPriceFormattedValue(price) {
136
+ if (!price) {
137
+ return '';
138
+ }
139
+
140
+ if (price.formattedValue) {
141
+ return price.formattedValue;
142
+ }
143
+
144
+ if (typeof price.value === 'number') {
145
+ return Wick.BloomreachWidget.formatPrice(price.value);
146
+ }
147
+
148
+ return '';
149
+ },
150
+
151
+ getWasPrice(product) {
152
+ const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
153
+
154
+ return displayPrice && displayPrice.wasPrice ? displayPrice.wasPrice : null;
155
+ },
156
+
157
+ getWasPriceFormatted(product) {
158
+ const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
159
+ const wasPrice = Wick.BloomreachWidget.getWasPrice(product);
160
+
161
+ if (wasPrice && wasPrice.formattedValue) {
162
+ return wasPrice.formattedValue;
163
+ }
164
+
165
+ if (typeof wasPrice === 'number') {
166
+ return Wick.BloomreachWidget.formatPrice(wasPrice);
167
+ }
168
+
169
+ if (wasPrice) {
170
+ return `${displayPrice.currencySymbol || '£'}${wasPrice}`;
171
+ }
172
+
173
+ return '';
174
+ },
175
+
176
+ getExcVatWasPrice(product) {
177
+ const priceExclusiveVat = product.priceExclusiveVat || null;
178
+ const displayPriceExclusiveVat = product.displayPriceExclusiveVat || null;
179
+ const wasPrice =
180
+ (displayPriceExclusiveVat && displayPriceExclusiveVat.wasPrice) ||
181
+ (priceExclusiveVat && priceExclusiveVat.wasPrice);
182
+
183
+ if (wasPrice && wasPrice.formattedValue) {
184
+ return wasPrice.formattedValue;
185
+ }
186
+
187
+ if (typeof wasPrice === 'number') {
188
+ return Wick.BloomreachWidget.formatPrice(wasPrice);
189
+ }
190
+
191
+ return wasPrice || '';
192
+ },
193
+
194
+ getProductImage(product, fallbackProduct) {
195
+ const productImages = product.images || [];
196
+ const fallbackImages = fallbackProduct ? fallbackProduct.images || [] : [];
197
+ const images = productImages.length ? productImages : fallbackImages;
198
+
199
+ return (
200
+ images.find(function (item) {
201
+ return item.format === 'product';
202
+ }) ||
203
+ images.find(function (item) {
204
+ return item.imageType === 'PRIMARY';
205
+ }) ||
206
+ images[0] ||
207
+ {}
208
+ );
209
+ },
210
+
211
+ getProductRenderData(product, options = {}) {
212
+ const displayPrice = Wick.BloomreachWidget.getDisplayPrice(product);
213
+ const displayPriceExcVat = Wick.BloomreachWidget.getDisplayPriceExcVat(product);
214
+ const wasPriceFormatted = Wick.BloomreachWidget.getWasPriceFormatted(product);
215
+ const excVatWasPriceFormatted = Wick.BloomreachWidget.getExcVatWasPrice(product);
216
+ const isSwitchVat = !!(window.ACC && window.ACC.app && window.ACC.app.isVatToggleAvailable);
217
+
218
+ return {
219
+ ...product,
220
+ badge: Wick.BloomreachWidget.getBadge(product),
221
+ price: displayPrice,
222
+ image:
223
+ options.image ||
224
+ Wick.BloomreachWidget.getProductImage(product, options.fallbackProduct),
225
+ wasPriceFormatted,
226
+ 'switch-vat': isSwitchVat,
227
+ incVatFormattedValue: Wick.BloomreachWidget.getPriceFormattedValue(displayPrice),
228
+ incVatValue: Wick.BloomreachWidget.getPriceValue(displayPrice),
229
+ excVatFormattedValue: Wick.BloomreachWidget.getPriceFormattedValue(displayPriceExcVat),
230
+ excVatValue: Wick.BloomreachWidget.getPriceValue(displayPriceExcVat),
231
+ incVatWasPriceFormatted: wasPriceFormatted,
232
+ excVatWasPriceFormatted: Wick.BloomreachWidget.getExcVatWasPrice(product),
233
+ };
234
+ },
235
+
236
+ drawRating($root) {
237
+ const { ratingOverlay, starOverlay } = Wick.BloomreachWidget.el;
238
+
239
+ $root.find(ratingOverlay).each(function () {
240
+ let rating = parseFloat($(this).attr('data-rating')) || 0;
241
+ const $stars = $(this).children(starOverlay);
242
+
243
+ $stars.each(function () {
244
+ const $star = $(this);
245
+
246
+ if (rating >= 1) {
247
+ rating--;
248
+ } else if (rating > 0) {
249
+ const width = Math.asin(2 * rating - 1) / Math.PI + 0.5;
250
+ $star.css('width', width + 'rem');
251
+ rating = 0;
252
+ } else {
253
+ $star.css('width', '0rem');
254
+ }
255
+ });
256
+ });
257
+ },
258
+
259
+ dispatchWidgetEvent(eventName, payload) {
260
+ return new Promise(function (resolve, reject) {
261
+ const eventDetail = { resolve, reject };
262
+ const event = createEvent(eventName, payload, eventDetail);
263
+
264
+ window.dispatchEvent(event);
265
+ });
266
+ },
267
+
268
+ reapplyVatDisplay() {
269
+ if (!Wick.VatToggle || typeof Wick.VatToggle.isActive !== 'function') {
270
+ return;
271
+ }
272
+
273
+ const { vatInc, vatExc } = Wick.BloomreachWidget.el;
274
+ const hiddenClassName = Wick.VatToggle.HIDDEN_CLASS_NAME || 'd-none';
275
+ const isExcVatActive = Wick.VatToggle.isActive();
276
+
277
+ $(vatInc).toggleClass(hiddenClassName, isExcVatActive);
278
+ $(vatExc).toggleClass(hiddenClassName, !isExcVatActive);
279
+ },
280
+
281
+ bindVatToggle(namespace) {
282
+ if (!Wick.VatToggle || !Wick.VatToggle.TOGGLE_VAT_EVENT_NAME) {
283
+ return;
284
+ }
285
+
286
+ const eventName = `${Wick.VatToggle.TOGGLE_VAT_EVENT_NAME}.${namespace}`;
287
+
288
+ $(window).off(eventName).on(eventName, Wick.BloomreachWidget.reapplyVatDisplay);
289
+ },
290
+
291
+ formatPrice(value) {
292
+ return new Intl.NumberFormat('en-GB', {
293
+ style: 'currency',
294
+ currency: 'GBP',
295
+ minimumFractionDigits: 2,
296
+ maximumFractionDigits: 2,
297
+ }).format(value);
298
+ },
299
+ };
300
+
301
+ Wick.BloomreachWidget.registerWidgets([
302
+ {
303
+ type: 'completeYourProject',
304
+ widget: CompleteYourProjectWidget,
305
+ },
306
+ {
307
+ type: 'whyNotAdd',
308
+ widget: WhyNotAddWidget,
309
+ },
310
+ {
311
+ type: 'dontForget',
312
+ widget: DontForgetWidget,
313
+ },
314
+ ]);
315
+
316
+ $(document).ready(function () {
317
+ Wick.BloomreachWidget.showSkeleton('completeYourProject');
318
+ Wick.BloomreachWidget.showSkeleton('whyNotAdd');
319
+ });