wickes-css2 2.103.0-RG-1756-incorrect-payment-method-when-proceed-payment-with-gift-card.2 → 2.103.0-RG-1742-billie-30-60-90-days.1

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 (176) hide show
  1. package/Readme.md +3 -1
  2. package/build/css/components/checkout-payment-details-v2.css +1 -1
  3. package/build/js/account-members.min.js +1 -1
  4. package/build/js/add-project-list-id.min.js +1 -1
  5. package/build/js/address-book.min.js +1 -1
  6. package/build/js/basket.min.js +2 -2
  7. package/build/js/bundle.min.js +1 -1
  8. package/build/js/change-password.min.js +1 -1
  9. package/build/js/checkout.min.js +2 -2
  10. package/build/js/emulation.min.js +35 -273
  11. package/build/js/general.bundle.min.js +1 -1
  12. package/build/js/merged-checkout.min.js +2 -2
  13. package/build/js/page/components/order-summary.js +25 -42
  14. package/build/js/page/utils/validation.js +1 -46
  15. package/build/js/pdp.bundle.min.js +1 -1
  16. package/build/js/personal-details.min.js +1 -1
  17. package/build/js/plp.bundle.min.js +1 -1
  18. package/build/js/project-list.min.js +1 -44
  19. package/build/js/quiz.min.js +1 -1
  20. package/build/js/track-my-order.min.js +1 -1
  21. package/package.json +2 -2
  22. package/src/components/checkout-payment-details-v2.hbs +17 -5
  23. package/src/components/checkout-payment-repayment-terms.hbs +25 -0
  24. package/src/elements/form-row.hbs +1 -1
  25. package/src/elements/input.hbs +2 -31
  26. package/src/js/components/general/notification.js +1 -2
  27. package/src/js/components/toggle-password-visibility.js +58 -0
  28. package/src/js/emulation/checkout-payment-details.js +14 -23
  29. package/src/js/emulation/forms.js +21 -8
  30. package/src/js/page/components/order-summary.js +25 -42
  31. package/src/js/page/utils/validation.js +1 -46
  32. package/src/layouts/checkout.hbs +5 -1
  33. package/src/page_my-account_change-password.html +0 -1
  34. package/src/page_payment-details-with-gift-card.html +5 -8
  35. package/src/scss/components/checkout-payment-details-v2.scss +1 -2
  36. package/src/scss/components/checkout-payment-repayment-terms.scss +103 -0
  37. package/src/scss/pages/page_checkout_delivery-new.scss +0 -26
  38. package/build/css/components/energy-efficiency.css +0 -1
  39. package/build/css/components/global-search.css +0 -1
  40. package/build/css/components/kitchen/strip-stickers.css +0 -1
  41. package/build/css/components/legal-info.css +0 -1
  42. package/build/css/components/loader.css +0 -1
  43. package/build/css/components/long-banner.css +0 -1
  44. package/build/css/components/payment-details-BPS-form.css +0 -1
  45. package/build/css/components/pdf-loader.css +0 -1
  46. package/build/css/components/pdp-favourite-product.css +0 -1
  47. package/build/css/components/plp-favourite-product.css +0 -1
  48. package/build/css/components/price-block-v2-critical.css +0 -1
  49. package/build/css/components/price-block-v2.css +0 -1
  50. package/build/css/components/special-opening-schedule-v2.css +0 -1
  51. package/build/css/components/special-opening-schedule.css +0 -1
  52. package/build/css/components/store-locator-about.css +0 -1
  53. package/build/css/components/store-locator-facilities.css +0 -1
  54. package/build/css/components/store-locator-lookup.css +0 -1
  55. package/build/css/components/store-locator-v2-details.css +0 -1
  56. package/build/css/components/strip-stickers.css +0 -1
  57. package/build/css/components/tile-calculator.css +0 -1
  58. package/build/css/components/trade-pro-extras.css +0 -1
  59. package/build/css/pages/bicester-header.css +0 -1
  60. package/build/css/pages/bicester-project-list.css +0 -1
  61. package/build/css/pages/checkout-new.css +0 -1
  62. package/build/css/pages/checkout.css +0 -1
  63. package/build/css/pages/design-appointment.css +0 -1
  64. package/build/css/pages/home-movers.css +0 -1
  65. package/build/css/pages/iframe-paypage.css +0 -1
  66. package/build/css/pages/my-account-v2.css +0 -1
  67. package/build/css/pages/my-account.css +0 -1
  68. package/build/css/pages/new-usp-bar.css +0 -1
  69. package/build/css/pages/oldweb_header.css +0 -1
  70. package/build/css/pages/page_account-deletion.css +0 -1
  71. package/build/css/pages/page_act-trade-pro.css +0 -1
  72. package/build/css/pages/page_address-book.css +0 -1
  73. package/build/css/pages/page_bathroom-trends.css +0 -1
  74. package/build/css/pages/page_book-consultant-thank-you-new.css +0 -1
  75. package/build/css/pages/page_change-password.css +0 -1
  76. package/build/css/pages/page_checkout-payment-details.css +0 -1
  77. package/build/css/pages/page_checkout_delivery-new.css +0 -1
  78. package/build/css/pages/page_cms_homepage.css +0 -1
  79. package/build/css/pages/page_contact-us.css +0 -1
  80. package/build/css/pages/page_content.css +0 -1
  81. package/build/css/pages/page_coshh.css +0 -1
  82. package/build/css/pages/page_default-store.css +0 -1
  83. package/build/css/pages/page_discount.css +0 -1
  84. package/build/css/pages/page_empty-basket.css +0 -1
  85. package/build/css/pages/page_favourite-list.css +0 -1
  86. package/build/css/pages/page_fdl-management.css +0 -1
  87. package/build/css/pages/page_fdl-product.css +0 -1
  88. package/build/css/pages/page_fi.css +0 -1
  89. package/build/css/pages/page_forgotten-password.css +0 -1
  90. package/build/css/pages/page_half-login.css +0 -1
  91. package/build/css/pages/page_home.css +0 -1
  92. package/build/css/pages/page_hotspot-guttering.css +0 -1
  93. package/build/css/pages/page_in-store-checkout.css +0 -1
  94. package/build/css/pages/page_in-store_MVP_order-summary-submitted.css +0 -1
  95. package/build/css/pages/page_in-store_MVP_order-summary.css +0 -1
  96. package/build/css/pages/page_installation.css +0 -1
  97. package/build/css/pages/page_installer.css +0 -1
  98. package/build/css/pages/page_installer_form.css +0 -1
  99. package/build/css/pages/page_kitchen-claims.css +0 -1
  100. package/build/css/pages/page_kitchen-list.css +0 -1
  101. package/build/css/pages/page_login.css +0 -1
  102. package/build/css/pages/page_marketing-preferences.css +0 -1
  103. package/build/css/pages/page_merged-basket.css +0 -1
  104. package/build/css/pages/page_my-account_tradePro.css +0 -1
  105. package/build/css/pages/page_my-order.css +0 -1
  106. package/build/css/pages/page_my-orders.css +0 -1
  107. package/build/css/pages/page_new-checkout-forgot.css +0 -1
  108. package/build/css/pages/page_new-checkout_login-register.css +0 -1
  109. package/build/css/pages/page_no-results.css +0 -1
  110. package/build/css/pages/page_online-exclusive.css +0 -1
  111. package/build/css/pages/page_paint-mixing-error.css +0 -1
  112. package/build/css/pages/page_personal-details.css +0 -1
  113. package/build/css/pages/page_pre_home.css +0 -1
  114. package/build/css/pages/page_pre_home_thank-you.css +0 -1
  115. package/build/css/pages/page_product-details-critical.css +0 -1
  116. package/build/css/pages/page_product-details-v2-critical.css +0 -1
  117. package/build/css/pages/page_product-details-v2.css +0 -1
  118. package/build/css/pages/page_product-details.css +0 -1
  119. package/build/css/pages/page_product_search.css +0 -1
  120. package/build/css/pages/page_products-list-combined.css +0 -1
  121. package/build/css/pages/page_products-list-phone.css +0 -1
  122. package/build/css/pages/page_products-list.css +0 -1
  123. package/build/css/pages/page_products-list_v2.css +0 -1
  124. package/build/css/pages/page_projects.css +0 -1
  125. package/build/css/pages/page_quiz.css +0 -1
  126. package/build/css/pages/page_rate-review.css +0 -1
  127. package/build/css/pages/page_registration.css +0 -1
  128. package/build/css/pages/page_shopping-cart-v2.css +0 -1
  129. package/build/css/pages/page_shopping-cart.css +0 -1
  130. package/build/css/pages/page_split-orders.css +0 -1
  131. package/build/css/pages/page_store-locator-details.css +0 -1
  132. package/build/css/pages/page_store-locator.css +0 -1
  133. package/build/css/pages/page_thankyou.css +0 -1
  134. package/build/css/pages/page_ti.css +0 -1
  135. package/build/css/pages/page_tiling-calculator-generic.css +0 -1
  136. package/build/css/pages/page_top-rated.css +0 -1
  137. package/build/css/pages/page_track-my-order.css +0 -1
  138. package/build/css/pages/page_track_your_order.css +0 -1
  139. package/build/css/pages/page_trade_installer.css +0 -1
  140. package/build/css/pages/page_upd-pass.css +0 -1
  141. package/build/css/pages/page_wismo-details.css +0 -1
  142. package/build/css/pages/page_wismo-order-history.css +0 -1
  143. package/build/css/pages/page_wismo-orders.css +0 -1
  144. package/build/css/pages/print_quiz.css +0 -1
  145. package/build/css/pages/sticky_header.css +0 -1
  146. package/build/css/pages/tradePro-about.css +0 -1
  147. package/build/css/pages/tradePro-address-book.css +0 -1
  148. package/build/css/pages/tradePro-delivery-details.css +0 -1
  149. package/build/css/pages/tradePro-discount.css +0 -1
  150. package/build/css/pages/tradePro-order-history.css +0 -1
  151. package/build/css/pages/tradePro-payment-details.css +0 -1
  152. package/build/css/pages/tradePro-rewards-old.css +0 -1
  153. package/build/css/pages/tradePro-rewards.css +0 -1
  154. package/build/css/pages/tradePro-signup.css +0 -1
  155. package/build/css/pages/tradePro-thankyou-activate.css +0 -1
  156. package/build/img/giftcard.svg +0 -28
  157. package/build/js/gift-cards.min.js +0 -1
  158. package/build/js/page/components/gift-cards.js +0 -887
  159. package/build/js/page/components/toggle-password-visibility.js +0 -22
  160. package/build/js/page/utils/gift-cards-utils.js +0 -151
  161. package/build/js/page/utils/input-handling.js +0 -92
  162. package/build/js/page/utils/show-hide-input.js +0 -28
  163. package/build/js/toggle-password-visibility.min.js +0 -1
  164. package/src/components/gift-cards-hint.hbs +0 -9
  165. package/src/components/gift-cards.hbs +0 -90
  166. package/src/components/giftcard-chip.hbs +0 -23
  167. package/src/components/giftcard-summary.hbs +0 -6
  168. package/src/img/giftcard.svg +0 -28
  169. package/src/js/emulation/checkout-data.js +0 -35
  170. package/src/js/emulation/gift-cards.js +0 -205
  171. package/src/js/page/components/gift-cards.js +0 -887
  172. package/src/js/page/components/toggle-password-visibility.js +0 -22
  173. package/src/js/page/utils/gift-cards-utils.js +0 -151
  174. package/src/js/page/utils/input-handling.js +0 -92
  175. package/src/js/page/utils/show-hide-input.js +0 -28
  176. package/src/scss/components/_gift-cards.scss +0 -361
@@ -1,887 +0,0 @@
1
- import {initializeInputToggle} from "../utils/show-hide-input";
2
- import {updateOrderSummary} from './order-summary';
3
- import {hideLoader, showLoader, appendLoader} from "../utils/loader";
4
- import {
5
- ADD_GIFT_CARD,
6
- buildHintContext,
7
- buildSummaryEqualMap,
8
- formatGc16,
9
- isZeroAmount,
10
- linkifyClickHere,
11
- MESSAGE_BY_CODE,
12
- OK_CODE,
13
- PAY_WITH_GIFT_CARD,
14
- payWithGiftCard,
15
- REMOVE_GIFT_CARD,
16
- removeGiftCard,
17
- verifyGiftCard,
18
- ZERO_BALANCE_MESSAGE,
19
- PAY_MESSAGE_BY_CODE
20
- } from "../utils/gift-cards-utils";
21
-
22
- import { clearErrorText, validateExactDigits } from "../utils/validation";
23
- import {
24
- createGcNumberInputHandler,
25
- digitsOnlyKeypress,
26
- handleGcNumberBlur,
27
- handleGcPinInput,
28
- handleGcPinKeypress,
29
- handleGcPinBlur,
30
- } from '../utils/input-handling';
31
-
32
- const Handlebars = require('hbsfy/runtime');
33
-
34
- Handlebars.registerPartial('info-icon', require("../../../components/info-icon.hbs"));
35
- Handlebars.registerPartial('loader', require("../../../elements/loader.hbs"));
36
-
37
- const giftCardsHint = require("../../../components/gift-cards-hint.hbs");
38
- const giftCardChip = require("../../../components/giftcard-chip.hbs");
39
- const giftcardSummary = require("../../../components/giftcard-summary.hbs");
40
- const notificationTpl = require("../../../elements/notifications.hbs");
41
-
42
- var Wick = window.Wick || {};
43
-
44
- Wick.GiftCard = {
45
- ADD_GIFT_CARD,
46
- REMOVE_GIFT_CARD,
47
- PAY_WITH_GIFT_CARD,
48
- el: {
49
- $blocks: $('.giftcard'),
50
- block: '.giftcard',
51
- toggle: '#giftcard-toggle',
52
- panel: '#giftcard-inline',
53
- hint: '.giftcard-hint',
54
- closeBtn: '.giftcard-inline__close',
55
- form: '.giftcard-inline__form',
56
- number: 'input[name="giftcard-number"]',
57
- pin: 'input[name="giftcard-pin"]',
58
- note: '.giftcard-note',
59
- field: '.giftcard__field',
60
- errorText: '.giftcard__error-text',
61
- fieldError: 'giftcard-field--error',
62
- showToggle: '.toggle-show',
63
- loader: '.giftcard__container .loader-wrapper',
64
- success: '#giftcard-applied',
65
- container: '.giftcard__container',
66
- paymentForm: '.checkout-payment-details__payment-method',
67
- billieField: '.form-row__field.form-row__field-billie',
68
- klarnaField: '.form-row__field.form-row__field-klarna',
69
- clearpayField: '.form-row__field.form-row__field-clearpay',
70
- appleField: '.form-row__field.form-row__field-apple',
71
- googleField: '.form-row__field.form-row__field-google',
72
- paypalField: '.form-row__field.form-row__field-paypal',
73
- cardField: '.form-row__field.form-row__card-payment',
74
- summaryHint: '.giftcard-summary__hint',
75
- chipList: '.giftcard-chip-list',
76
- summary: '.giftcard-summary',
77
- chip: '.giftcard-chip',
78
- giftcardRow: '.giftcard-row',
79
- checkoutContainer: '.checkout-payment-details',
80
- formRow: '.form-row',
81
- iconInfo: '.icon-info-component',
82
- toggleIcon: 'svg, i',
83
- iconEye: 'fa-eye',
84
- iconEyeSlash: 'fa-eye-slash',
85
- iconSvgEyeSlash: 'eye-slash',
86
- passwordToggleEvent: 'input.passwordToggle',
87
- ariaInvalidAttr: 'aria-invalid',
88
- typeAttr: 'type',
89
- dataIconAttr: 'data-icon',
90
- svg: 'svg',
91
- expandedAttr: 'aria-expanded',
92
- giftcardBtn: '.giftcard__btn',
93
- jsGiftcardAdd: '.js-giftcard-add',
94
- giftcardChipClose: '.giftcard-chip__close',
95
- body: 'body',
96
- loaderChip: '.loader-wrapper',
97
- chipListLoader: '.giftcard-chip-list > .loader-wrapper',
98
- notification: '.giftcard-inline .notification',
99
- giftCardInline: '.giftcard-inline',
100
- notificationRoot: '.notification',
101
- inlineHeader: '.giftcard-inline__header',
102
- ctaSelector: '.btn-enter-details',
103
- btnDetails: 'button',
104
- btnText: '.btn__text',
105
- btnEnterDetails: '.btn-enter-details',
106
- checkoutPaymentFields: '.billing-address .checkout-payment-details__descr',
107
- pageLoader: '.loader-wrapper.page-loader',
108
- cardRadio: '#checkout-payment-details-card, #_checkout-payment-details-card_card',
109
- billieInfo: '.checkout-payment-details__billie',
110
- klarnaInfo: '.checkout-payment-details__klarna',
111
- billingAddress: '.billing-address',
112
- altPaymentRowsAttr: '[data-apple],[data-google],[data-paypal],[data-klarna],[data-billie],[data-clearpay],[data-existing-card]',
113
- hiddenCard: 'checkout-payment-details__card-details_hidden',
114
- cardDetails: '.checkout-payment-details__card-details',
115
- },
116
-
117
- messages: {
118
- numberMessage: 'Gift Card should consist of 16 digits',
119
- pinMessage: 'Gift Card PIN should consist of 8 digits',
120
- ctaDefaultText: 'Enter card details',
121
- ctaGiftcardText: 'Pay with Gift Card',
122
- },
123
-
124
- maxChips: 3,
125
- successTimer: null,
126
- pendingServerGiftCards: null,
127
- altPaymentInfosLocked: false,
128
- altPaymentPanelsLocked: false,
129
- summaryTotal: null,
130
-
131
- resetPinToggle($root) {
132
- const {
133
- pin,
134
- field,
135
- showToggle,
136
- toggleIcon,
137
- iconEye,
138
- iconEyeSlash,
139
- iconSvgEyeSlash,
140
- passwordToggleEvent,
141
- typeAttr,
142
- dataIconAttr,
143
- svg
144
- } = this.el;
145
-
146
- const $pinField = $root.find(pin).closest(field);
147
- const $pinInput = $pinField.find(pin).first();
148
-
149
- $pinInput.attr(typeAttr, 'password');
150
-
151
- const $toggle = $pinField.find(showToggle).first();
152
- const $icon = $toggle.find(toggleIcon).first();
153
-
154
- if ($icon.length) {
155
- $icon.removeClass(`${iconEye} ${iconEyeSlash}`).addClass(iconEyeSlash);
156
- if ($icon.is(svg) && $icon.attr(dataIconAttr)) {
157
- $icon.attr(dataIconAttr, iconSvgEyeSlash);
158
- }
159
- }
160
-
161
- const hasValue = ($pinInput.val() || '').length > 0;
162
- $toggle.toggle(hasValue);
163
-
164
- $pinInput.trigger(passwordToggleEvent);
165
- },
166
-
167
- resetForm($root) {
168
- const { number, pin, note } = this.el;
169
- const $num = $root.find(number);
170
- const $pinInput = $root.find(pin);
171
-
172
- $num.val('');
173
- $pinInput.val('');
174
- clearErrorText($num, this.el.field, this.el.errorText, this.el.fieldError, this.el.ariaInvalidAttr);
175
- clearErrorText($pinInput, this.el.field, this.el.errorText, this.el.fieldError, this.el.ariaInvalidAttr);
176
- $root.find(note).remove();
177
-
178
- this.hideBanner($root);
179
- this.resetPinToggle($root);
180
- },
181
-
182
- open($root) {
183
- const { toggle, panel, hint, pin, expandedAttr, passwordToggleEvent } = this.el;
184
- this.hideBanner($root);
185
- $root.show();
186
-
187
- $root.find(panel).prop('hidden', false);
188
- $root.find(toggle).attr(expandedAttr, 'true').hide();
189
- $root.find(hint).hide();
190
- $root.find(pin).trigger(passwordToggleEvent);
191
- },
192
-
193
- close($root) {
194
- const { toggle, panel, loader, expandedAttr } = this.el;
195
- const $toggle = $root.find(toggle);
196
- const $panel = $root.find(panel);
197
- const $loader = $root.find(loader);
198
-
199
- showLoader($loader);
200
-
201
- setTimeout(() => {
202
- hideLoader($loader);
203
-
204
- $panel.prop('hidden', true);
205
- $toggle.attr(expandedAttr, 'false').show().trigger('focus');
206
- this.updateHintVisibility($root);
207
- }, 1000);
208
- },
209
-
210
- showSubmitSpinner($root) {
211
- const { panel, toggle, hint, expandedAttr } = this.el;
212
- $root.find(panel).prop('hidden', true);
213
- $root.find(toggle).attr(expandedAttr, 'false').show().trigger('focus');
214
- $root.find(hint).show();
215
- this.showSuccess($root);
216
- },
217
-
218
- handleToggleClick(e) {
219
- e.preventDefault();
220
- this.open($(e.currentTarget).closest(this.el.$blocks));
221
- },
222
-
223
- handleCloseClick(e) {
224
- e.preventDefault();
225
- const $root = $(e.currentTarget).closest(this.el.$blocks);
226
- this.resetForm($root);
227
- this.close($root);
228
- },
229
-
230
- finalizeSuccess($root, $success) {
231
- let { panel, toggle, hint, expandedAttr } = this.el;
232
-
233
- if ($success && $success.length) {
234
- $success.attr('hidden', 'hidden').removeClass('fade show').off('transitionend');
235
- }
236
-
237
- this.resetForm($root);
238
- $root.find(panel).prop('hidden', true);
239
- $root.find(toggle).attr(expandedAttr, 'false').show();
240
- $root.find(hint).show();
241
-
242
- if (this.pendingServerGiftCards) {
243
- this.renderGiftCardsFromList($root, this.pendingServerGiftCards);
244
- this.pendingServerGiftCards = null;
245
- }
246
-
247
- this.updateHintVisibility($root);
248
- this.successTimer = null;
249
- },
250
-
251
- showSuccess($root) {
252
- const { success} = this.el;
253
-
254
- if (this.successTimer) {
255
- clearTimeout(this.successTimer);
256
- this.successTimer = null;
257
- }
258
-
259
- $root.hide();
260
- const $success = $(success);
261
- $success.removeAttr('hidden').addClass('fade');
262
- $success[0] && $success[0].offsetWidth;
263
- $success.addClass('show');
264
-
265
- this.successTimer = setTimeout(() => {
266
- $success.removeClass('show');
267
- const handler = () => this.finalizeSuccess($root, $success);
268
-
269
- $success.on('transitionend', handler);
270
- setTimeout(handler, 200)
271
- }, 3000);
272
- },
273
-
274
- handleFormSubmit(e) {
275
- const { number, block, giftcardRow, loaderChip } = this.el;
276
- e.preventDefault();
277
-
278
- const $root = $(e.currentTarget).closest(block);
279
- this.hideBanner($root);
280
-
281
- const $num = $root.find(number);
282
- $num.val(formatGc16($num.val()));
283
-
284
- const $numInput = $root.find(this.el.number);
285
- const $pinInput = $root.find(this.el.pin);
286
-
287
- const numberBlurOpts = {
288
- fieldSelector: this.el.field,
289
- errorTextSelector: this.el.errorText,
290
- errorClass: this.el.fieldError,
291
- ariaInvalidAttr: this.el.ariaInvalidAttr,
292
- numberMessage: this.messages.numberMessage,
293
- };
294
-
295
- const pinBlurOpts = {
296
- fieldSelector: this.el.field,
297
- errorTextSelector: this.el.errorText,
298
- errorClass: this.el.fieldError,
299
- ariaInvalidAttr: this.el.ariaInvalidAttr,
300
- pinMessage: this.messages.pinMessage,
301
- };
302
-
303
- const okNumber = validateExactDigits($numInput, 16, this.messages.numberMessage, this.el);
304
- const okPin = validateExactDigits($pinInput, 8, this.messages.pinMessage, this.el);
305
-
306
- if (!(okNumber && okPin)) {
307
- handleGcNumberBlur({ currentTarget: $numInput[0] }, numberBlurOpts);
308
- handleGcPinBlur({ currentTarget: $pinInput[0] }, pinBlurOpts);
309
- (!okNumber ? $numInput : $pinInput).trigger('focus');
310
- return;
311
- }
312
-
313
- const giftCardNumber = this.getNumberValue($root);
314
- const pin = this.getPinValue($root);
315
- const $row = $root.closest(giftcardRow);
316
-
317
- let $loader = $row.children(loaderChip);
318
-
319
- if (!$loader.length) {
320
- appendLoader({ wrapper: $row });
321
- $loader = $row.children(loaderChip).last();
322
- }
323
-
324
- verifyGiftCard($loader, giftCardNumber, pin)
325
- .then((res) => this.handleVerifyResponse($root, res))
326
- .catch((err) => {
327
- const code = err && typeof err.code === 'number' ? err.code : undefined;
328
- const msg = MESSAGE_BY_CODE[code] || MESSAGE_BY_CODE[-1];
329
- this.showBannerError($root, msg);
330
- });
331
- },
332
-
333
- handleVerifyResponse($root, res) {
334
- if (res && res.code === OK_CODE) {
335
- if (!Array.isArray(res.giftCards)) {
336
- this.showBannerError($root, MESSAGE_BY_CODE[-1]);
337
- return;
338
- }
339
- if (Number(res.giftCardTotal) === 0) {
340
- this.showBannerError($root, ZERO_BALANCE_MESSAGE);
341
- return;
342
- }
343
-
344
- this.pendingServerGiftCards = res.giftCards.slice();
345
-
346
- if (res.orderTotal != null || res.giftCardTotal != null) {
347
- const data = { total: res.orderTotal, giftCardApplied: res.giftCardTotal };
348
- updateOrderSummary(data, buildSummaryEqualMap(data), true);
349
- this.toggleBillingDescrForZero($root, { total: res.orderTotal });
350
- this.summaryTotal = res.orderTotal;
351
- this.updateCtaButton($root);
352
- }
353
-
354
- this.resetForm($root);
355
- this.showSubmitSpinner($root);
356
- return;
357
- }
358
-
359
- const msg = (res && MESSAGE_BY_CODE[res.code]) || MESSAGE_BY_CODE[-1];
360
- this.showBannerError($root, msg);
361
- },
362
-
363
- updateHintVisibility($root) {
364
- const {
365
- chipList, giftcardRow, hint, panel, toggle, iconInfo, expandedAttr,
366
- summaryHint, chip, block, body
367
- } = this.el;
368
-
369
- const $row = $root.closest(giftcardRow);
370
- const $giftcard = $row.find(block).first();
371
- const count = $row.find(`${chipList} ${chip}`).length;
372
- const limit = this.maxChips || 3;
373
-
374
- const zeroTotal = this.summaryTotal != null ? isZeroAmount(this.summaryTotal) : false;
375
-
376
- this.toggleAltPayments($giftcard, count === 0);
377
- this.toggleAltPaymentInfos($giftcard, count === 0);
378
-
379
- if (count > 0) {
380
- if (!this.altPaymentPanelsLocked) {
381
- this.showOnlyBillingAddress($giftcard);
382
- this.altPaymentPanelsLocked = true;
383
- } else {
384
- this.showOnlyBillingAddress($giftcard);
385
- }
386
- } else {
387
- if (!this.altPaymentPanelsLocked) {
388
- this.toggleAltPayments($giftcard, true);
389
- this.toggleAltPaymentInfos($giftcard, true);
390
- } else {
391
- this.showOnlyBillingAddress($giftcard);
392
- }
393
- }
394
-
395
- const $summary = this.ensureSummaryContainer($giftcard);
396
-
397
- if (count === 0) {
398
- $summary.hide();
399
- $giftcard.show();
400
- this.resetForm($giftcard);
401
- $giftcard.find(panel).prop('hidden', true);
402
- $giftcard.find(toggle).attr(expandedAttr, 'false').show();
403
- $giftcard.find(hint)[zeroTotal ? 'hide' : 'show']();
404
- this.updateCtaButton($giftcard);
405
- return;
406
- }
407
-
408
- this.setBillingLabelToCard($giftcard);
409
- $summary.show();
410
- $giftcard.hide();
411
- $giftcard.find(hint).hide();
412
-
413
- const ctx = buildHintContext(count, limit, zeroTotal);
414
- const html = giftCardsHint(ctx);
415
- const $old = $summary.find(summaryHint).first();
416
- const $new = $(html);
417
-
418
- if ($old.length) $old.replaceWith($new);
419
- else $summary.append($new);
420
-
421
-
422
- if (zeroTotal) {
423
- $summary.find(summaryHint).hide();
424
- }
425
-
426
- this.toggleCardDetailsForTotal($giftcard);
427
-
428
- if ($.fn.tooltip) {
429
- $summary.find(summaryHint).find(iconInfo).tooltip({ container: body });
430
- }
431
- },
432
-
433
- renderChipHTML({ id, maskedNumber, currency, amount }) {
434
- return giftCardChip({ id, maskedNumber, currency, amount });
435
- },
436
-
437
- toggleAltPaymentInfos($root, show) {
438
- const { checkoutContainer, billieInfo, klarnaInfo } = this.el;
439
- const $container = $root.closest(checkoutContainer);
440
-
441
- if (this.altPaymentInfosLocked) {
442
- show = false;
443
- }
444
-
445
- [$container.find(billieInfo), $container.find(klarnaInfo)].forEach(($panel) => {
446
- if ($panel && $panel.length) {
447
- $panel[show ? 'show' : 'hide']();
448
- }
449
- });
450
-
451
- if (!show) this.altPaymentInfosLocked = true;
452
- },
453
-
454
- toggleAltPayments($root, show) {
455
- const {
456
- paymentForm,
457
- billieField,
458
- klarnaField,
459
- clearpayField,
460
- appleField,
461
- googleField,
462
- paypalField,
463
- checkoutContainer,
464
- formRow,
465
- cardField,
466
- } = this.el;
467
-
468
- const $container = $root.closest(checkoutContainer);
469
- const $paymentField = $container.find(paymentForm);
470
-
471
- const paymentSelectors = [
472
- billieField,
473
- klarnaField,
474
- clearpayField,
475
- appleField,
476
- googleField,
477
- paypalField,
478
- ];
479
-
480
- paymentSelectors.forEach((sel) => {
481
- const $row = $paymentField.find(sel).closest(formRow);
482
- if ($row.length) {
483
- $row[show ? 'show' : 'hide']();
484
- }
485
- });
486
-
487
- const $cardRow = $paymentField.find(cardField).closest(formRow);
488
- if ($cardRow.length) {
489
- $cardRow.show();
490
- }
491
-
492
- if (!show) {
493
- this.ensureCardPaymentSelected($paymentField);
494
- }
495
- },
496
-
497
- ensureCardPaymentSelected($paymentField) {
498
- const { cardField, cardRadio, formRow } = this.el;
499
-
500
- const $cardFieldRow = $paymentField.find(cardField).closest(formRow);
501
- if (!$cardFieldRow.length) {
502
- return;
503
- }
504
-
505
- const $radio = $cardFieldRow.find(cardRadio);
506
-
507
- if ($radio.length && !$radio.prop('checked')) {
508
- $radio.prop('checked', true);
509
- $radio.trigger('change');
510
- this.updateCtaButton($cardFieldRow);
511
- }
512
- },
513
-
514
- handleAddAnotherClick(e) {
515
- e.preventDefault();
516
- const { giftcardRow, chipList, chip, block, number, summaryHint } = this.el;
517
-
518
- const $row = $(e.currentTarget).closest(giftcardRow);
519
- const count = $row.find(`${chipList} ${chip}`).length;
520
- if (count >= this.maxChips) return;
521
-
522
- const $giftcard = $row.find(block).first();
523
- this.resetForm($giftcard);
524
- this.open($giftcard);
525
-
526
- $row.find(summaryHint).hide();
527
-
528
- setTimeout(() => {
529
- $giftcard.find(number).trigger('focus');
530
- }, 0);
531
- },
532
-
533
- handleChipCloseClick(e) {
534
- e.preventDefault();
535
- const {
536
- chip,
537
- giftcardRow,
538
- block,
539
- giftcardChipClose,
540
- chipList,
541
- loaderChip,
542
- } = this.el;
543
-
544
- const $clickedChip = $(e.currentTarget).closest(chip);
545
- const $row = $clickedChip.closest(giftcardRow);
546
- const $giftcard = $row.find(block).first();
547
- const $summary = this.ensureSummaryContainer($giftcard);
548
-
549
- const $chips = $summary.find(`${chipList} ${chip}`);
550
- const index = $chips.index($clickedChip);
551
- if (index < 0) return;
552
-
553
- let $loader = $row.children(loaderChip);
554
- if (!$loader.length) {
555
- appendLoader({ wrapper: $row });
556
- $loader = $row.children(loaderChip).last();
557
- }
558
-
559
- $row
560
- .find(giftcardChipClose)
561
- .css('pointer-events', 'none')
562
- .attr('aria-disabled', 'true');
563
-
564
- removeGiftCard($loader, index)
565
- .then((res) => this.handleRemoveResponse($giftcard, res))
566
- .catch((err) => {
567
- const code = err && typeof err.code === 'number' ? err.code : undefined;
568
- const msg = MESSAGE_BY_CODE[code] || MESSAGE_BY_CODE[-1];
569
- this.showBannerError($giftcard, msg);
570
- })
571
- .finally(() => {
572
- hideLoader($loader);
573
- $row.find(giftcardChipClose).css('pointer-events', '').removeAttr('aria-disabled');
574
- });
575
- },
576
-
577
- handleRemoveResponse($giftcard, res) {
578
- if (res && res.code === OK_CODE) {
579
- const giftCardsList = Array.isArray(res.giftCards) ? res.giftCards : [];
580
- const data = { total: res.orderTotal, giftCardApplied: res.giftCardTotal };
581
- this.summaryTotal = res.orderTotal;
582
-
583
- this.renderGiftCardsFromList($giftcard, giftCardsList, data);
584
-
585
- if (res.orderTotal != null || res.giftCardTotal != null) {
586
- updateOrderSummary(data, buildSummaryEqualMap(data), true);
587
- }
588
- this.updateCtaButton($root);
589
- this.toggleBillingDescrForZero && this.toggleBillingDescrForZero($giftcard, { total: res.orderTotal });
590
- return;
591
- }
592
-
593
- const msg = (res && MESSAGE_BY_CODE[res.code]) || MESSAGE_BY_CODE[-1];
594
- this.showBannerError($giftcard, msg);
595
- },
596
-
597
- ensureSummaryContainer($root) {
598
- const { summary, giftcardRow } = this.el;
599
- const $row = $root.closest(giftcardRow);
600
- let $summary = $row.find(summary).first();
601
-
602
- if (!$summary.length) {
603
- $summary = $(giftcardSummary({}));
604
- $row.append($summary);
605
- }
606
-
607
- return $summary;
608
- },
609
-
610
- getPageLoader() {
611
- const $pl = $(this.el.pageLoader);
612
- if (!$pl.parent().is('body')) $pl.appendTo('body');
613
- return $pl;
614
- },
615
-
616
- showPageLoader() {
617
- const $pl = this.getPageLoader();
618
- showLoader($pl);
619
- },
620
-
621
- updateCtaButton($scope) {
622
- const { ctaSelector, btnDetails, btnText, checkoutContainer } = this.el;
623
- let $cta = $(ctaSelector);
624
- if (!$cta.length) {
625
- $cta = $scope.closest(checkoutContainer).find(ctaSelector);
626
- }
627
- if (!$cta.length) return;
628
-
629
- const $wrap = $cta.closest(btnDetails).length ? $cta.closest(btnDetails) : $cta;
630
- const $text = $wrap.find(btnText).first().length ? $wrap.find(btnText).first() : $wrap;
631
- const useGiftcard = isZeroAmount(this.summaryTotal);
632
-
633
- $text.text(useGiftcard ? this.messages.ctaGiftcardText : this.messages.ctaDefaultText);
634
- $wrap.attr('data-mode', useGiftcard ? 'giftcards' : 'card');
635
-
636
- if (useGiftcard) {
637
- $wrap.attr('type', 'button').removeAttr('form');
638
- } else {
639
- $wrap.attr('type', 'submit').attr('form', 'hopPaymentAddressPostForm');
640
- }
641
- },
642
-
643
- toggleBillingDescrForZero($scope, summaryData) {
644
- const $container = $scope.closest(this.el.checkoutContainer);
645
- const $descr = $container.find(this.el.checkoutPaymentFields);
646
- if (!$descr.length) return;
647
-
648
- const shouldHide = summaryData ? isZeroAmount(summaryData.total) : false;
649
- $descr[shouldHide ? 'hide' : 'show']();
650
- },
651
-
652
- getNumberValue($root) {
653
- const { number } = this.el;
654
- return String($root.find(number).val() || '').replace(/\D/g, '');
655
- },
656
-
657
- getPinValue($root) {
658
- const { pin } = this.el;
659
- return String($root.find(pin).val() || '').replace(/\D/g, '');
660
- },
661
-
662
- bindGiftcardCtaHandler() {
663
- const self = this;
664
-
665
- $(document).off('click.giftcard', this.el.btnEnterDetails);
666
- $(document).on('click.giftcard', this.el.btnEnterDetails, function (e) {
667
- const $btn = $(this);
668
- const mode = $btn.attr('data-mode');
669
-
670
- if (mode !== 'giftcards') return;
671
-
672
- e.preventDefault();
673
- e.stopPropagation();
674
- e.stopImmediatePropagation();
675
-
676
- const $scope = $btn.closest(self.el.checkoutContainer).find(self.el.block).first();
677
- const $root = $scope.length ? $scope : $(self.el.block).first();
678
-
679
- self.showPageLoader();
680
-
681
- payWithGiftCard()
682
- .then(({ url }) => {
683
- if (typeof url === 'string' && url) {
684
- window.location.href = url;
685
- }
686
- })
687
- .catch((error) => {
688
- if (Array.isArray(error?.giftCards)) {
689
- self.renderGiftCardsFromList($root, error.giftCards);
690
- }
691
-
692
- const numberCode = Number(error?.errorCode);
693
-
694
- if (Number.isFinite(numberCode) && PAY_MESSAGE_BY_CODE[numberCode]) {
695
- Wick.Notification.show({
696
- text: linkifyClickHere(PAY_MESSAGE_BY_CODE[numberCode]),
697
- container: '.globalMessages .container',
698
- type: 'error',
699
- });
700
- }
701
- })
702
- .finally(() => {
703
- const $pl = self.getPageLoader();
704
- hideLoader($pl);
705
- });
706
- });
707
- },
708
-
709
- showBannerError($root, message, title = '') {
710
- const { notificationRoot, giftCardInline, inlineHeader } = this.el;
711
- const $inline = $root.find(giftCardInline);
712
-
713
- $inline.find(notificationRoot).remove();
714
-
715
- const html = notificationTpl({
716
- classModifier: 'notification_error',
717
- error: true,
718
- withCloseBtn: true,
719
- title: title || undefined,
720
- text: linkifyClickHere(message)
721
- });
722
-
723
- $inline.find(inlineHeader).after(html);
724
- },
725
-
726
-
727
- hideBanner($root) {
728
- const { notification } = this.el;
729
- $root.find(notification).remove();
730
- },
731
-
732
- mapGiftToChipData($root, gift) {
733
- const $giftcard = $root.closest(this.el.block);
734
- const currency = $giftcard.data('currency') || '£';
735
- return {
736
- id: gift.id,
737
- maskedNumber: String(gift.maskedNumber || ''),
738
- currency,
739
- amount: Number(gift.amountToRedeem || 0),
740
- };
741
- },
742
-
743
- renderGiftCardsFromList($root, giftCards, summaryData) {
744
- const { chipList, loaderChip, chip } = this.el;
745
- const $summary = this.ensureSummaryContainer($root);
746
- const $list = $summary.find(chipList);
747
- $list.children(`${chip}:not(${loaderChip})`).remove();
748
-
749
- const html = (giftCards || [])
750
- .map((g) => this.renderChipHTML(this.mapGiftToChipData($root, g)))
751
- .join('');
752
-
753
- if (html) {
754
- $list.append(html);
755
- $summary.show();
756
- }
757
-
758
- this.updateHintVisibility($root, summaryData);
759
-
760
- if (Array.isArray(giftCards) && giftCards.length > 0) {
761
- this.setBillingLabelToCard($root);
762
- }
763
- },
764
-
765
- toggleCardDetailsForTotal($scope) {
766
- const { checkoutContainer, cardDetails, hiddenCard } = this.el;
767
- const $container = $scope.closest(checkoutContainer);
768
- const $cardDetails = $container.find(cardDetails);
769
- if (!$cardDetails.length) return;
770
-
771
- const zero = this.summaryTotal != null ? isZeroAmount(this.summaryTotal) : false;
772
- if (zero) $cardDetails.addClass(hiddenCard);
773
- },
774
-
775
- setBillingLabelToCard($scope) {
776
- const $container = $scope.closest(this.el.checkoutContainer);
777
- const $billing = $container.find(this.el.billingAddress);
778
- if (!$billing.length) return;
779
-
780
- const $label = $billing.find('[for="card-name"]');
781
- if ($label.length) {
782
- $label.text('Name on card');
783
- }
784
- },
785
-
786
- showOnlyBillingAddress($root) {
787
- const { checkoutContainer, billingAddress, altPaymentRowsAttr, hiddenCard } = this.el;
788
- const $container = $root.closest(checkoutContainer);
789
- $container.find(billingAddress).removeClass(hiddenCard);
790
- $container.find(altPaymentRowsAttr).addClass(hiddenCard);
791
- this.toggleAltPaymentInfos($root, false);
792
- },
793
-
794
- useGlobalError($root, message) {
795
- if (window.Wick && Wick.Notification && typeof Wick.Notification.show === 'function') {
796
- const text = linkifyClickHere ? linkifyClickHere(message) : String(message || '');
797
- Wick.Notification.show({
798
- text,
799
- container: '.globalMessages .container',
800
- type: 'error',
801
- });
802
- }
803
- },
804
-
805
- bindEvents() {
806
- const { number, pin, toggle, closeBtn, giftcardBtn, jsGiftcardAdd, giftcardChipClose } = this.el;
807
-
808
- $(document).off('.giftcard');
809
-
810
- const handleNumberInput = createGcNumberInputHandler({
811
- fieldSelector: this.el.field,
812
- fieldErrorClass: this.el.fieldError,
813
- errorTextSelector: this.el.errorText,
814
- ariaInvalidAttr: this.el.ariaInvalidAttr,
815
- });
816
-
817
- const onNumberBlur = (e) =>
818
- handleGcNumberBlur(e, {
819
- fieldSelector: this.el.field,
820
- errorTextSelector: this.el.errorText,
821
- errorClass: this.el.fieldError,
822
- ariaInvalidAttr: this.el.ariaInvalidAttr,
823
- numberMessage: this.messages.numberMessage,
824
- });
825
-
826
- const onPinInput = (e) =>
827
- handleGcPinInput(e, {
828
- fieldSelector: this.el.field,
829
- errorTextSelector: this.el.errorText,
830
- errorClass: this.el.fieldError,
831
- ariaInvalidAttr: this.el.ariaInvalidAttr,
832
- });
833
-
834
- const onPinBlur = (e) =>
835
- handleGcPinBlur(e, {
836
- fieldSelector: this.el.field,
837
- errorTextSelector: this.el.errorText,
838
- errorClass: this.el.fieldError,
839
- ariaInvalidAttr: this.el.ariaInvalidAttr,
840
- pinMessage: this.messages.pinMessage,
841
- });
842
-
843
-
844
- $(document)
845
- .on('input.giftcard', number, handleNumberInput)
846
- .on('keypress.giftcard', number, digitsOnlyKeypress)
847
- .on('blur.giftcard', number, onNumberBlur);
848
-
849
- $(document)
850
- .on('input.giftcard', pin, onPinInput)
851
- .on('keypress.giftcard', pin, handleGcPinKeypress)
852
- .on('blur.giftcard', pin, onPinBlur);
853
-
854
- $(document)
855
- .on('click.giftcard', toggle, this.handleToggleClick.bind(this))
856
- .on('click.giftcard', closeBtn, this.handleCloseClick.bind(this))
857
- .on('click.giftcard', giftcardBtn, this.handleFormSubmit.bind(this))
858
- .on('click.giftcard', jsGiftcardAdd, this.handleAddAnotherClick.bind(this))
859
- .on('click.giftcard', giftcardChipClose, this.handleChipCloseClick.bind(this))
860
-
861
- this.bindGiftcardCtaHandler();
862
- },
863
-
864
- init(payload = {}) {
865
- const { field, pin, $blocks } = this.el;
866
- this.bindEvents();
867
- if ($blocks && $blocks.length) {
868
- const $firstBlock = $blocks.first();
869
- if (Array.isArray(payload.giftCards) && payload.giftCards.length) {
870
- this.renderGiftCardsFromList($firstBlock, payload.giftCards);
871
- }
872
-
873
- const code = payload.errorCode;
874
-
875
- if (Number.isFinite(code) && PAY_MESSAGE_BY_CODE[code]) {
876
- this.useGlobalError($firstBlock, PAY_MESSAGE_BY_CODE[code]);
877
- }
878
- }
879
-
880
- $blocks.each((index, block) => {
881
- const $pinField = $(block).find(pin).closest(field);
882
- if ($pinField.length) {
883
- initializeInputToggle($pinField);
884
- }
885
- });
886
- }
887
- };