@nuskin/ns-shop 7.1.0-brw-988.1 → 7.1.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.
@@ -1,389 +0,0 @@
1
- import $ from '@nuskin/nuskinjquery';
2
- import { getCachedConfiguration } from '@nuskin/configuration-sdk';
3
- import { SolrProductAdaptor } from './solrProductAdaptor';
4
- import { CustomerTypes } from '@nuskin/ns-product-lib';
5
-
6
- /**
7
- * Checks if the input string follows a specific SKU format.
8
- * @param {string} str - The input string to be checked.
9
- * @returns {boolean} Returns true if the input string is a valid SKU format, otherwise false.
10
- */
11
- function isSkuFormat(str) {
12
- return typeof str === 'string' && str.length === 8 && /^[a-zA-Z0-9]+$/.test(str);
13
- }
14
-
15
- /**
16
- * Performs a search in the Equinox catalog based on the provided options.
17
- * @param {Promise} deferred - A promise object that resolves when the search is complete.
18
- * @param {Object} options - The search options including searchTerm, rows, language, market.
19
- */
20
- function productSearchAPI(deferred, options) {
21
-
22
- let allProducts = [];
23
- let currentPage = 1;
24
- let baseScore = 5;
25
- const { MySite_search_API_Base_URLs } = getCachedConfiguration('Equinox_Markets');
26
-
27
- /**
28
- * Sends a query to the Equinox catalog API.
29
- * @returns {Promise} A promise that resolves with the query response.
30
- */
31
- function sendQuery(page) {
32
-
33
- const query = `
34
- query ProductSearch(
35
- $sizeOpt: Int
36
- $language: String!
37
- $market: String!
38
- $storeId: String
39
- $searchTerm: String
40
- $filterOpt: String
41
- $sortOpt: String
42
- $pageOpt: Int
43
- ) {
44
- productSearch(
45
- sizeOpt: $sizeOpt
46
- language: $language
47
- market: $market
48
- store_Id: $storeId
49
- searchTerm: $searchTerm
50
- filterOpt: $filterOpt
51
- sortOpt: $sortOpt
52
- pageOpt: $pageOpt
53
- ) {
54
- ProductContent {
55
- products {
56
- error {
57
- errors
58
- }
59
- title
60
- productImages {
61
- url
62
- }
63
- variants {
64
- title
65
- sku
66
- productImages {
67
- url
68
- alt
69
- thumbnail
70
- }
71
- isExclusive
72
- availableChannels
73
- customerTypes
74
- description
75
- searchKeywords
76
- }
77
- bundle {
78
- purchaseTypes {
79
- buyOnce
80
- subscription
81
- }
82
- customerTypes
83
- }
84
- id
85
- }
86
- }
87
- pageableInfo {
88
- Page
89
- Size
90
- Count
91
- TotalCount
92
- }
93
- }
94
- }
95
- `;
96
-
97
- const variables = {
98
- "language": options.language,
99
- "market": options.market,
100
- "sizeOpt": options.rows,
101
- "pageOpt": page,
102
- "searchTerm": options.searchTerm,
103
- "filterOpt": null,
104
- "sortOpt": null
105
- };
106
-
107
- const data = JSON.stringify({
108
- query: query,
109
- variables: variables
110
- });
111
-
112
- return $.ajax({
113
- url: MySite_search_API_Base_URLs,
114
- type: "POST",
115
- contentType: 'application/json; charset=utf-8',
116
- data: data
117
- });
118
- }
119
-
120
- /**
121
- * Extracts relevant information from the product response.
122
- * @param {Object} response - The response from the Equinox catalog API.
123
- * @returns {Object} An object containing products and total number found.
124
- */
125
- function processResponse(response) {
126
- let retValue = {
127
- products: [],
128
- totalNumFound: 0
129
- };
130
-
131
- const result = response.data.productSearch || {};
132
-
133
- if (result.ProductContent && result.ProductContent.products && result.ProductContent.products.length > 0) {
134
- let products = result.ProductContent.products;
135
-
136
- if (options.groupByVariant) {
137
- products = processGroupByVariant(products);
138
- } else {
139
- products = processGroupByParent(products);
140
- }
141
-
142
- retValue = {
143
- products,
144
- totalNumFound: result.pageableInfo.TotalCount
145
- };
146
- }
147
-
148
- return retValue;
149
- }
150
-
151
- /**
152
- * Processes a list of products to be grouped by parent, generating a mapped product structure.
153
- *
154
- * @param {Array} products - The list of products to process.
155
- * @returns {Array} An array of mapped products with child documents for each variant.
156
- */
157
- function processGroupByParent(products) {
158
- let mappedProducts = [];
159
-
160
- //clean up null data (a lot exists in test environment)
161
- products = products.filter((product) => {
162
- if(product.error) {
163
- console.log('Removed Products with error' , product.error)
164
- }
165
-
166
- return !product.error
167
- })
168
-
169
- products.forEach((parentProduct) => {
170
- let mappedParentProduct = parentProduct;
171
-
172
- if (!isSkuFormat(parentProduct.id) && parentProduct.variants && parentProduct.variants.length > 0) {
173
- mappedParentProduct = parentProduct.variants[0];
174
- } else {
175
- mappedParentProduct.sku = parentProduct.id;
176
- mappedParentProduct.variants = [];
177
- mappedParentProduct.variants.push({ ...mappedParentProduct, sku: parentProduct.id });
178
- }
179
-
180
- let indexDocuments = parentProduct.variants.map((variant) => {
181
-
182
- let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
183
-
184
- return {
185
- path_exact: `product/${variant.sku}/${options.language}`,
186
- sku: [`${variant.sku}`],
187
- markets: [`${options.market}`],
188
- variantType: [""],
189
- name: [`${variant.title}`],
190
- shortDescription: variant.description,
191
- longDescription: variant.description,
192
- searchTerms: variant.searchKeywords,
193
- isExclusive: mappedParentProduct.isExclusive || "false",
194
- custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
195
- statusCode: ["10"],
196
- orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
197
- _root_: [`product/${mappedParentProduct.sku}`]
198
- };
199
- });
200
-
201
- let mySiteIndexDocuments = parentProduct.variants.map((variant) => {
202
-
203
- let orderTypes = mapOrderTypes(variant.availableChannels, variant.bundle ? variant.bundle.purchaseTypes : undefined);
204
-
205
- return {
206
- path_exact: `product/${variant.sku}/${options.market.toUpperCase()}`,
207
- sku: [`${variant.sku}`],
208
- searchTerms: variant.searchKeywords,
209
- orderType: Object.keys(orderTypes).filter(key => orderTypes[key]),
210
- custType: mapCustomerTypes(variant.bundle ? variant.bundle.customerTypes : variant.customerTypes),
211
- statusCode: ["10"],
212
- webEnabled: ["true"],
213
- _root_: [`product/${mappedParentProduct.sku}`]
214
- };
215
- });
216
-
217
- indexDocuments = indexDocuments.concat(mySiteIndexDocuments);
218
-
219
- if (indexDocuments.length > 0) {
220
- mappedProducts.push({
221
- path_exact: `product/${mappedParentProduct.sku}`,
222
- languages: [`${options.language.toLowerCase()}`],
223
- markets: [`${options.market.toLowerCase()}`],
224
- sku: [`${mappedParentProduct.sku}`],
225
- _childDocuments_: indexDocuments
226
- });
227
- } else {
228
- console.log('Invalid Product', mappedParentProduct);
229
- }
230
- });
231
-
232
- console.log('Products' , mappedProducts)
233
-
234
- return mappedProducts.map((product) => {
235
- baseScore -= 0.01;
236
- return new SolrProductAdaptor(product, baseScore)
237
- });
238
- }
239
-
240
- /**
241
- * Processes a list of products to be grouped by variant, generating a mapped product structure.
242
- *
243
- * @param {Array} products - The list of products to process.
244
- * @returns {Array} An array of mapped products with a flattened structure.
245
- */
246
- function processGroupByVariant(products) {
247
-
248
- //clean up null data (a lot exists in test environment)
249
- products = products.filter((product) => {
250
- if(product.error) {
251
- console.log('Removed Products with error' , product.error)
252
- }
253
-
254
- return !product.error
255
- })
256
-
257
- let groupedProducts = products.map((v) => {
258
- return v.variants && v.variants.length > 0 ? v.variants : [{ ...v, sku: v.id }];
259
- }).flat();
260
-
261
- groupedProducts = groupedProducts.filter((v) => v !== undefined).map((product) => {
262
- return {
263
- sku: [product.sku],
264
- fullImage: (product.productImages && product.productImages.length > 0) ? product.productImages[0].url : '',
265
- name: product.title || '',
266
- _root_: `product/${product.sku}`,
267
- isExclusive: product.isExclusive || "false"
268
- };
269
- });
270
-
271
- let exactSkuResult = groupedProducts.filter((product) => product.sku[0].toLowerCase() === options.searchTerm.toLowerCase());
272
-
273
- if (isSkuFormat(options.searchTerm) && exactSkuResult.length > 0) {
274
- groupedProducts = exactSkuResult
275
- }
276
-
277
- return groupedProducts;
278
- }
279
-
280
-
281
- /**
282
- * map EQ customer types to supported product card customer types
283
- * @param {Array<string>} eqCustomerTypes
284
- * @returns{string} customer types
285
- */
286
- function mapCustomerTypes(eqCustomerTypes) {
287
- if (!eqCustomerTypes) {
288
- return "";
289
- }
290
-
291
- const custTypes = eqCustomerTypes.map(str => str.toLowerCase());
292
-
293
- let newCustType = [];
294
- if (custTypes.includes(CustomerTypes.BrandAffiliate)) {
295
- newCustType.push(CustomerTypes.properties.BRAND_AFFILIATE.code);
296
- }
297
-
298
- if (custTypes.includes(CustomerTypes.Retail)) {
299
- newCustType.push(CustomerTypes.properties.RETAIL.code);
300
- }
301
-
302
- if (custTypes.includes(CustomerTypes.Preferred) || custTypes.includes(CustomerTypes.PreferredCustomer)) {
303
- newCustType.push(CustomerTypes.properties.PREFERRED.code);
304
- }
305
-
306
- return newCustType.toString().split(",")
307
- }
308
-
309
- /**
310
- * Map Order Types
311
- * @param {Array<string>} availableChannels
312
- * @param {object} purchaseTypes
313
- * @returns {object} orderTypes
314
- */
315
- function mapOrderTypes(availableChannels, purchaseTypes) {
316
-
317
- let orderTypes = {
318
- "adr": false,
319
- "order": false,
320
- "zpfc": false,
321
- "zadp": false,
322
- "ars": false,
323
- "kiosk": false,
324
- "mobile": false,
325
- "preferred customer": false,
326
- "retail": false,
327
- "web": false,
328
- "web display": false
329
- };
330
-
331
- if (availableChannels) {
332
- let availableChannelsArr = Array.isArray(availableChannels) ? availableChannels : availableChannels.split(',');
333
-
334
- availableChannelsArr.forEach(channel => {
335
- if (channel == 'arsPhone')
336
- orderTypes.ars = true
337
- if (channel == 'web') {
338
- orderTypes.order = true
339
- orderTypes.web = true
340
- }
341
- if (channel == 'kiosk')
342
- orderTypes.kiosk = true
343
- if (channel == 'mobile')
344
- orderTypes.mobile = true
345
- if (channel == 'subscription')
346
- orderTypes.adr = true
347
- });
348
- }
349
-
350
- if (purchaseTypes && purchaseTypes.buyOnce) {
351
- orderTypes.web = true
352
- orderTypes.order = true
353
- }
354
- if (purchaseTypes && purchaseTypes.subscription) {
355
- orderTypes.adr = true
356
- }
357
-
358
- return orderTypes;
359
- }
360
-
361
-
362
- function fetchNextPage() {
363
- sendQuery(currentPage)
364
- .then(processResponse)
365
- .then((result) => {
366
- allProducts = allProducts.concat(result.products);
367
- if ((currentPage * options.rows) < result.totalNumFound && !options.groupByVariant) {
368
- currentPage++;
369
- fetchNextPage();
370
- } else {
371
- deferred.resolve({
372
- products: allProducts,
373
- totalNumFound: result.totalNumFound
374
- });
375
- }
376
- })
377
- .catch((error) => {
378
- console.error(error);
379
- deferred.reject(error);
380
- });
381
- }
382
-
383
- fetchNextPage();
384
- }
385
-
386
- export {
387
- productSearchAPI,
388
- isSkuFormat
389
- };