@nakedwines/naked-components 1.0.0 → 3.637.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of @nakedwines/naked-components might be problematic. Click here for more details.

Files changed (121) hide show
  1. package/README.md +33 -0
  2. package/build-utils/update-library.js +91 -0
  3. package/library/globals.js +4 -0
  4. package/library/index.js +69 -0
  5. package/package.json +22 -6
  6. package/src/components/badges/Badge.vue +20 -0
  7. package/src/components/badges/Badge.vue?1b45 +1 -0
  8. package/src/components/badges/Badge.vue?5424 +10 -0
  9. package/src/components/badges/Badge.vue?c5b6 +1 -0
  10. package/src/components/banners/Banner.vue +20 -0
  11. package/src/components/banners/Banner.vue?2006 +1 -0
  12. package/src/components/banners/Banner.vue?36d1 +1 -0
  13. package/src/components/banners/Banner.vue?9b97 +4 -0
  14. package/src/components/buttons/Button.vue +21 -0
  15. package/src/components/buttons/Button.vue?2035 +1 -0
  16. package/src/components/buttons/Button.vue?5c96 +1 -0
  17. package/src/components/buttons/Button.vue?838e +26 -0
  18. package/src/components/buttons/Button.vue?e88c +1 -0
  19. package/src/components/buttons/LoadingButton.vue +20 -0
  20. package/src/components/buttons/LoadingButton.vue?2f5e +17 -0
  21. package/src/components/buttons/LoadingButton.vue?4a65 +1 -0
  22. package/src/components/buttons/LoadingButton.vue?65be +1 -0
  23. package/src/components/buttons/Ripple.vue +20 -0
  24. package/src/components/buttons/Ripple.vue?130a +1 -0
  25. package/src/components/buttons/Ripple.vue?2026 +13 -0
  26. package/src/components/buttons/Ripple.vue?4835 +1 -0
  27. package/src/components/cards/ContentCard.vue +20 -0
  28. package/src/components/cards/ContentCard.vue?35c8 +10 -0
  29. package/src/components/cards/ContentCard.vue?7164 +1 -0
  30. package/src/components/cards/ContentCard.vue?ec15 +1 -0
  31. package/src/components/cards/bottle-cards/CaseContentsCard.vue +20 -0
  32. package/src/components/cards/bottle-cards/CaseContentsCard.vue?3ac7 +1 -0
  33. package/src/components/cards/bottle-cards/CaseContentsCard.vue?7e00 +4 -0
  34. package/src/components/cards/bottle-cards/CaseContentsCard.vue?dd6f +1 -0
  35. package/src/components/cards/bottle-cards/CaseProductCard.vue +21 -0
  36. package/src/components/cards/bottle-cards/CaseProductCard.vue?0cb0 +1 -0
  37. package/src/components/cards/bottle-cards/CaseProductCard.vue?1bd2 +1 -0
  38. package/src/components/cards/bottle-cards/CaseProductCard.vue?25e9 +4 -0
  39. package/src/components/cards/bottle-cards/CaseProductCard.vue?95f9 +1 -0
  40. package/src/components/cards/bottle-cards/WineBottleCard.vue +21 -0
  41. package/src/components/cards/bottle-cards/WineBottleCard.vue?61a8 +1 -0
  42. package/src/components/cards/bottle-cards/WineBottleCard.vue?7e9a +1 -0
  43. package/src/components/cards/bottle-cards/WineBottleCard.vue?bd3e +4 -0
  44. package/src/components/cards/bottle-cards/WineBottleCard.vue?bdcc +1 -0
  45. package/src/components/cards/bottle-cards/components/BiaText.vue +20 -0
  46. package/src/components/cards/bottle-cards/components/BiaText.vue?123e +1 -0
  47. package/src/components/cards/bottle-cards/components/BiaText.vue?3e10 +1 -0
  48. package/src/components/cards/bottle-cards/components/BiaText.vue?d135 +4 -0
  49. package/src/components/cards/bottle-cards/components/HeartRatingPanel.vue +20 -0
  50. package/src/components/cards/bottle-cards/components/HeartRatingPanel.vue?712f +4 -0
  51. package/src/components/cards/bottle-cards/components/HeartRatingPanel.vue?c55a +1 -0
  52. package/src/components/cards/bottle-cards/components/HeartRatingPanel.vue?ee3b +1 -0
  53. package/src/components/cards/bottle-cards/components/PriceBreakdownPanel.vue +20 -0
  54. package/src/components/cards/bottle-cards/components/PriceBreakdownPanel.vue?5052 +1 -0
  55. package/src/components/cards/bottle-cards/components/PriceBreakdownPanel.vue?5838 +4 -0
  56. package/src/components/cards/bottle-cards/components/PriceBreakdownPanel.vue?7aad +1 -0
  57. package/src/components/cards/bottle-cards/components/WineDetailPanel.vue +20 -0
  58. package/src/components/cards/bottle-cards/components/WineDetailPanel.vue?5047 +1 -0
  59. package/src/components/cards/bottle-cards/components/WineDetailPanel.vue?8e3b +1 -0
  60. package/src/components/cards/bottle-cards/components/WineDetailPanel.vue?d1ea +4 -0
  61. package/src/components/carousel/Carousel.vue +21 -0
  62. package/src/components/carousel/Carousel.vue?492f +1 -0
  63. package/src/components/carousel/Carousel.vue?4e80 +4 -0
  64. package/src/components/carousel/Carousel.vue?66a0 +1 -0
  65. package/src/components/carousel/Carousel.vue?72ce +1 -0
  66. package/src/components/chips/Chip.vue +20 -0
  67. package/src/components/chips/Chip.vue?7e2c +1 -0
  68. package/src/components/chips/Chip.vue?9563 +4 -0
  69. package/src/components/chips/Chip.vue?f42c +1 -0
  70. package/src/components/footers/sticky-footer/StickyFooter.vue +20 -0
  71. package/src/components/footers/sticky-footer/StickyFooter.vue?10bf +4 -0
  72. package/src/components/footers/sticky-footer/StickyFooter.vue?b195 +1 -0
  73. package/src/components/footers/sticky-footer/StickyFooter.vue?e2d9 +1 -0
  74. package/src/components/forms/CheckboxInput.vue +20 -0
  75. package/src/components/forms/CheckboxInput.vue?1713 +1 -0
  76. package/src/components/forms/CheckboxInput.vue?51c9 +1 -0
  77. package/src/components/forms/CheckboxInput.vue?feea +4 -0
  78. package/src/components/forms/QuantityInput.vue +20 -0
  79. package/src/components/forms/QuantityInput.vue?233a +25 -0
  80. package/src/components/forms/QuantityInput.vue?4975 +1 -0
  81. package/src/components/forms/QuantityInput.vue?bb30 +1 -0
  82. package/src/components/forms/SelectInput.vue +172 -0
  83. package/src/components/forms/SelectInput.vue?1d47 +1 -0
  84. package/src/components/forms/SelectInput.vue?642a +21 -0
  85. package/src/components/forms/SelectInput.vue?7590 +20 -0
  86. package/src/components/forms/SelectInput.vue?f210 +1 -0
  87. package/src/components/forms/SelectInput.vue?fc78 +1 -0
  88. package/src/components/icons/CustomisableHeart.vue +19 -0
  89. package/src/components/icons/CustomisableHeart.vue?30ab +1 -0
  90. package/src/components/icons/CustomisableHeart.vue?ce76 +4 -0
  91. package/src/components/icons/Icon.vue +21 -0
  92. package/src/components/icons/Icon.vue?47ee +9 -0
  93. package/src/components/icons/Icon.vue?6e26 +1 -0
  94. package/src/components/icons/Icon.vue?897e +1 -0
  95. package/src/components/icons/Icon.vue?e753 +1 -0
  96. package/src/components/modal/ProductDetailModal.vue +20 -0
  97. package/src/components/modal/ProductDetailModal.vue?5d3a +1 -0
  98. package/src/components/modal/ProductDetailModal.vue?9f0f +1 -0
  99. package/src/components/modal/ProductDetailModal.vue?a2a9 +4 -0
  100. package/src/components/popover/Popover.vue +20 -0
  101. package/src/components/popover/Popover.vue?088e +1 -0
  102. package/src/components/popover/Popover.vue?4dad +1 -0
  103. package/src/components/popover/Popover.vue?7034 +7 -0
  104. package/src/components/roundels/Roundel.vue +20 -0
  105. package/src/components/roundels/Roundel.vue?14bf +7 -0
  106. package/src/components/roundels/Roundel.vue?a97a +1 -0
  107. package/src/components/roundels/Roundel.vue?aa28 +1 -0
  108. package/src/components/shelf/Shelf.vue +20 -0
  109. package/src/components/shelf/Shelf.vue?50f3 +1 -0
  110. package/src/components/shelf/Shelf.vue?9eba +1 -0
  111. package/src/components/shelf/Shelf.vue?d8e7 +4 -0
  112. package/src/globals/assortments.js +80 -0
  113. package/src/globals/csrf.js +25 -0
  114. package/src/globals/functions.js +166 -0
  115. package/src/globals/products.js +251 -0
  116. package/src/globals/responsive.js +53 -0
  117. package/src/globals/validation.js +8 -0
  118. package/src/globals/variables.js +48 -0
  119. package/src/mixins/productCard.js +151 -0
  120. package/src/styles/js-modules/breakpoints.scss +2 -0
  121. package/index.js +0 -0
@@ -0,0 +1,251 @@
1
+ /* eslint-disable no-prototype-builtins */
2
+
3
+ import { csrf } from './csrf';
4
+ import { Assortments } from './assortments';
5
+ import { Logger } from './functions';
6
+ import { styleNamesIds, styleColours } from './variables';
7
+ import 'whatwg-fetch';
8
+
9
+ export const Products = {
10
+
11
+ /**
12
+ * Fetches a list of products
13
+ * @param {Array} productIds the list of product IDs
14
+ * @returns {Array} returns an array of products
15
+ */
16
+ getProductsById({ productIds }) {
17
+ return new Promise((resolve, reject) => {
18
+ if (!productIds) {
19
+ reject({ error: 'productId is required' });
20
+ return;
21
+ }
22
+
23
+ fetch(`/products?productIds=${productIds}`, {
24
+ 'method': 'GET'
25
+ }).then(response => {
26
+ return resolve(response.json());
27
+ }).catch(error => reject({ error: error }));
28
+ });
29
+ },
30
+
31
+ /**
32
+ * Adds a product to basket
33
+ * @param {Array} productId the product ID to add to basket
34
+ * @param {Number} quantity quantity to add to basket
35
+ * @returns {Object} returns a success/error response
36
+ */
37
+ addToBasket({ productId, quantity = 1 }) {
38
+ return new Promise((resolve, reject) => {
39
+ if (!productId) {
40
+ reject({ error: 'productId is required' });
41
+ return;
42
+ }
43
+
44
+ const headers = new Headers(csrf.header);
45
+ const formData = new FormData();
46
+ formData.append('productId', productId.toString());
47
+ formData.append('quantity', quantity.toString());
48
+
49
+ fetch('/customer/add-to-cart.json', {
50
+ 'method': 'POST',
51
+ 'headers': headers,
52
+ 'body': formData
53
+ }).then(response => {
54
+ return resolve(response.json());
55
+ }).catch(error => reject({ error: error }));
56
+ });
57
+ },
58
+
59
+ /**
60
+ * Displays an add to basket notification in the header
61
+ * @param {String} productName the product name to display
62
+ */
63
+ showATBConfirmation(productName) {
64
+ if (window && window.Notify && window.Notify.CoinPurse) {
65
+ const config = {
66
+ settings: { purseType: 'product-added' },
67
+ productName: productName,
68
+ autoDismiss: true,
69
+ timeout: 4000
70
+ };
71
+
72
+ window.Notify.CoinPurse.show(config.settings, config.productName, config.autoDismiss, config.timeout);
73
+
74
+ if (window.nkd && window.nkd.headerCart) {
75
+ window.nkd.headerCart.reload();
76
+ }
77
+ }
78
+ },
79
+
80
+ _parseProduct(data) {
81
+ let model = null;
82
+ let type;
83
+ let imageAssortmentKey;
84
+ let imageMediumCutout = 'mediumCutout';
85
+
86
+ // skip item if it's not in the right format
87
+ if (!data || !data.object) { Logger.log('_parseProduct skipping item', "'object' property not found"); return null; }
88
+
89
+ // wrap in try catch so we can skip an item if the data is inconsistent
90
+ try {
91
+ // use different keys if it's a case rather than a single product
92
+ if (data && data.object && data.object.productTypeDesc && data.object.productTypeDesc == 'Case') {
93
+ type = 'case-product';
94
+ imageAssortmentKey = 'headline';
95
+ } else {
96
+ type = 'single-product';
97
+ imageAssortmentKey = 'background';
98
+ }
99
+
100
+ model = {
101
+ id: data.object.id,
102
+ type: type,
103
+ data: {
104
+ id: data.object.id,
105
+ heading: data.object.productName,
106
+ subHeading: null,
107
+ thumbnail: '/merchandising/content/wines/default-content/background.jpg',
108
+ button: null,
109
+ pricesCurrent: {
110
+ prices: {}
111
+ },
112
+ positiveRatingPercentage: null,
113
+ numberOfRatings: null,
114
+ angelOnly: data.object.angelOnly,
115
+ tickpoints: null,
116
+ tickpointsCase: null,
117
+ taste: null,
118
+ originForSpiritsOrBeer: data.object.originForSpiritsOrBeer,
119
+ style: {},
120
+ percentageMatch: null,
121
+ likeThis: null,
122
+ producer: {},
123
+ url: null,
124
+ productTypeDesc: null,
125
+ productQuantity: null,
126
+ scheme: {},
127
+ assortmentObjects: {},
128
+ origin: '',
129
+ wineGrape: '',
130
+ hideFromView: false,
131
+ hideRatings: false,
132
+ specialDelivery: false,
133
+ freeShipping: false,
134
+ bia: {},
135
+ vegan: false,
136
+ vegetarian: false,
137
+ alcoholStrength: null,
138
+ bottleSizeDesc: '',
139
+ promotionalPrice: null,
140
+ angelPrices: false
141
+ }
142
+ };
143
+ // attach ratings
144
+ if (data.object.hasOwnProperty('ratingData')) {
145
+ model.data.positiveRatingPercentage = data.object.ratingData.positiveRatingPercentage;
146
+ model.data.numberOfRatings = data.object.ratingData.numberOfRatings;
147
+ model.data.hideRatings = data.object.ratingData.hideRatings;
148
+ }
149
+ // attach pricing
150
+ if (data.object.pricesCurrent && data.object.pricesCurrent.prices) {
151
+ model.data.pricesCurrent.prices = data.object.pricesCurrent.prices;
152
+ // attach ATB button (customer price)
153
+ if (data.object.pricesCurrent.prices.customerPrice) { model.data.button = data.object.pricesCurrent.prices.customerPrice; }
154
+ }
155
+ if (data.object.assortmentObjects) {
156
+ // attach thumbnail image
157
+ let thumbnail = Assortments._getAssortmentObject(data.object.assortmentObjects, imageAssortmentKey);
158
+ if (thumbnail) model.data.thumbnail = thumbnail;
159
+ // attach bottleImage
160
+ let bottleImage = Assortments._getAssortmentObject(data.object.assortmentObjects, imageMediumCutout);
161
+ if (bottleImage) model.data.bottleImage = bottleImage;
162
+ // attach tickpoints
163
+ let tickpoints = Assortments._getAssortmentObject(data.object.assortmentObjects, 'whatWeThink');
164
+ if (tickpoints) model.data.tickpoints = tickpoints;
165
+ let tickpointsCase = Assortments._getAssortmentObject(data.object.assortmentObjects, 'whatWeSay');
166
+ if (tickpointsCase) model.data.tickpointsCase = tickpointsCase;
167
+ }
168
+ // attach style data
169
+ if (data.object.taste) {
170
+ model.data.style = this._getWineStyleByName(data.object.taste);
171
+ // attach sub style data (modern/classic)
172
+ if (data.object.productSubStyle) { model.data.style.subStyle = data.object.productSubStyle.toLowerCase(); }
173
+ }
174
+ // attach producer data
175
+ if (data.object.producer) {
176
+ model.data.producer.firstName = data.object.producer.firstName;
177
+ model.data.producer.lastName = data.object.producer.lastName;
178
+ model.data.producer.url = data.object.producer.url;
179
+ model.data.producer.urlString = data.object.producer.urlString;
180
+ }
181
+ // attach url
182
+ if (data.object.url) { model.data.url = data.object.url; }
183
+ // attach percentage match and like this
184
+ if (data.object.customerProductLikeThis) {
185
+ let likeData = data.object.customerProductLikeThis;
186
+
187
+ if (likeData.hasOwnProperty('likeThis')) { model.data.likeThis = likeData.likeThis; }
188
+
189
+ if (likeData.custProdRecommendation && likeData.custProdRecommendation.hasOwnProperty('score')) {
190
+ model.data.percentageMatch = likeData.custProdRecommendation.score;
191
+ const percVal = likeData.custProdRecommendation.score;
192
+ let formatted = (typeof percVal !== 'number') ? percVal : `${(percVal * 100).toFixed(0)}%`;
193
+ model.data.percentageMatchFormatted = formatted;
194
+ model.data.subHeading = formatted + ' Match';
195
+ }
196
+ }
197
+ // attach type description
198
+ if (data.object.productTypeDesc) { model.data.productTypeDesc = data.object.productTypeDesc; }
199
+ // attach product quantity
200
+ if (data.object.productQuantity) { model.data.productQuantity = data.object.productQuantity; }
201
+ // attached bottle quantity
202
+ if(data.object.quantity) { model.data.quantity = data.object.quantity; }
203
+ // attach scheme
204
+ if (data.object.scheme && data.object.scheme.id) { model.data.scheme = data.object.scheme; }
205
+ // attach assortment objects
206
+ if (data.object.assortmentObjects && data.object.assortmentObjects.objects && data.object.assortmentObjects.objects.length > 0) {
207
+ data.object.assortmentObjects.objects.forEach(ao => {
208
+ model.data.assortmentObjects[ao.name] = ao;
209
+ });
210
+ }
211
+ // attach shipping data
212
+ if (data.object.hasOwnProperty('shipAsCase')) { model.data.shipAsCase = data.object.shipAsCase; }
213
+ if (data.object.hasOwnProperty('packingSlots')) { model.data.packingSlots = data.object.packingSlots; }
214
+ // attach more info
215
+ if (data.object.hasOwnProperty('origin')) { model.data.origin = data.object.origin; }
216
+ if (data.object.hasOwnProperty('taste')) { model.data.taste = data.object.taste; }
217
+ if (data.object.hasOwnProperty('wineGrape')) { model.data.wineGrape = data.object.wineGrape; }
218
+ if (data.object.hasOwnProperty('hideFromView')) { model.data.hideFromView = data.object.hideFromView; }
219
+ if (data.object.hasOwnProperty('specialDelivery')) { model.data.specialDelivery = data.object.specialDelivery; }
220
+ if (data.object.hasOwnProperty('freeShipping')) { model.data.freeShipping = data.object.freeShipping; }
221
+ if (data.object.productRatingBreakdownList && data.object.productRatingBreakdownList.length > 0) { model.data.bia = data.object.productRatingBreakdownList[0]; }
222
+ if (data.object.hasOwnProperty('vegan')) { model.data.vegan = data.object.vegan; }
223
+ if (data.object.hasOwnProperty('vegetarian')) { model.data.vegetarian = data.object.vegetarian; }
224
+ if (data.object.hasOwnProperty('alcoholStrength')) { model.data.alcoholStrength = data.object.alcoholStrength; }
225
+ if (data.object.hasOwnProperty('bottleSizeDesc')) { model.data.bottleSizeDesc = data.object.bottleSizeDesc; }
226
+ if (data.object.hasOwnProperty('averageRating')) { model.data.averageRating = data.object.averageRating; }
227
+ if (data.object.hasOwnProperty('region')) { model.data.region = data.object.region; }
228
+ // for free bottles
229
+ if(data.promotionalPrice !== null && data.promotionalPrice === 0) { model.data.promotionalPrice = data.promotionalPrice; }
230
+ if(data.angelPrices !== null) { model.data.angelPrices = data.angelPrices; }
231
+ }
232
+ catch(error) { console.error('_parseProduct skipping item', error); return null; }
233
+ return model;
234
+ },
235
+
236
+ // get the wine style from data prop
237
+ _getWineStyleByName(styleName) {
238
+ let result = {};
239
+ if (!styleName) return result;
240
+ if (styleNamesIds[styleName]) {
241
+ let styleId = styleNamesIds[styleName];
242
+ let colours = styleColours[styleId];
243
+ result = {
244
+ name: styleName,
245
+ id: styleId,
246
+ colours: colours
247
+ };
248
+ }
249
+ return result;
250
+ },
251
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Method used for creating the computed breakpoint objects
3
+ * for use.
4
+ * @param {[Object, Number]} propToUse - the prop to use for creating the object
5
+ * @param {Object} defaults - default settings to use
6
+ * @return {Object} - containing breakpoints and values
7
+ */
8
+ export function getResponsiveOption(propToUse, defaults) {
9
+ if (propToUse && typeof propToUse === 'object') {
10
+ let obj = {};
11
+ for (let index = 0; index < Object.keys(defaults).length; index++) {
12
+ const breakpointProp = Object.keys(defaults)[index];
13
+ const breakpointPropValue = propToUse[breakpointProp];
14
+ // if propToUse declares a breakpoint, apply to this breakpoint and up
15
+ if (breakpointPropValue || (typeof breakpointPropValue === 'number' && breakpointPropValue === 0)) {
16
+ for (let remaining = index; remaining < Object.keys(defaults).length; remaining++) {
17
+ obj[Object.keys(defaults)[remaining]] = breakpointPropValue;
18
+ }
19
+ }
20
+ // fallback if not created yet, uses defaults equivalent value
21
+ else if (!obj[breakpointProp]) {
22
+ obj[breakpointProp] = defaults[breakpointProp];
23
+ }
24
+ }
25
+ return obj;
26
+ }
27
+ else if (propToUse && typeof propToUse === 'number') {
28
+ // Number defined, apply to all breakpoints
29
+ let obj = {};
30
+ for (let index = 0; index < Object.keys(defaults).length; index++) {
31
+ const breakpointProp = Object.keys(defaults)[index];
32
+ obj[breakpointProp] = propToUse;
33
+ }
34
+ return obj;
35
+ }
36
+ else {
37
+ // if responsive prop not defined, just use defaults
38
+ return defaults;
39
+ }
40
+ }
41
+
42
+ import { breakpoints } from './variables.js';
43
+ export function getCurrentBreakpoint() {
44
+ let ret;
45
+ for (let index = 0; index < Object.keys(breakpoints).length; index++) {
46
+ const breakProp = Object.keys(breakpoints)[index];
47
+ if (window.innerWidth < breakpoints[breakProp]) {
48
+ ret = (index === 0) ? 'xs' : Object.keys(breakpoints)[index-1];
49
+ break;
50
+ }
51
+ }
52
+ return ret ? ret : 'xl';
53
+ }
@@ -0,0 +1,8 @@
1
+ export function getValidationMessage(element, options) {
2
+ const defaults = {
3
+ fallback: 'Input not valid, please try something else'
4
+ };
5
+ const opt = Object.assign({}, defaults, options);
6
+
7
+ return element.validationMessage != null ? element.validationMessage : opt.fallback;
8
+ }
@@ -0,0 +1,48 @@
1
+ import sassBreakpoints from '../styles/js-modules/breakpoints.scss';
2
+
3
+ export const breakpoints = {
4
+ xs: parseInt(sassBreakpoints.breakpointXs), // mobile min (iphone 5/se)
5
+ sm: parseInt(sassBreakpoints.breakpointSm), // large mobile
6
+ md: parseInt(sassBreakpoints.breakpointMd), // tablet
7
+ lg: parseInt(sassBreakpoints.breakpointLg), // desktop
8
+ xl: parseInt(sassBreakpoints.breakpointXl), // wide
9
+ };
10
+
11
+ export const styleNamesIds = {
12
+ 'Crisp White': 'WHITE_CRISP',
13
+ 'Fruity White': 'WHITE_FRUITY',
14
+ 'Rich White': 'WHITE_RICH',
15
+ 'Sweet White': 'WHITE_SWEET',
16
+ 'Fruity Red': 'RED_FRUITY',
17
+ 'Smooth Red': 'RED_SMOOTH',
18
+ 'Big Red': 'RED_BIG',
19
+ 'Rose': 'ROSE',
20
+ 'Sparkling': 'SPARKLING',
21
+ 'Dessert & Fortified': 'DESSERT_FORTIFIED'
22
+ };
23
+
24
+ export const styleIdsNames = {
25
+ WHITE_CRISP: 'Crisp White',
26
+ WHITE_FRUITY: 'Fruity White',
27
+ WHITE_RICH: 'Rich White',
28
+ WHITE_SWEET: 'Sweet White',
29
+ RED_FRUITY: 'Fruity Red',
30
+ RED_SMOOTH: 'Smooth Red',
31
+ RED_BIG: 'Big Red',
32
+ ROSE: 'Rosé',
33
+ SPARKLING: 'Sparkling',
34
+ DESSERT_FORTIFIED: 'Dessert & Fortified'
35
+ };
36
+
37
+ export const styleColours = {
38
+ WHITE_CRISP: { primary: '#CCD402', secondary: '#BAC106' },
39
+ WHITE_FRUITY: { primary: '#5A8C24', secondary: '#4F7A17' },
40
+ WHITE_RICH: { primary: '#E8BC02', secondary: '#D4AC04' },
41
+ WHITE_SWEET: { primary: '#01A6B4', secondary: '#068F9A' },
42
+ RED_FRUITY: { primary: '#AC0F63', secondary: '#8E0C51' },
43
+ RED_SMOOTH: { primary: '#E4481D', secondary: '#CF3D15' },
44
+ RED_BIG: { primary: '#552681', secondary: '#451B6D' },
45
+ ROSE: { primary: '#E86D83', secondary: '#DC6378' },
46
+ SPARKLING: { primary: '#AC8A4D', secondary: '#9C7C43' },
47
+ DESSERT_FORTIFIED: { primary: '#151432', secondary: '#06061C' },
48
+ };
@@ -0,0 +1,151 @@
1
+ import { convertStyleCodeToClassName } from '../globals/functions';
2
+ import { Products } from '../globals/products.js';
3
+ const bottleShotPlaceHolderPath = '/merchandising/content/placeholders/wine-bottle-placeholder.png';
4
+
5
+ const productCard = {
6
+ props: {
7
+ product: {
8
+ type: Object,
9
+ required: false
10
+ },
11
+ recommendationType: {
12
+ type: String,
13
+ required: false,
14
+ default: 'bia'
15
+ },
16
+ styleBar: {
17
+ type: Boolean,
18
+ required: false,
19
+ default: false
20
+ },
21
+ type: {
22
+ type: String,
23
+ required: false
24
+ }
25
+ },
26
+
27
+ computed: {
28
+ productData() {
29
+ let product = this.product;
30
+
31
+ if(product && product.data) {
32
+ return product.data
33
+ } else {
34
+ return null;
35
+ }
36
+ },
37
+
38
+ typeBia() {
39
+ return this.recommendationType === 'bia' &&
40
+ this.productData.bia &&
41
+ this.productData.bia.positiveRatingPercentage;
42
+ },
43
+
44
+ typePercentagematch() {
45
+ return this.recommendationType === 'percentageMatch' &&
46
+ this.productData.percentageMatchFormatted;
47
+ },
48
+
49
+ percentageMatchNumber() {
50
+ let score = null,
51
+ productData = this.productData;
52
+
53
+ if(
54
+ productData.customerProductLikeThis &&
55
+ productData.customerProductLikeThis.custProdRecommendation &&
56
+ productData.customerProductLikeThis.custProdRecommendation.score
57
+ ) {
58
+ score = productData.customerProductLikeThis.custProdRecommendation.score;
59
+ score * 100;
60
+ }
61
+
62
+ return score;
63
+ },
64
+
65
+ itemPriceString() { return `${this.currencySymbol == '&#36;' ? '$' : '£'}${this.productData.pricesCurrent.prices.customerPrice.toFixed(2)}` },
66
+
67
+ productImage() {
68
+ if (this.productData.bottleImage) { return window.staticImageUrl + this.productData.bottleImage; }
69
+ else {
70
+ let find = false;
71
+
72
+ if (this.productData.assortmentObjects.objects) {
73
+ find = this.productData.assortmentObjects.objects.findIndex(item => item.name == "mediumCutout");
74
+ }
75
+
76
+ if(find) {
77
+ return window.staticImageUrl + this.productData.assortmentObjects.objects[find].contentPath;
78
+ } else {
79
+ return window.staticImageUrl + bottleShotPlaceHolderPath;
80
+ }
81
+ }
82
+ },
83
+
84
+ caseImage() {
85
+ // TODO: Tidy up - maybe include default placeholder image here if not available?
86
+ if (this.productData.bottleImage) { return window.staticImageUrl + this.productData.bottleImage; }
87
+ else { return window.staticImageUrl + this.productData.assortmentObjects.headline.contentPath; }
88
+ },
89
+
90
+ hasActionSlot() {
91
+ return !!this.$slots.action
92
+ }
93
+ },
94
+
95
+ methods: {
96
+ styleCodeClassName(product) {
97
+ if(product && product.style && product.style.id) {
98
+ return convertStyleCodeToClassName(product.style.id)
99
+ } else {
100
+ return null;
101
+ }
102
+ },
103
+
104
+ bottleShot(product) {
105
+ if (product.bottleImage) {
106
+ return window.staticImageUrl + product.bottleImage;
107
+ } else {
108
+ let find = false;
109
+
110
+ if (product.assortmentObjects.objects) {
111
+ find = product.assortmentObjects.objects.findIndex(item => item.name == "mediumCutout");
112
+ }
113
+
114
+ if(find) {
115
+ return window.staticImageUrl + product.assortmentObjects.objects[find].contentPath;
116
+ } else {
117
+ return window.staticImageUrl + bottleShotPlaceHolderPath;
118
+ }
119
+ }
120
+ },
121
+
122
+ parentElement() {
123
+ return this.$el.parentElement;
124
+ },
125
+
126
+ atb: function() {
127
+ if (!this.productData.id) { return false; }
128
+ Products.addToBasket({ productId: this.productData.id, quantity: 1 })
129
+ .then(() => {
130
+ if (window.nkd && window.nkd.headerCart) { window.nkd.headerCart.reload(); }
131
+ window.notificationCentre.notify({
132
+ title: `1x ${this.productData.heading} added to your basket.`,
133
+ text: 'To checkout, please go to the basket page.',
134
+ group: 'header',
135
+ duration: 8000
136
+ });
137
+ });
138
+ },
139
+ goToUrl: function() { window.location = this.productData.url; }
140
+ },
141
+
142
+ filters: {
143
+ nameChopper: function(val) {
144
+ if (!val) { return false; }
145
+ const maxCharactersTitle = 42;
146
+ return val.length >= maxCharactersTitle ? `${val.substring(0, maxCharactersTitle)} ...` : val;
147
+ },
148
+ }
149
+ };
150
+
151
+ export default productCard;
@@ -0,0 +1,2 @@
1
+ // extracted by mini-css-extract-plugin
2
+ module.exports = {"breakpointXs":"320","breakpointSm":"426","breakpointMd":"768","breakpointLg":"993","breakpointXl":"993"};
package/index.js DELETED
File without changes