wickes-css2 2.113.0 → 2.116.0

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 (207) hide show
  1. package/Readme.md +1 -1
  2. package/build/css/category-main.css +1 -1
  3. package/build/css/components/checkout-payment-details-v2.css +1 -1
  4. package/build/css/components/checkout-payment-repayment-terms.css +1 -1
  5. package/build/css/components/price-block-v2-critical.css +1 -1
  6. package/build/css/components/price-block-v2.css +1 -1
  7. package/build/css/kitchen-plp-main.css +1 -1
  8. package/build/css/main.css +1 -1
  9. package/build/css/my-account-main-v2.css +1 -1
  10. package/build/css/my-account-main.css +1 -1
  11. package/build/css/pages/checkout-new.css +1 -1
  12. package/build/css/pages/checkout.css +1 -1
  13. package/build/css/pages/page_checkout_delivery-new.css +1 -1
  14. package/build/css/pages/page_product-details-v2-critical.css +1 -1
  15. package/build/css/pages/page_product-details-v2.css +1 -1
  16. package/build/css/pages/page_product-details.css +1 -1
  17. package/build/css/pages/page_products-list-combined.css +1 -1
  18. package/build/css/pages/page_products-list_v2.css +1 -1
  19. package/build/css/pdp-main-before-combine.css +1 -1
  20. package/build/css/pdp-main-critical.css +1 -1
  21. package/build/css/pdp-main-non-critical.css +1 -1
  22. package/build/css/pdp-main.css +1 -1
  23. package/build/css/plp-main.css +1 -1
  24. package/build/css/store-locator-main.css +1 -1
  25. package/build/js/account-members.min.js +1 -1
  26. package/build/js/add-project-list-id.min.js +1 -1
  27. package/build/js/address-book.min.js +1 -1
  28. package/build/js/basket.min.js +2 -2
  29. package/build/js/bloomreach-widget.min.js +1 -1
  30. package/build/js/bundle.min.js +1 -1
  31. package/build/js/change-password.min.js +1 -1
  32. package/build/js/checkout.min.js +2 -2
  33. package/build/js/emulation.min.js +260 -192
  34. package/build/js/general.bundle.min.js +1 -1
  35. package/build/js/gift-cards.min.js +1 -1
  36. package/build/js/kitchen/kitchen-plp.min.js +1 -1
  37. package/build/js/merged-checkout.min.js +2 -2
  38. package/build/js/package-bulk-add.min.js +1 -0
  39. package/build/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +7 -6
  40. package/build/js/page/bloomreach-widget/bloomreach-widget-core.js +47 -27
  41. package/build/js/page/bloomreach-widget/bloomreach-widget.js +5 -0
  42. package/build/js/page/bloomreach-widget/complete-your-project/view.js +11 -6
  43. package/build/js/page/bloomreach-widget/complete-your-project/widget.js +0 -1
  44. package/build/js/page/bloomreach-widget/similar-products-widget.js +17 -0
  45. package/build/js/page/plp-load-more.js +81 -66
  46. package/build/js/page/ripple/bulk-add.js +71 -0
  47. package/build/js/page/ripple/package-bulk-add.js +43 -0
  48. package/build/js/page/ripple/postcode-checker.js +83 -0
  49. package/build/js/page/ripple/thumb-gallery.js +236 -0
  50. package/build/js/page/utils/validation.js +1 -1
  51. package/build/js/pdp.bundle.min.js +2 -2
  52. package/build/js/personal-details.min.js +1 -1
  53. package/build/js/plp.bundle.min.js +1 -1
  54. package/build/js/postcode-checker.min.js +1 -0
  55. package/build/js/project-list.min.js +2 -2
  56. package/build/js/quiz.min.js +1 -1
  57. package/build/js/track-my-order.min.js +1 -1
  58. package/package.json +1 -1
  59. package/src/badges-ripple.html +120 -0
  60. package/src/badges.html +9 -18
  61. package/src/components/bloomreach/complete-card.hbs +1 -1
  62. package/src/components/bloomreach/why-not-add-card.hbs +26 -7
  63. package/src/components/bloomreach/why-not-add.hbs +1 -1
  64. package/src/components/fulfilment-accordions.hbs +1 -1
  65. package/src/components/image-accordion.hbs +18 -0
  66. package/src/components/kitchen/price.hbs +49 -29
  67. package/src/components/kitchen/strip-stickers.hbs +9 -3
  68. package/src/components/package-card.hbs +30 -0
  69. package/src/components/pdp-price-actions.hbs +17 -0
  70. package/src/components/postcode-checker.hbs +24 -0
  71. package/src/components/price-badges.hbs +12 -10
  72. package/src/components/price-block-v2.hbs +289 -199
  73. package/src/components/product-main-info-v2.hbs +2 -0
  74. package/src/components/suite-includes.hbs +66 -0
  75. package/src/components/suite-product-card.hbs +47 -0
  76. package/src/components/thumb-gallery.hbs +23 -0
  77. package/src/data/data_badges.json +143 -0
  78. package/src/data/data_bathroom-plp.json +814 -0
  79. package/src/data/data_suite-includes-products.json +134 -0
  80. package/src/js/components/banner-placement-manager.js +25 -9
  81. package/src/js/components/general/image-accordion.js +54 -0
  82. package/src/js/components/general/switchVat.js +8 -1
  83. package/src/js/components/package-card.js +69 -0
  84. package/src/js/components/store-locator-cards.js +76 -0
  85. package/src/js/emulation/banner-placement-manager.js +219 -188
  86. package/src/js/emulation/bloomreach-widget-calculations.js +1 -1
  87. package/src/js/emulation/mock.js +66 -34
  88. package/src/js/emulation/plp-load-more.js +13 -4
  89. package/src/js/emulation/postcode-checker.js +11 -0
  90. package/src/js/emulation/similar-products-loading.js +22 -0
  91. package/src/js/page/bloomreach-widget/bloomreach-recommendation-carousel-widget.js +7 -6
  92. package/src/js/page/bloomreach-widget/bloomreach-widget-core.js +47 -27
  93. package/src/js/page/bloomreach-widget/bloomreach-widget.js +5 -0
  94. package/src/js/page/bloomreach-widget/complete-your-project/view.js +11 -6
  95. package/src/js/page/bloomreach-widget/complete-your-project/widget.js +0 -1
  96. package/src/js/page/bloomreach-widget/similar-products-widget.js +17 -0
  97. package/src/js/page/plp-load-more.js +81 -66
  98. package/src/js/page/ripple/bulk-add.js +71 -0
  99. package/src/js/page/ripple/package-bulk-add.js +43 -0
  100. package/src/js/page/ripple/postcode-checker.js +83 -0
  101. package/src/js/page/ripple/thumb-gallery.js +236 -0
  102. package/src/js/page/utils/validation.js +1 -1
  103. package/src/page_bathroom-plp-vat.html +81 -0
  104. package/src/page_bathroom-plp-without-load-more.html +83 -0
  105. package/src/page_bathroom-plp.html +98 -0
  106. package/src/page_checkout_delivery-details-v2-calendar-not-loaded.html +167 -0
  107. package/src/page_checkout_payment-details-v2-asm.html +2 -3
  108. package/src/page_checkout_payment-details-v2.html +2 -3
  109. package/src/page_checkout_payment-details_with-card-loader.html +2 -3
  110. package/src/page_checkout_payment-details_with-klarna-loader.html +2 -3
  111. package/src/page_checkout_payment-details_with-loader-v2.html +2 -3
  112. package/src/page_klarna_payment-details_with-klarna.html +2 -3
  113. package/src/page_payment-details-billie-registered-only.html +2 -3
  114. package/src/page_payment-details-billie-unregistered-only.html +2 -3
  115. package/src/page_payment-details-with-billie.html +2 -3
  116. package/src/page_payment-details-with-clearpay.html +2 -3
  117. package/src/page_payment-details-with-gift-card.html +2 -3
  118. package/src/page_payment-details_with_apple-pay.html +0 -1
  119. package/src/page_payment-details_with_google-pay.html +2 -3
  120. package/src/page_product-details-banner.html +1 -3
  121. package/src/page_product-details-big-wins-disabled-delivery.html +1 -3
  122. package/src/page_product-details-big-wins-non-registered.html +1 -3
  123. package/src/page_product-details-big-wins-out-nearest.html +1 -3
  124. package/src/page_product-details-big-wins-unhappy.html +1 -3
  125. package/src/page_product-details-big-wins.html +1 -3
  126. package/src/page_product-details-billie.html +1 -3
  127. package/src/page_product-details-calculator.html +1 -3
  128. package/src/page_product-details-cashback-v2.html +1 -3
  129. package/src/page_product-details-clearpay.html +1 -3
  130. package/src/page_product-details-cnc-error-notification.html +1 -3
  131. package/src/page_product-details-cnc-success-notification-vat.html +1 -4
  132. package/src/page_product-details-cnc-success-notification.html +1 -3
  133. package/src/page_product-details-default-store.html +1 -3
  134. package/src/page_product-details-energy-efficiency.html +1 -3
  135. package/src/page_product-details-flooring-with-pr-placeholder.html +1 -3
  136. package/src/page_product-details-flooring.html +1 -3
  137. package/src/page_product-details-gallery-actual.html +1 -3
  138. package/src/page_product-details-mfe-calculator.html +1 -3
  139. package/src/page_product-details-mtm-doors.html +1 -3
  140. package/src/page_product-details-only-clearpay.html +1 -3
  141. package/src/page_product-details-paint-mixing.html +1 -3
  142. package/src/page_product-details-ripple-gallery-1-image.html +120 -0
  143. package/src/page_product-details-ripple-gallery-missing-image.html +121 -0
  144. package/src/page_product-details-ripple-gallery.html +121 -0
  145. package/src/page_product-details-saved-pl.html +1 -3
  146. package/src/page_product-details-suite-includes-banners.html +139 -0
  147. package/src/page_product-details-suite-includes-billie.html +128 -0
  148. package/src/page_product-details-suite-includes-klarna.html +120 -0
  149. package/src/page_product-details-suite-includes-vat.html +126 -0
  150. package/src/page_product-details-suite-includes.html +122 -0
  151. package/src/page_product-details-tile-steps-klarna-widget-with-method-ids.html +1 -3
  152. package/src/page_product-details-tile-steps-logout.html +1 -3
  153. package/src/page_product-details-tile-steps-no-new-project-list.html +1 -3
  154. package/src/page_product-details-tile-steps-with-klarna.html +1 -3
  155. package/src/page_product-details-tile-steps.html +1 -3
  156. package/src/page_product-details-v2.html +1 -3
  157. package/src/page_product-details-vat.html +1 -3
  158. package/src/page_product-details-wisdom-mcfc-registered.html +1 -3
  159. package/src/page_product-details-wisdom-mcfc.html +1 -3
  160. package/src/page_product-details-wisdom-oos-registered.html +1 -3
  161. package/src/page_product-details-wisdom-oos.html +1 -3
  162. package/src/page_product-details-wisdom-registered.html +1 -3
  163. package/src/page_product-details-wisdom.html +1 -3
  164. package/src/page_product-details-with-favourite.html +1 -3
  165. package/src/page_product-details-with-global-search-v2.html +2 -3
  166. package/src/page_product-details-with-similar-products-widget.html +132 -0
  167. package/src/page_product-details-with-why-not-add-single.html +1 -0
  168. package/src/page_product-details_no-previous-default.html +1 -3
  169. package/src/scss/common/_loading-button.scss +3 -1
  170. package/src/scss/components/_date-selection-add-new-styles.scss +53 -3
  171. package/src/scss/components/_gift-cards.scss +1 -1
  172. package/src/scss/components/_image-accordion.scss +54 -0
  173. package/src/scss/components/_kitchen-card.scss +1 -0
  174. package/src/scss/components/_map.scss +38 -0
  175. package/src/scss/components/_package-card.scss +65 -0
  176. package/src/scss/components/_package-plp.scss +88 -0
  177. package/src/scss/components/_postcode-checker.scss +115 -0
  178. package/src/scss/components/_price-badges-critical.scss +10 -0
  179. package/src/scss/components/_price-badges.scss +10 -0
  180. package/src/scss/components/_price-block-critical.scss +1 -0
  181. package/src/scss/components/_price-block.scss +1 -0
  182. package/src/scss/components/_suite-includes.scss +141 -0
  183. package/src/scss/components/_suite-product-card.scss +98 -0
  184. package/src/scss/components/_thumb-gallery-critical.scss +35 -0
  185. package/src/scss/components/_thumb-gallery.scss +200 -0
  186. package/src/scss/components/bloomreach/_why-not-add.scss +3 -1
  187. package/src/scss/components/checkout-payment-details-v2.scss +44 -20
  188. package/src/scss/components/checkout-payment-repayment-terms.scss +0 -1
  189. package/src/scss/components/kitchen/_price.scss +10 -0
  190. package/src/scss/components/kitchen/_strip-stickers.scss +46 -0
  191. package/src/scss/components/price-block-v2-critical.scss +62 -0
  192. package/src/scss/components/price-block-v2.scss +62 -0
  193. package/src/scss/pages/_checkout_delivery-details.scss +16 -104
  194. package/src/scss/pages/page_checkout_delivery-new.scss +252 -164
  195. package/src/scss/pages/page_product-details-v2-critical.scss +216 -109
  196. package/src/scss/pages/page_product-details-v2.scss +168 -107
  197. package/src/scss/pages/page_product-details.scss +11 -0
  198. package/src/scss/pages/page_products-list-combined.scss +8 -6
  199. package/src/scss/pages/page_products-list_v2.scss +8 -6
  200. package/src/scss/pdp-main-critical.scss +1 -0
  201. package/src/scss/pdp-main.scss +6 -0
  202. package/src/scss/plp-main.scss +5 -0
  203. package/src/sitemap.html +29 -6
  204. package/build/css/components/kitchen/strip-stickers.css +0 -1
  205. package/build/css/components/strip-stickers.css +0 -1
  206. package/src/scss/components/kitchen/strip-stickers.scss +0 -18
  207. package/src/scss/components/strip-stickers.scss +0 -18
@@ -0,0 +1,71 @@
1
+ import { createToast } from '../utils/create-toast';
2
+ import { createLoadingButton } from '../utils/create-loading-button';
3
+ import { createEvent } from '../utils/create-event';
4
+ const notificationTemplate = require('../../../elements/notifications.hbs');
5
+
6
+ const BULK_ADD_EVENT = 'bulkAddToCart';
7
+ const QUANTITY = 1;
8
+
9
+ const bulkAddFailedResponse = {
10
+ bulkAddToCartData: {
11
+ messageType: 'error',
12
+ messageText: 'Product was not added to basket',
13
+ },
14
+ };
15
+
16
+ export function dispatchWindowEvent(eventName, payload) {
17
+ return new Promise(function (resolve, reject) {
18
+ window.dispatchEvent(createEvent(eventName, payload, { resolve, reject }));
19
+ });
20
+ }
21
+
22
+ export function createBulkAddHelper({ productCodeSelector }) {
23
+ let toast = null;
24
+ let loadingButton = null;
25
+
26
+ function getProductCode() {
27
+ return $(productCodeSelector).val();
28
+ }
29
+
30
+ function addProductToCart(postcode) {
31
+ const item = { productCode: getProductCode(), quantity: QUANTITY };
32
+
33
+ const payload = {
34
+ entries: [item]
35
+ };
36
+
37
+ if (postcode) {
38
+ payload.postCode = postcode;
39
+ }
40
+
41
+ return dispatchWindowEvent(BULK_ADD_EVENT, payload);
42
+ }
43
+
44
+ function showBulkAddResult(response) {
45
+ const bulkData = response && response.bulkAddToCartData;
46
+
47
+ if (bulkData) {
48
+ toast.show({ type: bulkData.messageType, text: bulkData.messageText });
49
+ }
50
+ }
51
+
52
+ function init() {
53
+ if (!toast) {
54
+ toast = createToast({ template: notificationTemplate });
55
+ }
56
+ if (!loadingButton) {
57
+ loadingButton = createLoadingButton();
58
+ }
59
+ }
60
+
61
+ return {
62
+ init,
63
+ getProductCode,
64
+ addProductToCart,
65
+ showBulkAddResult,
66
+ showBulkAddFailed: () => showBulkAddResult(bulkAddFailedResponse),
67
+ get loadingButton() {
68
+ return loadingButton;
69
+ },
70
+ };
71
+ }
@@ -0,0 +1,43 @@
1
+ import { createBulkAddHelper } from './bulk-add';
2
+
3
+ var Wick = window.Wick || {};
4
+
5
+ Wick.PackageBulkAdd = (function () {
6
+ const selectors = {
7
+ button: '.package-bulk-add',
8
+ productCodeInput: '.pdp-price input[name=productCodePost]',
9
+ };
10
+
11
+ const bulkAdd = createBulkAddHelper({ productCodeSelector: selectors.productCodeInput });
12
+
13
+ async function handleButtonClick(e) {
14
+ e.preventDefault();
15
+
16
+ const $buttons = $(selectors.button);
17
+
18
+ if (bulkAdd.loadingButton.isLoading($buttons)) {
19
+ return;
20
+ }
21
+
22
+ bulkAdd.loadingButton.start($buttons);
23
+
24
+ try {
25
+ bulkAdd.showBulkAddResult(await bulkAdd.addProductToCart());
26
+ Wick.MiniBasketSliderFE.isMiniBasketLoaded = false;
27
+ } catch {
28
+ bulkAdd.showBulkAddFailed();
29
+ } finally {
30
+ bulkAdd.loadingButton.stop($buttons);
31
+ }
32
+ }
33
+
34
+ function init() {
35
+ bulkAdd.init();
36
+
37
+ $(selectors.button).on('click', handleButtonClick);
38
+ }
39
+
40
+ return { init };
41
+ })();
42
+
43
+ $(document).ready(Wick.PackageBulkAdd.init);
@@ -0,0 +1,83 @@
1
+ import { isValidPostcodeField } from '../utils/validation';
2
+ import { createBulkAddHelper, dispatchWindowEvent } from './bulk-add';
3
+
4
+ var Wick = window.Wick || {};
5
+
6
+ Wick.PostcodeChecker = (function () {
7
+ const POSTCODE_CHECK_AVAILABILITY_EVENT = 'postcodeCheckAviability';
8
+ const QUANTITY = 1;
9
+
10
+ const selectors = {
11
+ root: '.postcode-checker',
12
+ input: '.postcode-checker__input',
13
+ button: '.postcode-checker__button',
14
+ productCodeInput: '.pdp-price input[name=productCodePost]',
15
+ };
16
+
17
+ const modifiers = {
18
+ hasError: 'postcode-checker--error',
19
+ };
20
+
21
+ const bulkAdd = createBulkAddHelper({ productCodeSelector: selectors.productCodeInput });
22
+
23
+ function checkPostcodeAvailability(postcode) {
24
+ const payload = { postcode, productCode: bulkAdd.getProductCode(), quantity: QUANTITY };
25
+
26
+ return dispatchWindowEvent(POSTCODE_CHECK_AVAILABILITY_EVENT, payload);
27
+ }
28
+
29
+ async function bulkAddForPostcode(postcode) {
30
+ try {
31
+ await checkPostcodeAvailability(postcode);
32
+ bulkAdd.showBulkAddResult(await bulkAdd.addProductToCart(postcode));
33
+ Wick.MiniBasketSliderFE.isMiniBasketLoaded = false;
34
+ } catch {
35
+ bulkAdd.showBulkAddFailed();
36
+ }
37
+ }
38
+
39
+ function isPostcodeValid($component, $postcodeInput) {
40
+ const isValid = isValidPostcodeField($postcodeInput.val());
41
+ $component.toggleClass(modifiers.hasError, !isValid);
42
+ console.log({ isValid, val: $postcodeInput.val() });
43
+ return isValid;
44
+ }
45
+
46
+ function handleSubmitClick($component, $postcodeInput, $submitButton) {
47
+ if (
48
+ bulkAdd.loadingButton.isLoading($submitButton) ||
49
+ !isPostcodeValid($component, $postcodeInput)
50
+ ) {
51
+ return;
52
+ }
53
+
54
+ bulkAdd.loadingButton.start($submitButton);
55
+
56
+ const postcode = $postcodeInput.val();
57
+
58
+ bulkAddForPostcode(postcode).finally(function () {
59
+ bulkAdd.loadingButton.stop($submitButton);
60
+ });
61
+ }
62
+
63
+ function init() {
64
+ bulkAdd.init();
65
+
66
+ $(selectors.root).each(function () {
67
+ const $component = $(this);
68
+ const $postcodeInput = $component.find(selectors.input);
69
+ const $submitButton = $component.find(selectors.button);
70
+
71
+ $component.removeClass(modifiers.hasError);
72
+
73
+ $submitButton.on('click', function (e) {
74
+ e.preventDefault();
75
+ handleSubmitClick($component, $postcodeInput, $submitButton);
76
+ });
77
+ });
78
+ }
79
+
80
+ return { init };
81
+ })();
82
+
83
+ $(document).ready(Wick.PostcodeChecker.init);
@@ -0,0 +1,236 @@
1
+ var Wick = window.Wick || {};
2
+
3
+ Wick.ThumbGallery = (function () {
4
+ const IMG_BREAKPOINTS = [
5
+ { media: '(max-width: 576px)', w: 576, h: 324 },
6
+ { media: '(max-width: 768px)', w: 510, h: 287 },
7
+ { media: '(max-width: 992px)', w: 310, h: 174 },
8
+ ];
9
+
10
+ const MAIN_DEFAULT = { w: 710, h: 399 };
11
+ const THUMB = { w: 100, h: 56 };
12
+
13
+ function getMediaDomain() {
14
+ return (typeof window !== 'undefined' && window.mediaDomain) || 'media.wickes.co.uk';
15
+ }
16
+
17
+ function getProductName() {
18
+ return (typeof window !== 'undefined' && window.pdpProduct && window.pdpProduct.name) || '';
19
+ }
20
+
21
+ function getBaseUrl(customDomain) {
22
+ const domain = customDomain || getMediaDomain();
23
+ const cleanDomain = domain.replace(/^https?:\/\//, '').replace(/\/$/, '');
24
+ return `https://${cleanDomain}/image/upload/`;
25
+ }
26
+
27
+ function buildCloudinaryUrl(publicId, w, h, baseUrl) {
28
+ const base = baseUrl || getBaseUrl();
29
+ const cleanId = String(publicId).replace(/^\/+/, '');
30
+ const transforms = `b_rgb:FFFFFF,c_pad,dpr_1.0,f_jpg,h_${h},q_auto:good,w_${w}`;
31
+ return `${base}${transforms}/c_pad,h_${h},w_${w}/v1/${cleanId}?pgw=1`;
32
+ }
33
+
34
+ function parseIdentifiers(hybrisString) {
35
+ if (Array.isArray(hybrisString)) {
36
+ return hybrisString.filter(Boolean);
37
+ }
38
+ if (!hybrisString || typeof hybrisString !== 'string') {
39
+ return [];
40
+ }
41
+ const trimmed = hybrisString.trim();
42
+ const content = trimmed.startsWith('[') && trimmed.endsWith(']')
43
+ ? trimmed.slice(1, -1)
44
+ : trimmed;
45
+
46
+ return content
47
+ .split(',')
48
+ .map((s) => s.trim())
49
+ .filter(Boolean);
50
+ }
51
+
52
+ function renderMainSlide(src, sourcesHtml = '') {
53
+ const productName = getProductName();
54
+ return `<div class="thumb-gallery__slide-wrapper swiper-slide">
55
+ <picture>
56
+ ${sourcesHtml}
57
+ <img class="swiper-slide-main" src="${src}" alt="${productName}">
58
+ </picture>
59
+ </div>`;
60
+ }
61
+
62
+ function renderThumbSlide(src) {
63
+ const productName = getProductName();
64
+ return `<div class="thumb-gallery__slide-wrapper swiper-slide">
65
+ <img class="swiper-slide-thumbs" src="${src}" alt="${productName}">
66
+ </div>`;
67
+ }
68
+
69
+ function generateCloudinaryMainSlide(publicId, baseUrl) {
70
+ const sourcesHtml = IMG_BREAKPOINTS.map(
71
+ (bp) => `<source srcset="${buildCloudinaryUrl(publicId, bp.w, bp.h, baseUrl)}" media="${bp.media}">`
72
+ ).join('\n ');
73
+ const fallbackSrc = buildCloudinaryUrl(publicId, MAIN_DEFAULT.w, MAIN_DEFAULT.h, baseUrl);
74
+ return renderMainSlide(fallbackSrc, sourcesHtml);
75
+ }
76
+
77
+ function generateCloudinaryThumbSlide(publicId, baseUrl) {
78
+ const src = buildCloudinaryUrl(publicId, THUMB.w, THUMB.h, baseUrl);
79
+ return renderThumbSlide(src);
80
+ }
81
+
82
+ const SELECTORS = {
83
+ galleryCarousel: '.thumb-gallery',
84
+ swiperContainerMain: '.swiper-container-main',
85
+ swiperContainerThumbs: '.swiper-container-thumbs',
86
+ swiperMainWrapper: '.swiper-container-main .swiper-wrapper',
87
+ swiperThumbsWrapper: '.swiper-container-thumbs .swiper-wrapper',
88
+ nextBtn: '.thumb-gallery__next-btn',
89
+ prevBtn: '.thumb-gallery__prev-btn',
90
+ thumbNextBtn: '.swiper-container-thumbs__next-btn',
91
+ thumbPrevBtn: '.swiper-container-thumbs__prev-btn',
92
+ swiperSlide: '.swiper-slide',
93
+ activeThumbClass: 'swiper-true-active',
94
+ };
95
+
96
+ const THUMBS_SWIPER_CONFIG = {
97
+ spaceBetween: 8,
98
+ slidesPerView: 8,
99
+ watchSlidesVisibility: true,
100
+ watchSlidesProgress: true,
101
+ watchOverflow: true,
102
+ observer: true,
103
+ observeParents: true,
104
+ simulateTouch: false,
105
+ };
106
+
107
+ const THUMBS_BREAKPOINTS = {
108
+ 991: { slidesPerView: 5 },
109
+ 767: { allowTouchMove: true, slidesPerView: 5 },
110
+ };
111
+
112
+ const MAIN_SWIPER_CONFIG = {
113
+ speed: 400,
114
+ slidesPerView: 1,
115
+ loop: true,
116
+ observer: true,
117
+ observeParents: true,
118
+ simulateTouch: false,
119
+ };
120
+
121
+ function handleThumbClick(swiper) {
122
+ return function () {
123
+ const clickedIndex = $(this).index();
124
+ if (swiper.params && swiper.params.loop) {
125
+ swiper.slideToLoop(clickedIndex);
126
+ } else {
127
+ swiper.slideTo(clickedIndex);
128
+ }
129
+ };
130
+ }
131
+
132
+ function updateActiveThumbnail(swiper, thumbsSwiper) {
133
+ const activeIndex = swiper.realIndex;
134
+ thumbsSwiper.slides.removeClass(SELECTORS.activeThumbClass);
135
+ thumbsSwiper.slides.eq(activeIndex).addClass(SELECTORS.activeThumbClass);
136
+ }
137
+
138
+ function getThumbsConfig($thumbNextBtn, $thumbPrevBtn) {
139
+ return {
140
+ ...THUMBS_SWIPER_CONFIG,
141
+ navigation: {
142
+ nextEl: $thumbNextBtn[0],
143
+ prevEl: $thumbPrevBtn[0],
144
+ },
145
+ breakpoints: { ...THUMBS_BREAKPOINTS },
146
+ };
147
+ }
148
+
149
+ function getMainSwiperConfig($nextBtn, $prevBtn, thumbsSwiper, onSlideChange, count) {
150
+ return {
151
+ ...MAIN_SWIPER_CONFIG,
152
+ loop: count > 1,
153
+ simulateTouch: count > 1,
154
+ navigation: {
155
+ nextEl: $nextBtn[0],
156
+ prevEl: $prevBtn[0],
157
+ },
158
+ thumbs: { swiper: thumbsSwiper },
159
+ on: { slideChange: onSlideChange },
160
+ };
161
+ }
162
+
163
+ function initializeCarousel($slider, ids, baseUrl, missingImage) {
164
+ const isMissing = ids.length === 0 && Boolean(missingImage);
165
+ if (ids.length === 0 && !missingImage) {
166
+ return;
167
+ }
168
+
169
+ const $container = $slider.find(SELECTORS.swiperContainerMain);
170
+ const $thumbContainer = $slider.find(SELECTORS.swiperContainerThumbs);
171
+ if (!$container.length || !$thumbContainer.length) {
172
+ return;
173
+ }
174
+
175
+ if ($container[0].swiper) {
176
+ $container[0].swiper.destroy(true, true);
177
+ }
178
+ if ($thumbContainer[0].swiper) {
179
+ $thumbContainer[0].swiper.destroy(true, true);
180
+ }
181
+
182
+ const total = isMissing ? 1 : ids.length;
183
+ $slider.attr('data-length', total);
184
+
185
+ if (isMissing) {
186
+ $slider.addClass('thumb-gallery--missing-image');
187
+ $slider.find(SELECTORS.swiperMainWrapper).html(renderMainSlide(missingImage));
188
+ $slider.find(SELECTORS.swiperThumbsWrapper).html(renderThumbSlide(missingImage));
189
+ } else {
190
+ $slider.removeClass('thumb-gallery--missing-image');
191
+ $slider
192
+ .find(SELECTORS.swiperMainWrapper)
193
+ .html(ids.map((id) => generateCloudinaryMainSlide(id, baseUrl)).join('\n'));
194
+ $slider
195
+ .find(SELECTORS.swiperThumbsWrapper)
196
+ .html(ids.map((id) => generateCloudinaryThumbSlide(id, baseUrl)).join('\n'));
197
+ }
198
+
199
+ const $nextBtn = $slider.find(SELECTORS.nextBtn);
200
+ const $prevBtn = $slider.find(SELECTORS.prevBtn);
201
+ const $thumbNextBtn = $slider.find(SELECTORS.thumbNextBtn);
202
+ const $thumbPrevBtn = $slider.find(SELECTORS.thumbPrevBtn);
203
+
204
+ const thumbsSwiper = new Swiper(
205
+ $thumbContainer[0],
206
+ getThumbsConfig($thumbNextBtn, $thumbPrevBtn)
207
+ );
208
+
209
+ const swiper = new Swiper(
210
+ $container[0],
211
+ getMainSwiperConfig($nextBtn, $prevBtn, thumbsSwiper, () => {
212
+ updateActiveThumbnail(swiper, thumbsSwiper);
213
+ }, total)
214
+ );
215
+
216
+ $thumbContainer
217
+ .off('click', SELECTORS.swiperSlide)
218
+ .on('click', SELECTORS.swiperSlide, handleThumbClick(swiper));
219
+
220
+ updateActiveThumbnail(swiper, thumbsSwiper);
221
+ }
222
+
223
+ function init(hybrisString, options = {}) {
224
+ const ids = parseIdentifiers(hybrisString);
225
+
226
+ const opts = typeof options === 'string' ? { mediaDomain: options } : (options || {});
227
+ const baseUrl = getBaseUrl(opts.mediaDomain);
228
+ const missingImage = opts.missingImage || '';
229
+
230
+ $(SELECTORS.galleryCarousel).each(function (_, slider) {
231
+ initializeCarousel($(slider), ids, baseUrl, missingImage);
232
+ });
233
+ }
234
+
235
+ return { init };
236
+ })();
@@ -148,7 +148,7 @@ export function validatePostcode(element, ifConvert) {
148
148
  export function isValidPostcodeField(value) {
149
149
  const transformedValue = value.toUpperCase().replaceAll(' ', '');
150
150
  const regExp = new RegExp(
151
- '^(GIR 0AA)|((([A-PR-UWYZ][0-9][0-9]?)|([A-PR-UWYZ][A-HK-Y][0-9][0-9]?)|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))[0-9][A-BD-HJLNP-UW-Z]{2})$'
151
+ '^((GIR0AA)|((([A-PR-UWYZ][0-9][0-9]?)|([A-PR-UWYZ][A-HK-Y][0-9][0-9]?)|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))[0-9][A-BD-HJLNP-UW-Z]{2}))$'
152
152
  );
153
153
  return transformedValue.replace(/\s+/g, '').length > 4 && regExp.test(transformedValue);
154
154
  }
@@ -0,0 +1,81 @@
1
+ {{#extend "base" hybrisClass="hybris-class" pageClass="products-list-page" title="Bathroom PLP" globalSearchV2="true" pagePlp=true bundle="plp" switch-vat=true}}
2
+ {{#content "head" mode="append"}}
3
+ <link type="text/css" rel="stylesheet" href="./css/components/global-search.css">
4
+ {{/content}}
5
+ {{#content "body"}}
6
+ <main>
7
+ <div class="package-plp container">
8
+ <div class="page-header page-header_border-all">
9
+ <h1 class="page-header__title">
10
+ Bathroom Suite Packages
11
+ </h1>
12
+ {{> srp-injected}}
13
+ </div>
14
+
15
+ {{> quick-filter filterData=quickFilter.iconAndText_5}}
16
+
17
+ <div class="package-plp__container">
18
+ <aside class="package-plp__search-filter">
19
+ {{> search-filter collapsed="accordion_collapsed" hidden="hidden-state"}}
20
+ </aside>
21
+
22
+ <div class="package-plp__content products-list-v2">
23
+ <div class="plp-filters" data-component="plp-filters" aria-label="Product filters">
24
+ <div class="plp-filters__bar plp-filters__bar-mobile" role="tablist" aria-label="Filters">
25
+ {{> kitchen/mobile-nav-item
26
+ icon="fas fa-filter"
27
+ title="Filter by"
28
+ info="24 results"
29
+ modalId="filterModal"
30
+ mod="filter-modal-cta"
31
+ }}
32
+ {{> kitchen/mobile-nav-item
33
+ icon="fas fa-sort-alt"
34
+ title="Sort by"
35
+ info="Relevance"
36
+ dropdown=true
37
+ }}
38
+ </div>
39
+ </div>
40
+
41
+ <input id="numberOfPagesPLP" value="2" type="hidden">
42
+ <div class="sort-products-list">
43
+ {{> kitchen/sort-by }}
44
+ </div>
45
+
46
+ <div class="package-plp__cards">
47
+ {{> package-card cards=ripple-plp.cards}}
48
+ {{#if search-result_v2.product-banner}}
49
+ {{#each search-result_v2.product-banner}}
50
+ {{>card_product_banner_v2}}
51
+ {{/each}}
52
+ {{/if}}
53
+ {{#if search-result_v2.bloomreach-media-banner}}
54
+ {{#each search-result_v2.bloomreach-media-banner}}
55
+ {{>card_bloomreach_media_banner}}
56
+ {{/each}}
57
+ {{/if}}
58
+ {{#if search-result_v2.sponsor-banner}}
59
+ {{#each search-result_v2.sponsor-banner}}
60
+ {{>card_sponsor_banner}}
61
+ {{/each}}
62
+ {{/if}}
63
+ </div>
64
+
65
+ <div class="load-more-wrap">
66
+ <button class="btn btn-primary btn_full btn-load-more">
67
+ Load more
68
+ </button>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </main>
74
+ {{/content}}
75
+ {{#content "foot" mode="append"}}
76
+ {{> kitchen/filter-modal isKitchenMode=false modalTitle="Filter by" }}
77
+ <script defer src="./js/search-filter.min.js"></script>
78
+ <script defer src="./js/plp-filters.min.js"></script>
79
+ <script defer src="./js/page/quick-filter.js"></script>
80
+ {{/content}}
81
+ {{/extend}}
@@ -0,0 +1,83 @@
1
+ {{#extend "base" hybrisClass="hybris-class" pageClass="products-list-page" title="Bathroom PLP" globalSearchV2="true" pagePlp=true bundle="plp"}}
2
+ {{#content "head" mode="append"}}
3
+ <link type="text/css" rel="stylesheet" href="./css/components/global-search.css">
4
+ <link type="text/css" rel="stylesheet" href="https://static-content-develop.dev.wickes.co.uk/whisk/kitchen-static/css/kitchen-content.css">
5
+ {{/content}}
6
+ {{#content "body"}}
7
+ <main>
8
+ <div class="package-plp container">
9
+ <div class="page-header page-header_border-all">
10
+ <h1 class="page-header__title">
11
+ Bathroom Suite Packages
12
+ </h1>
13
+ {{> srp-injected}}
14
+ {{> sponsor-top-banner }}
15
+ </div>
16
+
17
+ {{> quick-filter filterData=quickFilter.iconAndText_5}}
18
+
19
+ <div class="hybris-slot">
20
+ <div style="min-height: 120px; background-color: gray;"></div>
21
+ <div style="min-height: 120px; background-color: gray;"></div>
22
+ </div>
23
+
24
+ <div class="package-plp__container">
25
+ <aside class="package-plp__search-filter">
26
+ {{> search-filter collapsed="accordion_collapsed" hidden="hidden-state"}}
27
+ </aside>
28
+
29
+ <div class="package-plp__content products-list-v2">
30
+ <div class="plp-filters" data-component="plp-filters" aria-label="Product filters">
31
+ <div class="plp-filters__bar plp-filters__bar-mobile" role="tablist" aria-label="Filters">
32
+ {{> kitchen/mobile-nav-item
33
+ icon="fas fa-filter"
34
+ title="Filter by"
35
+ info="24 results"
36
+ modalId="filterModal"
37
+ mod="filter-modal-cta"
38
+ }}
39
+ {{> kitchen/mobile-nav-item
40
+ icon="fas fa-sort-alt"
41
+ title="Sort by"
42
+ info="Relevance"
43
+ dropdown=true
44
+ }}
45
+ </div>
46
+ </div>
47
+
48
+ <input id="numberOfPagesPLP" value="1" type="hidden">
49
+ <div class="sort-products-list">
50
+ {{> kitchen/sort-by }}
51
+ </div>
52
+
53
+ <div class="package-plp__cards">
54
+ {{> package-card cards=(limitArray ripple-plp.cards 7)}}
55
+ </div>
56
+
57
+ <div class="load-more-wrap">
58
+ <button class="btn btn-primary btn_full btn-load-more">
59
+ Load more
60
+ </button>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="container">
67
+ <div class="hybris-slot">
68
+ <div class="banner-emulation" style="height: 398px; min-height: 120px; background-color: gray;"></div>
69
+ <div style="min-height: 120px; background-color: gray;"></div>
70
+ <div style="min-height: 120px; background-color: gray;"></div>
71
+ </div>
72
+ </div>
73
+
74
+ {{> legal-info}}
75
+ </main>
76
+ {{/content}}
77
+ {{#content "foot" mode="append"}}
78
+ {{> kitchen/filter-modal isKitchenMode=false modalTitle="Filter by" }}
79
+ <script defer src="./js/search-filter.min.js"></script>
80
+ <script defer src="./js/plp-filters.min.js"></script>
81
+ <script defer src="./js/page/quick-filter.js"></script>
82
+ {{/content}}
83
+ {{/extend}}