@blotoutio/providers-shop-gpt-sdk 1.4.0 → 1.6.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 (4) hide show
  1. package/index.cjs.js +426 -13
  2. package/index.js +426 -13
  3. package/index.mjs +426 -13
  4. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -299,9 +299,73 @@ const isoCountries = new Map([
299
299
  ['ZM', 'Zambia'],
300
300
  ['ZW', 'Zimbabwe'],
301
301
  ]);
302
- new Set(isoCountries.keys());
302
+ /**
303
+ * ISO-3166 US state ISO codes
304
+ * @see https://en.wikipedia.org/wiki/ISO_3166-2:US
305
+ * */
306
+ const usStates = new Map([
307
+ ['US-AL', 'Alabama'],
308
+ ['US-AK', 'Alaska'],
309
+ ['US-AZ', 'Arizona'],
310
+ ['US-AR', 'Arkansas'],
311
+ ['US-CA', 'California'],
312
+ ['US-CO', 'Colorado'],
313
+ ['US-CT', 'Connecticut'],
314
+ ['US-DE', 'Delaware'],
315
+ ['US-FL', 'Florida'],
316
+ ['US-GA', 'Georgia'],
317
+ ['US-HI', 'Hawaii'],
318
+ ['US-ID', 'Idaho'],
319
+ ['US-IL', 'Illinois'],
320
+ ['US-IN', 'Indiana'],
321
+ ['US-IA', 'Iowa'],
322
+ ['US-KS', 'Kansas'],
323
+ ['US-KY', 'Kentucky'],
324
+ ['US-LA', 'Louisiana'],
325
+ ['US-ME', 'Maine'],
326
+ ['US-MD', 'Maryland'],
327
+ ['US-MA', 'Massachusetts'],
328
+ ['US-MI', 'Michigan'],
329
+ ['US-MN', 'Minnesota'],
330
+ ['US-MS', 'Mississippi'],
331
+ ['US-MO', 'Missouri'],
332
+ ['US-MT', 'Montana'],
333
+ ['US-NE', 'Nebraska'],
334
+ ['US-NV', 'Nevada'],
335
+ ['US-NH', 'New Hampshire'],
336
+ ['US-NJ', 'New Jersey'],
337
+ ['US-NM', 'New Mexico'],
338
+ ['US-NY', 'New York'],
339
+ ['US-NC', 'North Carolina'],
340
+ ['US-ND', 'North Dakota'],
341
+ ['US-OH', 'Ohio'],
342
+ ['US-OK', 'Oklahoma'],
343
+ ['US-OR', 'Oregon'],
344
+ ['US-PA', 'Pennsylvania'],
345
+ ['US-RI', 'Rhode Island'],
346
+ ['US-SC', 'South Carolina'],
347
+ ['US-SD', 'South Dakota'],
348
+ ['US-TN', 'Tennessee'],
349
+ ['US-TX', 'Texas'],
350
+ ['US-UT', 'Utah'],
351
+ ['US-VT', 'Vermont'],
352
+ ['US-VA', 'Virginia'],
353
+ ['US-WA', 'Washington'],
354
+ ['US-WV', 'West Virginia'],
355
+ ['US-WI', 'Wisconsin'],
356
+ ['US-WY', 'Wyoming'],
357
+ ['US-DC', 'District of Columbia'],
358
+ ['US-AS', 'American Samoa'],
359
+ ['US-GU', 'Guam'],
360
+ ['US-MP', 'Northern Mariana Islands'],
361
+ ['US-PR', 'Puerto Rico'],
362
+ ['US-UM', 'United States Minor Outlying Islands'],
363
+ ['US-VI', 'Virgin Islands, U.S.'],
364
+ ]);
365
+ new Set([...isoCountries.keys(), ...usStates.keys()]);
303
366
 
304
367
  const packageName = 'shopGPT';
368
+ const DEFAULT_MAX_THREAD_AGE = 14;
305
369
  const previewKeyName = 'previewShopGPT';
306
370
 
307
371
  const canLog = () => {
@@ -381,6 +445,7 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
381
445
  }
382
446
  const data = (await response.json());
383
447
  return {
448
+ messageId: data.messageId,
384
449
  message: data.message,
385
450
  products: (_a = data.products) === null || _a === void 0 ? void 0 : _a.filter((item) => !!item).map((item) => ({ ...item, quantity: 1 })),
386
451
  chatTitle: data.chatTitle,
@@ -451,6 +516,20 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
451
516
  throw new Error(`Failed to delete all chat threads - ${response.status}: ${await response.text()}`);
452
517
  }
453
518
  };
519
+ const saveFeedback = async (messageId, feedback) => {
520
+ const response = await fetchImpl(getURL('/feedback'), {
521
+ method: 'POST',
522
+ headers: getHeaders(),
523
+ credentials: 'include',
524
+ body: JSON.stringify({
525
+ messageId,
526
+ feedback,
527
+ }),
528
+ });
529
+ if (!response.ok) {
530
+ throw new Error(`Failed to save feedback - ${response.status}: ${await response.text()}`);
531
+ }
532
+ };
454
533
  return {
455
534
  processQuery,
456
535
  fetchChatHistory,
@@ -458,6 +537,7 @@ const createShopGPTAPI = ({ fetch: fetchImpl = window.fetch, baseURL, userId, st
458
537
  createChatThread,
459
538
  deleteSingleThread,
460
539
  deleteAllThreads,
540
+ saveFeedback,
461
541
  };
462
542
  };
463
543
 
@@ -491,7 +571,7 @@ const init = (params) => {
491
571
  // exit if not in top window
492
572
  return;
493
573
  }
494
- const { enabled, devMode, merchantUrl, profiles, productHandles, targetPath, uiMode, brandName, quickPrompts, merchantImage, } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
574
+ const { enabled, devMode, merchantUrl, profiles, productHandles, targetPath, uiMode, brandName, quickPrompts, merchantImage, latestThreadLoad, } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
495
575
  let shouldShowUI = enabled;
496
576
  if (!enabled && hasPreviewKey()) {
497
577
  logger.log('Enabling UI in preview mode');
@@ -520,6 +600,7 @@ const init = (params) => {
520
600
  brandName,
521
601
  quickPrompts,
522
602
  merchantImage,
603
+ latestThreadLoad: latestThreadLoad !== null && latestThreadLoad !== void 0 ? latestThreadLoad : DEFAULT_MAX_THREAD_AGE,
523
604
  });
524
605
  }
525
606
  };
@@ -1581,14 +1662,18 @@ class ProductsList extends r$2 {
1581
1662
  super(...arguments);
1582
1663
  this.showButtons = true;
1583
1664
  this.updateButtonsState = () => {
1584
- if (!this.leftBtnEle || !this.productsEle || !this.rightBtnEle) {
1665
+ if (!this.productsEle) {
1585
1666
  return;
1586
1667
  }
1587
1668
  const { scrollWidth, clientWidth } = this.productsEle;
1588
1669
  this.showButtons = scrollWidth > clientWidth;
1589
- this.leftBtnEle.classList.toggle('disabled', this.productsEle.scrollLeft === 0);
1670
+ if (this.leftBtnEle) {
1671
+ this.leftBtnEle.classList.toggle('disabled', this.productsEle.scrollLeft === 0);
1672
+ }
1590
1673
  const maxScroll = this.productsEle.scrollWidth - this.productsEle.clientWidth;
1591
- this.rightBtnEle.classList.toggle('disabled', this.productsEle.scrollLeft >= maxScroll - 1);
1674
+ if (this.rightBtnEle) {
1675
+ this.rightBtnEle.classList.toggle('disabled', this.productsEle.scrollLeft >= maxScroll - 1);
1676
+ }
1592
1677
  };
1593
1678
  }
1594
1679
  connectedCallback() {
@@ -1996,6 +2081,26 @@ const chatSectionStyles = i$4 `
1996
2081
  }
1997
2082
  }
1998
2083
 
2084
+ .bot-response-actions {
2085
+ display: flex;
2086
+ margin-left: 12px;
2087
+ margin-top: -10px;
2088
+
2089
+ button {
2090
+ display: flex;
2091
+ align-items: center;
2092
+ justify-content: center;
2093
+ padding: 8px;
2094
+ background: none;
2095
+ color: rgb(140, 137, 156);
2096
+ border-radius: 50%;
2097
+
2098
+ &:hover {
2099
+ background-color: rgba(47, 43, 61, 0.08);
2100
+ }
2101
+ }
2102
+ }
2103
+
1999
2104
  .bot-icon {
2000
2105
  display: flex;
2001
2106
  padding: 8px 11px;
@@ -2255,6 +2360,18 @@ const timerBtn = b `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="2
2255
2360
  const crossBtn = b `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
2256
2361
  <path d="M18 7.05L16.95 6L12 10.95L7.05 6L6 7.05L10.95 12L6 16.95L7.05 18L12 13.05L16.95 18L18 16.95L13.05 12L18 7.05Z" fill="white"/>
2257
2362
  </svg>`;
2363
+ const thumbsUpBtn = b `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--tabler" font-size="1.375rem" width="1em" height="1em" viewBox="0 0 24 24">
2364
+ <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 11v8a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1h3a4 4 0 0 0 4-4V6a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1-2 2h-7a3 3 0 0 1-3-3"></path>
2365
+ </svg>`;
2366
+ const thumbsUpFilledBtn = b `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--tabler" font-size="1.375rem" width="1em" height="1em" viewBox="0 0 24 24">
2367
+ <path fill="currentColor" d="M13 3a3 3 0 0 1 2.995 2.824L16 6v4h2a3 3 0 0 1 2.98 2.65l.015.174L21 13l-.02.196l-1.006 5.032c-.381 1.626-1.502 2.796-2.81 2.78L17 21H9a1 1 0 0 1-.993-.883L8 20l.001-9.536a1 1 0 0 1 .5-.865a3 3 0 0 0 1.492-2.397L10 7V6a3 3 0 0 1 3-3m-8 7a1 1 0 0 1 .993.883L6 11v9a1 1 0 0 1-.883.993L5 21H4a2 2 0 0 1-1.995-1.85L2 19v-7a2 2 0 0 1 1.85-1.995L4 10z"></path>
2368
+ </svg>`;
2369
+ const thumbsDownBtn = b `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--tabler" font-size="1.375rem" width="1em" height="1em" viewBox="0 0 24 24">
2370
+ <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7 13V5a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2-2l-1-5a2 3 0 0 0-2-2h-7a3 3 0 0 0-3 3"></path>
2371
+ </svg>`;
2372
+ const thumbsDownFilledBtn = b `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--tabler" font-size="1.375rem" width="1em" height="1em" viewBox="0 0 24 24">
2373
+ <path fill="currentColor" d="M13 21.008a3 3 0 0 0 2.995-2.823l.005-.177v-4h2a3 3 0 0 0 2.98-2.65l.015-.173l.005-.177l-.02-.196l-1.006-5.032c-.381-1.625-1.502-2.796-2.81-2.78L17 3.008H9a1 1 0 0 0-.993.884L8 4.008l.001 9.536a1 1 0 0 0 .5.866a3 3 0 0 1 1.492 2.396l.007.202v1a3 3 0 0 0 3 3m-8-7a1 1 0 0 0 .993-.883L6 13.008v-9a1 1 0 0 0-.883-.993L5 3.008H4A2 2 0 0 0 2.005 4.86L2 5.01v7a2 2 0 0 0 1.85 1.994l.15.005h1z"></path>
2374
+ </svg>`;
2258
2375
 
2259
2376
  const personalizeDialogStyles = i$4 `
2260
2377
  :host {
@@ -3158,6 +3275,212 @@ if (!customElements.get('confirm-dialog')) {
3158
3275
  customElements.define('confirm-dialog', ConfirmDialog);
3159
3276
  }
3160
3277
 
3278
+ const feedbackDialogStyles = i$4 `
3279
+ :host {
3280
+ font-family: 'Inter', sans-serif;
3281
+ font-size: 16px;
3282
+ line-height: 24px;
3283
+ font-weight: 400;
3284
+
3285
+ display: flex;
3286
+ position: absolute;
3287
+ top: 0;
3288
+ left: 0;
3289
+ width: 100%;
3290
+ height: 100%;
3291
+ background: #00000050;
3292
+ }
3293
+
3294
+ .modal {
3295
+ width: 75%;
3296
+ max-width: 400px;
3297
+ background: #fff;
3298
+ padding: 24px;
3299
+ margin: auto;
3300
+
3301
+ border-radius: 8px;
3302
+ box-shadow: rgba(47, 43, 61, 0.28) 0px 8px 23px 0px;
3303
+
3304
+ z-index: 2000;
3305
+ }
3306
+
3307
+ .header {
3308
+ display: flex;
3309
+ justify-content: space-between;
3310
+ align-items: center;
3311
+ margin-bottom: 16px;
3312
+ }
3313
+
3314
+ .close {
3315
+ display: flex;
3316
+ justify-content: center;
3317
+ align-items: center;
3318
+ cursor: pointer;
3319
+ }
3320
+
3321
+ h3 {
3322
+ margin: 0;
3323
+ font-size: 20px;
3324
+ font-weight: 700;
3325
+ color: #172a41;
3326
+ line-height: 24px;
3327
+ }
3328
+
3329
+ form {
3330
+ display: flex;
3331
+ flex-direction: column;
3332
+ gap: 12px;
3333
+ margin: 0;
3334
+ }
3335
+
3336
+ textarea {
3337
+ padding: 16px;
3338
+ border: 1px solid #2f2b3d28;
3339
+ border-radius: 10px;
3340
+ font-size: 16px;
3341
+ resize: none;
3342
+ min-height: 104px;
3343
+ box-sizing: border-box;
3344
+ font-family: inherit;
3345
+ color: #4e647f;
3346
+ font-weight: 500;
3347
+ line-height: 24px;
3348
+
3349
+ &:focus {
3350
+ outline: none;
3351
+ box-shadow: rgba(57, 123, 244, 0.5) 0px 0px 4px;
3352
+ }
3353
+
3354
+ &::placeholder {
3355
+ font-style: italic;
3356
+ color: #8799af80;
3357
+ }
3358
+ }
3359
+
3360
+ .btns-container {
3361
+ display: flex;
3362
+ gap: 0 8px;
3363
+ margin-left: auto;
3364
+ margin-top: 10px;
3365
+ }
3366
+
3367
+ button {
3368
+ padding: 9px 20px;
3369
+ border: none;
3370
+ border-radius: 5px;
3371
+ cursor: pointer;
3372
+ }
3373
+
3374
+ .btn-skip {
3375
+ background-color: #dbe2eb;
3376
+ color: #172a41;
3377
+ font-weight: 500;
3378
+
3379
+ &:hover {
3380
+ background-color: rgb(219, 226, 235);
3381
+ }
3382
+ }
3383
+
3384
+ .btn-submit-feedback {
3385
+ background-color: rgb(23, 42, 65);
3386
+ color: #ffffff;
3387
+ font-weight: 500;
3388
+
3389
+ &:hover {
3390
+ background-color: rgb(9, 22, 39);
3391
+ }
3392
+
3393
+ &:disabled {
3394
+ background-color: #e0e0e0;
3395
+ cursor: not-allowed;
3396
+ }
3397
+ }
3398
+ `;
3399
+
3400
+ class FeedbackDialog extends r$2 {
3401
+ dispatchFeedbackEvent(feedback) {
3402
+ this.dispatchEvent(new CustomEvent('submit-feedback', {
3403
+ detail: {
3404
+ messageId: this.messageId,
3405
+ feedback,
3406
+ },
3407
+ composed: true,
3408
+ bubbles: true,
3409
+ }));
3410
+ }
3411
+ handleSubmit(e) {
3412
+ var _a;
3413
+ e.preventDefault();
3414
+ const form = e.target;
3415
+ const data = new FormData(form);
3416
+ this.dispatchFeedbackEvent({
3417
+ rating: 'bad',
3418
+ comment: (_a = data.get('comment')) === null || _a === void 0 ? void 0 : _a.toString().trim(),
3419
+ });
3420
+ form.reset();
3421
+ }
3422
+ handleSkipComment(e) {
3423
+ e.preventDefault();
3424
+ this.comment = '';
3425
+ this.dispatchFeedbackEvent({ rating: 'bad', comment: null });
3426
+ }
3427
+ close(e) {
3428
+ e.preventDefault();
3429
+ this.dispatchEvent(new CustomEvent('close', {
3430
+ composed: true,
3431
+ bubbles: true,
3432
+ }));
3433
+ }
3434
+ render() {
3435
+ return x `
3436
+ <div class="modal">
3437
+ <div class="header">
3438
+ <h3>Provide Additional Feedback</h3>
3439
+ <div class="close" @click=${this.close}>${closeBtn}</div>
3440
+ </div>
3441
+ <form @submit=${this.handleSubmit}>
3442
+ <textarea
3443
+ name="comment"
3444
+ @input=${(e) => { var _a; return (this.comment = (_a = e.target) === null || _a === void 0 ? void 0 : _a.value); }}
3445
+ placeholder="Share your feedback"
3446
+ required
3447
+ >
3448
+ ${this.comment ? this.comment : E}</textarea
3449
+ >
3450
+ <div class="btns-container">
3451
+ <button
3452
+ type="button"
3453
+ class="btn btn-skip"
3454
+ @click=${this.handleSkipComment}
3455
+ >
3456
+ Skip
3457
+ </button>
3458
+ <button
3459
+ type="submit"
3460
+ class="btn btn-submit-feedback"
3461
+ ?disabled=${!this.comment}
3462
+ >
3463
+ Submit
3464
+ </button>
3465
+ </div>
3466
+ </form>
3467
+ </div>
3468
+ `;
3469
+ }
3470
+ }
3471
+ FeedbackDialog.styles = [feedbackDialogStyles];
3472
+ __decorate([
3473
+ n({ type: String }),
3474
+ __metadata("design:type", Object)
3475
+ ], FeedbackDialog.prototype, "messageId", void 0);
3476
+ __decorate([
3477
+ n({ type: String }),
3478
+ __metadata("design:type", Object)
3479
+ ], FeedbackDialog.prototype, "comment", void 0);
3480
+ if (!customElements.get('feedback-dialog')) {
3481
+ customElements.define('feedback-dialog', FeedbackDialog);
3482
+ }
3483
+
3161
3484
  class ChatSection extends r$2 {
3162
3485
  constructor() {
3163
3486
  super(...arguments);
@@ -3205,6 +3528,23 @@ class ChatSection extends r$2 {
3205
3528
  }));
3206
3529
  this.deleteThreadId = '';
3207
3530
  }
3531
+ handleFeedback(rating, messageId, comment) {
3532
+ if (rating === 'bad') {
3533
+ this.feedbackDetails = { messageId, comment };
3534
+ return;
3535
+ }
3536
+ this.dispatchEvent(new CustomEvent('submit-feedback', {
3537
+ detail: {
3538
+ messageId: messageId,
3539
+ feedback: {
3540
+ rating,
3541
+ comment: null,
3542
+ },
3543
+ },
3544
+ composed: true,
3545
+ bubbles: true,
3546
+ }));
3547
+ }
3208
3548
  typingIndicator() {
3209
3549
  return x ` <div class="typing-dots">
3210
3550
  <div class="dot"></div>
@@ -3213,7 +3553,7 @@ class ChatSection extends r$2 {
3213
3553
  </div>`;
3214
3554
  }
3215
3555
  botMessage(message) {
3216
- var _a;
3556
+ var _a, _b, _c, _d, _e;
3217
3557
  return x `
3218
3558
  <div class="message-wrapper">
3219
3559
  <div class="message bot">
@@ -3244,6 +3584,26 @@ class ChatSection extends r$2 {
3244
3584
  .viewType=${this.viewType}
3245
3585
  ></products-list>`
3246
3586
  : E}
3587
+ ${message.messageId
3588
+ ? x `<div class="bot-response-actions">
3589
+ <button
3590
+ type="button"
3591
+ @click=${this.handleFeedback.bind(this, 'good', message.messageId, (_b = message.feedback) === null || _b === void 0 ? void 0 : _b.comment)}
3592
+ >
3593
+ ${((_c = message.feedback) === null || _c === void 0 ? void 0 : _c.rating) === 'good'
3594
+ ? thumbsUpFilledBtn
3595
+ : thumbsUpBtn}
3596
+ </button>
3597
+ <button
3598
+ type="button"
3599
+ @click=${this.handleFeedback.bind(this, 'bad', message.messageId, (_d = message.feedback) === null || _d === void 0 ? void 0 : _d.comment)}
3600
+ >
3601
+ ${((_e = message.feedback) === null || _e === void 0 ? void 0 : _e.rating) === 'bad'
3602
+ ? thumbsDownFilledBtn
3603
+ : thumbsDownBtn}
3604
+ </button>
3605
+ </div>`
3606
+ : E}
3247
3607
  </div>
3248
3608
  `;
3249
3609
  }
@@ -3264,10 +3624,19 @@ class ChatSection extends r$2 {
3264
3624
  </div>`
3265
3625
  : ''}
3266
3626
  ${this.isFailed
3267
- ? this.botMessage({
3268
- sender: 'bot',
3269
- message: "Uh-oh! Looks like I tripped over some alpha-stage wires. Things are still a bit wobbly here, buy hey, that's what testing is for, Let's try that again; or feel free to throw another challenge my way!",
3270
- })
3627
+ ? x `<div class="message bot">
3628
+ <div>
3629
+ <div class="bot-icon">${botIcon}</div>
3630
+ </div>
3631
+ <div>
3632
+ <p>
3633
+ Uh-oh! Looks like I tripped over some alpha-stage wires.
3634
+ Things are still a bit wobbly here, buy hey, that's what
3635
+ testing is for, Let's try that again; or feel free to throw
3636
+ another challenge my way!
3637
+ </p>
3638
+ </div>
3639
+ </div>`
3271
3640
  : E}
3272
3641
  ${this.messages.map((message) => {
3273
3642
  if (message.sender === 'bot') {
@@ -3299,7 +3668,7 @@ class ChatSection extends r$2 {
3299
3668
  ? this.messages[0].welcomePrompts
3300
3669
  : this.prompts
3301
3670
  ? this.prompts.split(',').map((prompt) => prompt.trim())
3302
- : ['Best Selling Items', 'Hot Sales'];
3671
+ : ['Best Sellers'];
3303
3672
  if (!prompts) {
3304
3673
  return E;
3305
3674
  }
@@ -3611,6 +3980,21 @@ class ChatSection extends r$2 {
3611
3980
  </confirm-dialog>
3612
3981
  `
3613
3982
  : E}
3983
+ ${this.feedbackDetails
3984
+ ? x `
3985
+ <feedback-dialog
3986
+ .messageId=${this.feedbackDetails.messageId}
3987
+ .comment=${this.feedbackDetails.comment}
3988
+ @submit-feedback=${() => {
3989
+ this.feedbackDetails = undefined;
3990
+ }}
3991
+ @close=${(e) => {
3992
+ e.stopPropagation();
3993
+ this.feedbackDetails = undefined;
3994
+ }}
3995
+ ></feedback-dialog>
3996
+ `
3997
+ : E}
3614
3998
  `;
3615
3999
  }
3616
4000
  }
@@ -3695,6 +4079,10 @@ __decorate([
3695
4079
  e$3('personalize-dialog'),
3696
4080
  __metadata("design:type", Object)
3697
4081
  ], ChatSection.prototype, "personalizeDialogElement", void 0);
4082
+ __decorate([
4083
+ r(),
4084
+ __metadata("design:type", Object)
4085
+ ], ChatSection.prototype, "feedbackDetails", void 0);
3698
4086
  __decorate([
3699
4087
  n({ type: String }),
3700
4088
  __metadata("design:type", Object)
@@ -3704,11 +4092,11 @@ if (!customElements.get('chat-section')) {
3704
4092
  }
3705
4093
 
3706
4094
  const DIALOG_DELAY = 1000;
3707
- const LATEST_THREAD_LOAD_DAYS = 14;
3708
4095
  const normalizePath = (path) => path.replace(/\/$/, '');
3709
4096
  class ShopGPT extends r$2 {
3710
4097
  constructor() {
3711
4098
  super(...arguments);
4099
+ this.latestThreadLoad = DEFAULT_MAX_THREAD_AGE;
3712
4100
  this.modalState = 'close';
3713
4101
  this.isLoadingHistory = false;
3714
4102
  this.isLoadingThreads = false;
@@ -3815,6 +4203,7 @@ class ShopGPT extends r$2 {
3815
4203
  }
3816
4204
  this.messages = [
3817
4205
  {
4206
+ messageId: reply.messageId,
3818
4207
  sender: 'bot',
3819
4208
  message: reply.message,
3820
4209
  products: reply.products,
@@ -3846,7 +4235,7 @@ class ShopGPT extends r$2 {
3846
4235
  }
3847
4236
  }
3848
4237
  selectLatestThread() {
3849
- const cutoffTime = Date.now() - LATEST_THREAD_LOAD_DAYS * 24 * 60 * 60 * 1000;
4238
+ const cutoffTime = Date.now() - this.latestThreadLoad * 24 * 60 * 60 * 1000;
3850
4239
  // If the latest thread is not older than cutoff we should load the thread
3851
4240
  let latestThread;
3852
4241
  for (const thread of this.chatThreads.values()) {
@@ -3882,10 +4271,12 @@ class ShopGPT extends r$2 {
3882
4271
  latestAvailableProducts = products;
3883
4272
  }
3884
4273
  return {
4274
+ messageId: message.messageId,
3885
4275
  message: message.message,
3886
4276
  sender: message.sender,
3887
4277
  products,
3888
4278
  welcomePrompts: message.welcomePrompts,
4279
+ feedback: message.feedback,
3889
4280
  };
3890
4281
  });
3891
4282
  this.products = latestAvailableProducts;
@@ -3966,6 +4357,7 @@ class ShopGPT extends r$2 {
3966
4357
  }
3967
4358
  this.messages = [
3968
4359
  {
4360
+ messageId: reply.messageId,
3969
4361
  sender: 'bot',
3970
4362
  message: reply.message,
3971
4363
  products: reply.products,
@@ -3985,6 +4377,20 @@ class ShopGPT extends r$2 {
3985
4377
  this.isTyping = false;
3986
4378
  }
3987
4379
  }
4380
+ submitFeedback(e) {
4381
+ e.stopPropagation();
4382
+ this.shopGPTAPI
4383
+ .saveFeedback(e.detail.messageId, e.detail.feedback)
4384
+ .then(() => {
4385
+ const messages = this.messages;
4386
+ const messageIndex = messages.findIndex(({ messageId }) => messageId === e.detail.messageId);
4387
+ messages[messageIndex] = {
4388
+ ...messages[messageIndex],
4389
+ feedback: e.detail.feedback,
4390
+ };
4391
+ this.messages = [...messages];
4392
+ });
4393
+ }
3988
4394
  getSiteCurrency() {
3989
4395
  return this.storeAPI.getSiteCurrency();
3990
4396
  }
@@ -4001,6 +4407,7 @@ class ShopGPT extends r$2 {
4001
4407
  id="shop-gpt-dialog-overlay"
4002
4408
  @delete-thread=${this.handleThreadDelete}
4003
4409
  @delete-all-threads=${this.handleAllThreadsDelete}
4410
+ @submit-feedback=${this.submitFeedback}
4004
4411
  >
4005
4412
  <div class="mobile-version">
4006
4413
  Please switch to the desktop version for the best experience.
@@ -4065,6 +4472,7 @@ class ShopGPT extends r$2 {
4065
4472
  id="shop-gpt-modal"
4066
4473
  @delete-thread=${this.handleThreadDelete}
4067
4474
  @delete-all-threads=${this.handleAllThreadsDelete}
4475
+ @submit-feedback=${this.submitFeedback}
4068
4476
  >
4069
4477
  <chat-section
4070
4478
  .prompts=${this.quickPrompts}
@@ -4092,6 +4500,10 @@ class ShopGPT extends r$2 {
4092
4500
  }
4093
4501
  }
4094
4502
  ShopGPT.styles = [shopGPTStyles];
4503
+ __decorate([
4504
+ n({ type: Number }),
4505
+ __metadata("design:type", Number)
4506
+ ], ShopGPT.prototype, "latestThreadLoad", void 0);
4095
4507
  __decorate([
4096
4508
  e$3('#shop-gpt-dialog-overlay'),
4097
4509
  __metadata("design:type", Object)
@@ -4158,6 +4570,7 @@ if (typeof window != 'undefined' && typeof document != 'undefined') {
4158
4570
  shopGPT.brandName = params.brandName;
4159
4571
  shopGPT.quickPrompts = params.quickPrompts;
4160
4572
  shopGPT.merchantImage = params.merchantImage;
4573
+ shopGPT.latestThreadLoad = params.latestThreadLoad;
4161
4574
  document.body.append(shopGPT);
4162
4575
  },
4163
4576
  destroy() {