wineater-bot 1.4.1 → 1.4.3

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,4 +1,4 @@
1
- const g = `
1
+ const f = `
2
2
  @font-face {
3
3
  font-family: 'Poppins';
4
4
  src: url('https://fonts.googleapis.com/css2?family=Poppins:wght@400&display=swap');
@@ -273,68 +273,113 @@ const g = `
273
273
  .typing-indicator.visible {
274
274
  visibility: visible;
275
275
  height: 50px;
276
- }`, c = document.createElement("style");
277
- c.textContent = g;
278
- document.head.appendChild(c);
279
- function l() {
280
- const n = document.getElementById("chat-window"), t = document.getElementById("chat-icon");
281
- n.classList.contains("visible") ? (n.classList.remove("visible"), t.style.display = "flex") : (n.classList.add("visible"), t.style.display = "none");
276
+ }`, p = document.createElement("style");
277
+ p.textContent = f;
278
+ document.head.appendChild(p);
279
+ function b(n, e, t) {
280
+ let o = "";
281
+ if (t) {
282
+ const i = /* @__PURE__ */ new Date();
283
+ i.setTime(i.getTime() + t * 24 * 60 * 60 * 1e3), o = "; expires=" + i.toUTCString();
284
+ }
285
+ document.cookie = n + "=" + (e || "") + o + "; path=/; secure; samesite=strict";
286
+ }
287
+ function r(n) {
288
+ const t = `; ${document.cookie}`.split(`; ${n}=`);
289
+ if (t.length === 2)
290
+ return t.pop().split(";").shift();
291
+ }
292
+ function d(n, e) {
293
+ fetch("https://api-eu.mixpanel.com/track", {
294
+ method: "POST",
295
+ headers: {
296
+ "Content-Type": "application/json",
297
+ Authentication: "6f3d90d5b02720f58de3663e3ef675fe"
298
+ },
299
+ body: JSON.stringify({
300
+ event: n,
301
+ properties: e
302
+ })
303
+ }).then((a) => {
304
+ a.ok || console.error("Mixpanel tracking failed", a);
305
+ }).catch((a) => {
306
+ console.error("Mixpanel tracking error", a);
307
+ });
282
308
  }
283
309
  function h() {
284
- document.getElementById("chat-window").classList.remove("visible");
310
+ d("Chatbot Opened", { distinct_id: r("chatbotToken") });
311
+ }
312
+ function g() {
313
+ d("Chatbot Closed", { distinct_id: r("chatbotToken") });
314
+ }
315
+ function y(n) {
316
+ d("Message Sent", { distinct_id: r("chatbotToken"), message_content: n });
317
+ }
318
+ function w(n) {
319
+ d("Message Sent", { distinct_id: r("chatbotToken"), products: n });
320
+ }
321
+ function x(n) {
322
+ d("Product Clicked", { distinct_id: r("chatbotToken"), product_id: n });
285
323
  }
286
324
  function u() {
287
- document.getElementById("chat-window").classList.add("visible");
325
+ const n = document.getElementById("chat-window"), e = document.getElementById("chat-icon");
326
+ n.classList.contains("visible") ? (g(), n.classList.remove("visible"), e.style.display = "flex") : (h(), n.classList.add("visible"), e.style.display = "none");
327
+ }
328
+ function v() {
329
+ g(), document.getElementById("chat-window").classList.remove("visible");
330
+ }
331
+ function k() {
332
+ h(), document.getElementById("chat-window").classList.add("visible");
288
333
  }
289
334
  document.addEventListener("DOMContentLoaded", () => {
290
335
  setupCloseButton(), setupOutsideClick();
291
336
  });
292
- const m = ["climats", "telckel", "biobio", "weinpoint"], f = "OuhXJRleF6sROjsQZPWx1yqjrL6APeJxmHswqyOBWbgIqtXcht3MDadvI9DtOOoL";
293
- class p {
294
- constructor(t) {
295
- var e;
296
- this.baseURL = "https://api.wineater.com/", this.store = m.find((o) => window.location.href.includes(o)), this.token = ((e = window == null ? void 0 : window.wineaterData) == null ? void 0 : e.CLIENT_TOKEN) || f;
337
+ const C = ["climats", "telckel", "biobio", "weinpoint"], E = "OuhXJRleF6sROjsQZPWx1yqjrL6APeJxmHswqyOBWbgIqtXcht3MDadvI9DtOOoL";
338
+ class m {
339
+ constructor(e) {
340
+ var t;
341
+ this.baseURL = "https://api.wineater.com/", this.store = C.find((o) => window.location.href.includes(o)), this.token = ((t = window == null ? void 0 : window.wineaterData) == null ? void 0 : t.CLIENT_TOKEN) || E;
297
342
  }
298
- async getStoreConfig(t) {
299
- console.log(t);
343
+ async getStoreConfig(e) {
344
+ console.log(e);
300
345
  try {
301
- const e = await fetch(`${this.baseURL}stores/store`, {
346
+ const t = await fetch(`${this.baseURL}stores/store`, {
302
347
  method: "POST",
303
348
  headers: {
304
349
  "Content-Type": "application/json",
305
350
  Authorization: `Bearer ${this.token}`
306
351
  },
307
- body: JSON.stringify({ store: t })
352
+ body: JSON.stringify({ store: e })
308
353
  });
309
- if (!e.ok)
310
- throw new Error(`HTTP error! Status: ${e.status}`);
311
- return await e.json();
312
- } catch (e) {
313
- throw console.error("Error fetching store configuration:", e), e;
354
+ if (!t.ok)
355
+ throw new Error(`HTTP error! Status: ${t.status}`);
356
+ return await t.json();
357
+ } catch (t) {
358
+ throw console.error("Error fetching store configuration:", t), t;
314
359
  }
315
360
  }
316
- async getWineRecommendations(t) {
361
+ async getWineRecommendations(e) {
317
362
  console.log(window.location.href);
318
363
  try {
319
- const e = await fetch(`${this.baseURL}dish/recommendations`, {
364
+ const t = await fetch(`${this.baseURL}dish/recommendations`, {
320
365
  method: "POST",
321
366
  headers: {
322
367
  "Content-Type": "application/json",
323
368
  Authorization: `Bearer ${this.token}`
324
369
  },
325
- body: JSON.stringify({ text: t, store: this.store ? this.store.toString().charAt(0).toUpperCase() + this.store.slice(1) : void 0 })
326
- }), o = await e.json();
327
- if (!e.ok)
328
- throw new Error(`API call failed with status ${e.status}: ${o.message || "No additional error information"}`);
370
+ body: JSON.stringify({ text: e, store: this.store ? this.store.toString().charAt(0).toUpperCase() + this.store.slice(1) : void 0 })
371
+ }), o = await t.json();
372
+ if (!t.ok)
373
+ throw new Error(`API call failed with status ${t.status}: ${o.message || "No additional error information"}`);
329
374
  return o;
330
- } catch (e) {
331
- throw console.error("Fetching wine recommendations failed:", e.message), new Error(`Error in getWineRecommendations: ${e.message}`);
375
+ } catch (t) {
376
+ throw console.error("Fetching wine recommendations failed:", t.message), new Error(`Error in getWineRecommendations: ${t.message}`);
332
377
  }
333
378
  }
334
379
  }
335
- class y {
380
+ class I {
336
381
  constructor() {
337
- this.api = new p(), this.language = "en", this.translations = {
382
+ this.api = new m(), this.language = "en", this.translations = {
338
383
  fr: {
339
384
  welcomeMessage: "Sublimez votre expérience gastronomique. Il vous suffit de donner les détails de votre plat, et obtenez la recommandation de compagnon de vin idéale. Que voulez-vous manger?",
340
385
  noResultsFound: "Aucun résultat trouvé.",
@@ -373,36 +418,37 @@ class y {
373
418
  }
374
419
  };
375
420
  }
376
- async fetchConfig(t) {
377
- if (t) {
378
- const e = await this.api.getStoreConfig(t);
379
- this.language = e.lang;
421
+ async fetchConfig(e) {
422
+ if (e) {
423
+ const t = await this.api.getStoreConfig(e);
424
+ this.language = t.lang;
380
425
  }
381
426
  }
382
- translate(t) {
383
- return this.translations[this.language][t] || t;
427
+ translate(e) {
428
+ return this.translations[this.language][e] || e;
384
429
  }
385
430
  }
386
- const s = new y();
387
- class b {
431
+ const s = new I();
432
+ class T {
388
433
  constructor() {
389
- this.api = new p(), this.displayFirstMessage(s.translate("welcomeMessage"));
434
+ this.api = new m(), this.displayFirstMessage(s.translate("welcomeMessage"));
390
435
  }
391
436
  initialize() {
392
437
  document.getElementById("send-button").addEventListener("click", () => this.handleUserInput()), document.getElementById("user-input").addEventListener("keypress", (o) => {
393
438
  o.key === "Enter" && this.handleUserInput();
394
439
  });
395
440
  }
396
- displayFirstMessage(t, e = "api") {
441
+ displayFirstMessage(e, t = "api") {
397
442
  const o = document.getElementById("message-container"), i = document.createElement("div");
398
- i.className = `message ${e}`, i.textContent = t, o.appendChild(i), o.scrollTop = o.scrollHeight;
443
+ i.className = `message ${t}`, i.textContent = e, o.appendChild(i), o.scrollTop = o.scrollHeight;
399
444
  }
400
445
  async handleUserInput() {
401
- const t = document.getElementById("user-input"), e = t.value.trim();
402
- if (e) {
403
- this.displayMessage(e, "user"), t.value = "", this.showTypingIndicator();
446
+ const e = document.getElementById("user-input"), t = e.value.trim();
447
+ if (t) {
448
+ this.displayMessage(t, "user"), e.value = "", this.showTypingIndicator();
404
449
  try {
405
- const o = await this.api.getWineRecommendations(e);
450
+ y(t);
451
+ const o = await this.api.getWineRecommendations(t);
406
452
  this.hideTypingIndicator(), o && o.length ? this.displayResults(o) : this.displayMessage("No results found.", "api");
407
453
  } catch {
408
454
  this.hideTypingIndicator(), this.displayMessage(s.translate("somethingWentWrong"), "api");
@@ -415,32 +461,35 @@ class b {
415
461
  hideTypingIndicator() {
416
462
  document.getElementById("typing-indicator").classList.remove("visible");
417
463
  }
418
- displayMessage(t, e) {
464
+ displayMessage(e, t) {
419
465
  const o = document.getElementById("message-container"), i = document.createElement("div");
420
- i.textContent = t, i.className = "message " + e, o.appendChild(i), o.scrollTop = o.scrollHeight;
466
+ i.textContent = e, i.className = "message " + t, o.appendChild(i), o.scrollTop = o.scrollHeight;
467
+ }
468
+ sendAnalytics(e) {
469
+ x(e);
421
470
  }
422
- displayResults(t) {
423
- const e = document.getElementById("message-container");
424
- t.forEach((o) => {
471
+ displayResults(e) {
472
+ const t = document.getElementById("message-container");
473
+ w(e.map((o) => o.Title)), e.forEach((o) => {
425
474
  const i = document.createElement("div");
426
475
  i.className = "wine-item";
427
476
  const a = document.createElement("img");
428
477
  a.src = o.Image, i.appendChild(a);
429
- const r = document.createElement("div");
430
- r.innerHTML = `
478
+ const c = document.createElement("div");
479
+ c.innerHTML = `
431
480
  <strong>${o.Title}</strong><br>
432
481
  ${s.translate("price")}: ${o.Price}<br>
433
482
  ${s.translate("region")}: ${o.Region}<br>
434
483
  ${s.translate("type")}: ${o.Type}<br>
435
- <a href="${o.Url}" target="_blank">${s.translate("moreInfo")}</a>
436
- `, i.appendChild(r), e.appendChild(i);
437
- }), e.scrollTop = e.scrollHeight;
484
+ <a href="${o.Url}" onclick="sendAnalytics(${o.Title})" target="_blank">${s.translate("moreInfo")}</a>
485
+ `, i.appendChild(c), t.appendChild(i);
486
+ }), t.scrollTop = t.scrollHeight;
438
487
  }
439
488
  }
440
489
  document.addEventListener("DOMContentLoaded", () => {
441
- window.toggleChatWindow = l, window.closeChatWindow = h, window.openChatWindow = u;
490
+ window.toggleChatWindow = u, window.closeChatWindow = v, window.openChatWindow = k;
442
491
  });
443
- function w() {
492
+ function B() {
444
493
  const n = `
445
494
  <div id="chatbot-container">
446
495
  <div id="chat-icon" onclick="toggleChatWindow()">
@@ -470,31 +519,32 @@ function w() {
470
519
  `;
471
520
  document.body.insertAdjacentHTML("beforeend", n);
472
521
  }
473
- function x() {
474
- document.getElementById("close-btn").addEventListener("click", l);
522
+ function L() {
523
+ document.getElementById("close-btn").addEventListener("click", u);
475
524
  }
476
- function v() {
525
+ function P() {
477
526
  window.addEventListener("click", function(n) {
478
- const t = document.getElementById("chat-window"), e = document.getElementById("chat-icon");
479
- !t.contains(n.target) && !e.contains(n.target) && (t.classList.remove("visible"), e.style.display = "flex");
527
+ const e = document.getElementById("chat-window"), t = document.getElementById("chat-icon");
528
+ !e.contains(n.target) && !t.contains(n.target) && (e.classList.remove("visible"), t.style.display = "flex");
480
529
  });
481
530
  }
482
- function E(n) {
531
+ function W(n) {
483
532
  console.log(n);
484
- const t = document.getElementById("chat-icon"), e = document.getElementById("chat-window");
485
- t.className = "", e.className = "", n === "right-center" ? (t.classList.add("chat-icon-right-center"), e.classList.add("right-center-aligned")) : t.classList.add("chat-icon-bottom-right");
533
+ const e = document.getElementById("chat-icon"), t = document.getElementById("chat-window");
534
+ e.className = "", t.className = "", n === "right-center" ? (e.classList.add("chat-icon-right-center"), t.classList.add("right-center-aligned")) : e.classList.add("chat-icon-bottom-right");
486
535
  }
487
- var d;
536
+ var l;
488
537
  if (typeof window < "u") {
489
- const n = ((d = window.wineaterData) == null ? void 0 : d.POSITION) || "bottom-right";
538
+ const n = ((l = window.wineaterData) == null ? void 0 : l.POSITION) || "bottom-right";
490
539
  window.addEventListener("DOMContentLoaded", async () => {
491
- const e = ["climats", "telckel", "biobio", "weinpoint"].find((a) => window.location.href.includes(a)) || null;
540
+ var a;
541
+ const t = ["climats", "telckel", "biobio", "weinpoint"].find((c) => window.location.href.includes(c)) || null;
492
542
  let o;
493
- e && (o = e.charAt(0).toUpperCase() + e.slice(1)), await s.fetchConfig(o || null), w(), x(), v(), E(n), new b().initialize();
543
+ t && (o = t.charAt(0).toUpperCase() + t.slice(1)), await s.fetchConfig(o || null), B(), L(), P(), W(n), b("chatbotToken", (a = window.wineaterData) == null ? void 0 : a.CLIENT_TOKEN, 365), new T().initialize();
494
544
  });
495
545
  }
496
546
  export {
497
- h as closeChatWindow,
498
- u as openChatWindow,
499
- l as toggleChatWindow
547
+ v as closeChatWindow,
548
+ k as openChatWindow,
549
+ u as toggleChatWindow
500
550
  };
@@ -1,4 +1,4 @@
1
- (function(a,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(a=typeof globalThis<"u"?globalThis:a||self,r(a.WineaterChatbot={}))})(this,function(a){"use strict";var u;const r=`
1
+ (function(r,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(r=typeof globalThis<"u"?globalThis:r||self,d(r.WineaterChatbot={}))})(this,function(r){"use strict";var w;const d=`
2
2
  @font-face {
3
3
  font-family: 'Poppins';
4
4
  src: url('https://fonts.googleapis.com/css2?family=Poppins:wght@400&display=swap');
@@ -273,17 +273,17 @@
273
273
  .typing-indicator.visible {
274
274
  visibility: visible;
275
275
  height: 50px;
276
- }`,l=document.createElement("style");l.textContent=r,document.head.appendChild(l);function c(){const n=document.getElementById("chat-window"),t=document.getElementById("chat-icon");n.classList.contains("visible")?(n.classList.remove("visible"),t.style.display="flex"):(n.classList.add("visible"),t.style.display="none")}function p(){document.getElementById("chat-window").classList.remove("visible")}function g(){document.getElementById("chat-window").classList.add("visible")}document.addEventListener("DOMContentLoaded",()=>{setupCloseButton(),setupOutsideClick()});const f=["climats","telckel","biobio","weinpoint"],y="OuhXJRleF6sROjsQZPWx1yqjrL6APeJxmHswqyOBWbgIqtXcht3MDadvI9DtOOoL";class h{constructor(t){var e;this.baseURL="https://api.wineater.com/",this.store=f.find(o=>window.location.href.includes(o)),this.token=((e=window==null?void 0:window.wineaterData)==null?void 0:e.CLIENT_TOKEN)||y}async getStoreConfig(t){console.log(t);try{const e=await fetch(`${this.baseURL}stores/store`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({store:t})});if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return await e.json()}catch(e){throw console.error("Error fetching store configuration:",e),e}}async getWineRecommendations(t){console.log(window.location.href);try{const e=await fetch(`${this.baseURL}dish/recommendations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({text:t,store:this.store?this.store.toString().charAt(0).toUpperCase()+this.store.slice(1):void 0})}),o=await e.json();if(!e.ok)throw new Error(`API call failed with status ${e.status}: ${o.message||"No additional error information"}`);return o}catch(e){throw console.error("Fetching wine recommendations failed:",e.message),new Error(`Error in getWineRecommendations: ${e.message}`)}}}class b{constructor(){this.api=new h,this.language="en",this.translations={fr:{welcomeMessage:"Sublimez votre expérience gastronomique. Il vous suffit de donner les détails de votre plat, et obtenez la recommandation de compagnon de vin idéale. Que voulez-vous manger?",noResultsFound:"Aucun résultat trouvé.",somethingWentWrong:"Désolé, quelque chose a mal tourné.",chatButton:"Accorder le vin au dîner",inputPlaceholder:"ex., Salade de thon",sendButton:"Accorder",price:"Prix",region:"Région",type:"Type",moreInfo:"Plus d'infos"},es:{welcomeMessage:"Mejore su experiencia gastronómica. Solo proporcione los detalles de su plato y obtenga la recomendación de vino ideal. ¿Qué le gustaría comer?",noResultsFound:"No se encontraron resultados.",somethingWentWrong:"Lo sentimos, algo salió mal.",chatButton:"Maridar vino con cena",inputPlaceholder:"ej., Ensalada de atún",sendButton:"Maridar",price:"Precio",region:"Región",type:"Tipo",moreInfo:"Más info"},en:{welcomeMessage:"Enhance your dining experience. Just provide your dish details and get the ideal wine pairing. What would you like to eat?",noResultsFound:"No results found.",somethingWentWrong:"Sorry, something went wrong.",chatButton:"Pair wine with dinner",inputPlaceholder:"e.g., Tuna Salad",sendButton:"Pair",price:"Price",region:"Region",type:"Type",moreInfo:"More info"}}}async fetchConfig(t){if(t){const e=await this.api.getStoreConfig(t);this.language=e.lang}}translate(t){return this.translations[this.language][t]||t}}const s=new b;class w{constructor(){this.api=new h,this.displayFirstMessage(s.translate("welcomeMessage"))}initialize(){document.getElementById("send-button").addEventListener("click",()=>this.handleUserInput()),document.getElementById("user-input").addEventListener("keypress",o=>{o.key==="Enter"&&this.handleUserInput()})}displayFirstMessage(t,e="api"){const o=document.getElementById("message-container"),i=document.createElement("div");i.className=`message ${e}`,i.textContent=t,o.appendChild(i),o.scrollTop=o.scrollHeight}async handleUserInput(){const t=document.getElementById("user-input"),e=t.value.trim();if(e){this.displayMessage(e,"user"),t.value="",this.showTypingIndicator();try{const o=await this.api.getWineRecommendations(e);this.hideTypingIndicator(),o&&o.length?this.displayResults(o):this.displayMessage("No results found.","api")}catch{this.hideTypingIndicator(),this.displayMessage(s.translate("somethingWentWrong"),"api")}}}showTypingIndicator(){document.getElementById("typing-indicator").classList.add("visible")}hideTypingIndicator(){document.getElementById("typing-indicator").classList.remove("visible")}displayMessage(t,e){const o=document.getElementById("message-container"),i=document.createElement("div");i.textContent=t,i.className="message "+e,o.appendChild(i),o.scrollTop=o.scrollHeight}displayResults(t){const e=document.getElementById("message-container");t.forEach(o=>{const i=document.createElement("div");i.className="wine-item";const d=document.createElement("img");d.src=o.Image,i.appendChild(d);const m=document.createElement("div");m.innerHTML=`
276
+ }`,g=document.createElement("style");g.textContent=d,document.head.appendChild(g);function x(n,t,e){let o="";if(e){const i=new Date;i.setTime(i.getTime()+e*24*60*60*1e3),o="; expires="+i.toUTCString()}document.cookie=n+"="+(t||"")+o+"; path=/; secure; samesite=strict"}function c(n){const e=`; ${document.cookie}`.split(`; ${n}=`);if(e.length===2)return e.pop().split(";").shift()}function l(n,t){fetch("https://api-eu.mixpanel.com/track",{method:"POST",headers:{"Content-Type":"application/json",Authentication:"6f3d90d5b02720f58de3663e3ef675fe"},body:JSON.stringify({event:n,properties:t})}).then(s=>{s.ok||console.error("Mixpanel tracking failed",s)}).catch(s=>{console.error("Mixpanel tracking error",s)})}function u(){l("Chatbot Opened",{distinct_id:c("chatbotToken")})}function m(){l("Chatbot Closed",{distinct_id:c("chatbotToken")})}function v(n){l("Message Sent",{distinct_id:c("chatbotToken"),message_content:n})}function k(n){l("Message Sent",{distinct_id:c("chatbotToken"),products:n})}function C(n){l("Product Clicked",{distinct_id:c("chatbotToken"),product_id:n})}function h(){const n=document.getElementById("chat-window"),t=document.getElementById("chat-icon");n.classList.contains("visible")?(m(),n.classList.remove("visible"),t.style.display="flex"):(u(),n.classList.add("visible"),t.style.display="none")}function f(){m(),document.getElementById("chat-window").classList.remove("visible")}function b(){u(),document.getElementById("chat-window").classList.add("visible")}document.addEventListener("DOMContentLoaded",()=>{setupCloseButton(),setupOutsideClick()});const E=["climats","telckel","biobio","weinpoint"],I="OuhXJRleF6sROjsQZPWx1yqjrL6APeJxmHswqyOBWbgIqtXcht3MDadvI9DtOOoL";class y{constructor(t){var e;this.baseURL="https://api.wineater.com/",this.store=E.find(o=>window.location.href.includes(o)),this.token=((e=window==null?void 0:window.wineaterData)==null?void 0:e.CLIENT_TOKEN)||I}async getStoreConfig(t){console.log(t);try{const e=await fetch(`${this.baseURL}stores/store`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({store:t})});if(!e.ok)throw new Error(`HTTP error! Status: ${e.status}`);return await e.json()}catch(e){throw console.error("Error fetching store configuration:",e),e}}async getWineRecommendations(t){console.log(window.location.href);try{const e=await fetch(`${this.baseURL}dish/recommendations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({text:t,store:this.store?this.store.toString().charAt(0).toUpperCase()+this.store.slice(1):void 0})}),o=await e.json();if(!e.ok)throw new Error(`API call failed with status ${e.status}: ${o.message||"No additional error information"}`);return o}catch(e){throw console.error("Fetching wine recommendations failed:",e.message),new Error(`Error in getWineRecommendations: ${e.message}`)}}}class T{constructor(){this.api=new y,this.language="en",this.translations={fr:{welcomeMessage:"Sublimez votre expérience gastronomique. Il vous suffit de donner les détails de votre plat, et obtenez la recommandation de compagnon de vin idéale. Que voulez-vous manger?",noResultsFound:"Aucun résultat trouvé.",somethingWentWrong:"Désolé, quelque chose a mal tourné.",chatButton:"Accorder le vin au dîner",inputPlaceholder:"ex., Salade de thon",sendButton:"Accorder",price:"Prix",region:"Région",type:"Type",moreInfo:"Plus d'infos"},es:{welcomeMessage:"Mejore su experiencia gastronómica. Solo proporcione los detalles de su plato y obtenga la recomendación de vino ideal. ¿Qué le gustaría comer?",noResultsFound:"No se encontraron resultados.",somethingWentWrong:"Lo sentimos, algo salió mal.",chatButton:"Maridar vino con cena",inputPlaceholder:"ej., Ensalada de atún",sendButton:"Maridar",price:"Precio",region:"Región",type:"Tipo",moreInfo:"Más info"},en:{welcomeMessage:"Enhance your dining experience. Just provide your dish details and get the ideal wine pairing. What would you like to eat?",noResultsFound:"No results found.",somethingWentWrong:"Sorry, something went wrong.",chatButton:"Pair wine with dinner",inputPlaceholder:"e.g., Tuna Salad",sendButton:"Pair",price:"Price",region:"Region",type:"Type",moreInfo:"More info"}}}async fetchConfig(t){if(t){const e=await this.api.getStoreConfig(t);this.language=e.lang}}translate(t){return this.translations[this.language][t]||t}}const a=new T;class B{constructor(){this.api=new y,this.displayFirstMessage(a.translate("welcomeMessage"))}initialize(){document.getElementById("send-button").addEventListener("click",()=>this.handleUserInput()),document.getElementById("user-input").addEventListener("keypress",o=>{o.key==="Enter"&&this.handleUserInput()})}displayFirstMessage(t,e="api"){const o=document.getElementById("message-container"),i=document.createElement("div");i.className=`message ${e}`,i.textContent=t,o.appendChild(i),o.scrollTop=o.scrollHeight}async handleUserInput(){const t=document.getElementById("user-input"),e=t.value.trim();if(e){this.displayMessage(e,"user"),t.value="",this.showTypingIndicator();try{v(e);const o=await this.api.getWineRecommendations(e);this.hideTypingIndicator(),o&&o.length?this.displayResults(o):this.displayMessage("No results found.","api")}catch{this.hideTypingIndicator(),this.displayMessage(a.translate("somethingWentWrong"),"api")}}}showTypingIndicator(){document.getElementById("typing-indicator").classList.add("visible")}hideTypingIndicator(){document.getElementById("typing-indicator").classList.remove("visible")}displayMessage(t,e){const o=document.getElementById("message-container"),i=document.createElement("div");i.textContent=t,i.className="message "+e,o.appendChild(i),o.scrollTop=o.scrollHeight}sendAnalytics(t){C(t)}displayResults(t){const e=document.getElementById("message-container");k(t.map(o=>o.Title)),t.forEach(o=>{const i=document.createElement("div");i.className="wine-item";const s=document.createElement("img");s.src=o.Image,i.appendChild(s);const p=document.createElement("div");p.innerHTML=`
277
277
  <strong>${o.Title}</strong><br>
278
- ${s.translate("price")}: ${o.Price}<br>
279
- ${s.translate("region")}: ${o.Region}<br>
280
- ${s.translate("type")}: ${o.Type}<br>
281
- <a href="${o.Url}" target="_blank">${s.translate("moreInfo")}</a>
282
- `,i.appendChild(m),e.appendChild(i)}),e.scrollTop=e.scrollHeight}}document.addEventListener("DOMContentLoaded",()=>{window.toggleChatWindow=c,window.closeChatWindow=p,window.openChatWindow=g});function x(){const n=`
278
+ ${a.translate("price")}: ${o.Price}<br>
279
+ ${a.translate("region")}: ${o.Region}<br>
280
+ ${a.translate("type")}: ${o.Type}<br>
281
+ <a href="${o.Url}" onclick="sendAnalytics(${o.Title})" target="_blank">${a.translate("moreInfo")}</a>
282
+ `,i.appendChild(p),e.appendChild(i)}),e.scrollTop=e.scrollHeight}}document.addEventListener("DOMContentLoaded",()=>{window.toggleChatWindow=h,window.closeChatWindow=f,window.openChatWindow=b});function L(){const n=`
283
283
  <div id="chatbot-container">
284
284
  <div id="chat-icon" onclick="toggleChatWindow()">
285
285
  <img src="https://landing-static.s3.eu-central-1.amazonaws.com/images/chat-icon.svg" alt="Chat Icon"> <!-- Update the path to your logo image -->
286
- <span>${s.translate("chatButton")}</span>
286
+ <span>${a.translate("chatButton")}</span>
287
287
  </div>
288
288
 
289
289
  <div id="chat-window" class="hidden">
@@ -300,9 +300,9 @@
300
300
  <span></span><span></span><span></span>
301
301
  </div>
302
302
  <div id="input-container">
303
- <input type="text" id="user-input" placeholder="${s.translate("inputPlaceholder")}">
304
- <button id="send-button">${s.translate("sendButton")}</button>
303
+ <input type="text" id="user-input" placeholder="${a.translate("inputPlaceholder")}">
304
+ <button id="send-button">${a.translate("sendButton")}</button>
305
305
  </div>
306
306
  </div>
307
307
  </div>
308
- `;document.body.insertAdjacentHTML("beforeend",n)}function v(){document.getElementById("close-btn").addEventListener("click",c)}function E(){window.addEventListener("click",function(n){const t=document.getElementById("chat-window"),e=document.getElementById("chat-icon");!t.contains(n.target)&&!e.contains(n.target)&&(t.classList.remove("visible"),e.style.display="flex")})}function I(n){console.log(n);const t=document.getElementById("chat-icon"),e=document.getElementById("chat-window");t.className="",e.className="",n==="right-center"?(t.classList.add("chat-icon-right-center"),e.classList.add("right-center-aligned")):t.classList.add("chat-icon-bottom-right")}if(typeof window<"u"){const n=((u=window.wineaterData)==null?void 0:u.POSITION)||"bottom-right";window.addEventListener("DOMContentLoaded",async()=>{const e=["climats","telckel","biobio","weinpoint"].find(d=>window.location.href.includes(d))||null;let o;e&&(o=e.charAt(0).toUpperCase()+e.slice(1)),await s.fetchConfig(o||null),x(),v(),E(),I(n),new w().initialize()})}a.closeChatWindow=p,a.openChatWindow=g,a.toggleChatWindow=c,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
308
+ `;document.body.insertAdjacentHTML("beforeend",n)}function W(){document.getElementById("close-btn").addEventListener("click",h)}function P(){window.addEventListener("click",function(n){const t=document.getElementById("chat-window"),e=document.getElementById("chat-icon");!t.contains(n.target)&&!e.contains(n.target)&&(t.classList.remove("visible"),e.style.display="flex")})}function S(n){console.log(n);const t=document.getElementById("chat-icon"),e=document.getElementById("chat-window");t.className="",e.className="",n==="right-center"?(t.classList.add("chat-icon-right-center"),e.classList.add("right-center-aligned")):t.classList.add("chat-icon-bottom-right")}if(typeof window<"u"){const n=((w=window.wineaterData)==null?void 0:w.POSITION)||"bottom-right";window.addEventListener("DOMContentLoaded",async()=>{var s;const e=["climats","telckel","biobio","weinpoint"].find(p=>window.location.href.includes(p))||null;let o;e&&(o=e.charAt(0).toUpperCase()+e.slice(1)),await a.fetchConfig(o||null),L(),W(),P(),S(n),x("chatbotToken",(s=window.wineaterData)==null?void 0:s.CLIENT_TOKEN,365),new B().initialize()})}r.closeChatWindow=f,r.openChatWindow=b,r.toggleChatWindow=h,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wineater-bot",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
package/src/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  // Import your CSS here
4
4
  import './js/styles.js';
5
+ import { setCookie } from './js/analytics.js';
5
6
 
6
7
  // Import your JavaScript modules here
7
8
  import { toggleChatWindow, closeChatWindow, openChatWindow } from './js/ui.js';
@@ -104,6 +105,7 @@ if (typeof window !== 'undefined') {
104
105
  setupCloseButton();
105
106
  setupOutsideClick();
106
107
  toggleChatIconPosition(position);
108
+ setCookie('chatbotToken', window.wineaterData?.CLIENT_TOKEN, 365);
107
109
  const myChatbot = new Chatbot();
108
110
  myChatbot.initialize();
109
111
  });
@@ -0,0 +1,65 @@
1
+ // analytics.js
2
+
3
+ function setCookie(name, value, days) {
4
+ let expires = "";
5
+ if (days) {
6
+ const date = new Date();
7
+ date.setTime(date.getTime() + (days*24*60*60*1000));
8
+ expires = "; expires=" + date.toUTCString();
9
+ }
10
+ document.cookie = name + "=" + (value || "") + expires + "; path=/; secure; samesite=strict";
11
+ }
12
+
13
+ function getCookie(name) {
14
+ const value = `; ${document.cookie}`;
15
+ const parts = value.split(`; ${name}=`);
16
+ if (parts.length === 2) return parts.pop().split(';').shift();
17
+ }
18
+
19
+ // Функция для отправки событий в Mixpanel
20
+ function trackEvent(event, properties) {
21
+ const token = '6f3d90d5b02720f58de3663e3ef675fe'; // Замените на ваш Mixpanel токен
22
+ const endpoint = 'https://api-eu.mixpanel.com/track';
23
+ const data = {
24
+ event: event,
25
+ properties: properties
26
+ };
27
+
28
+ fetch(endpoint, {
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ 'Authentication': token
33
+ },
34
+ body: JSON.stringify(data)
35
+ }).then(response => {
36
+ if (!response.ok) {
37
+ console.error('Mixpanel tracking failed', response);
38
+ }
39
+ }).catch(error => {
40
+ console.error('Mixpanel tracking error', error);
41
+ });
42
+ }
43
+
44
+ function trackChatbotOpen() {
45
+ trackEvent('Chatbot Opened', { distinct_id: getCookie('chatbotToken') });
46
+ }
47
+
48
+ function trackChatbotClose() {
49
+ trackEvent('Chatbot Closed', { distinct_id: getCookie('chatbotToken') });
50
+ }
51
+
52
+ function trackMessageSent(message) {
53
+ trackEvent('Message Sent', { distinct_id: getCookie('chatbotToken'), message_content: message });
54
+ }
55
+
56
+ function trackRecommendationsGet(products) {
57
+ trackEvent('Message Sent', { distinct_id: getCookie('chatbotToken'), products: products });
58
+ }
59
+
60
+ function trackProductClick(productId) {
61
+ trackEvent('Product Clicked', { distinct_id: getCookie('chatbotToken'), product_id: productId });
62
+ }
63
+
64
+ export { setCookie, getCookie, trackChatbotOpen, trackMessageSent, trackProductClick, trackChatbotClose, trackRecommendationsGet };
65
+
package/src/js/chatbot.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // chatbot.js
2
2
  import { Api } from './api.js';
3
3
  import translator from './i18n.js';
4
+ import { trackMessageSent, trackProductClick, trackRecommendationsGet } from './analytics.js';
4
5
 
5
6
  export class Chatbot {
6
7
  constructor() {
@@ -43,8 +44,9 @@ export class Chatbot {
43
44
  this.showTypingIndicator();
44
45
 
45
46
  try {
47
+ trackMessageSent(userInput);
46
48
  const results = await this.api.getWineRecommendations(userInput);
47
-
49
+
48
50
  // Hide the loader
49
51
  this.hideTypingIndicator();
50
52
 
@@ -80,8 +82,13 @@ export class Chatbot {
80
82
  messageContainer.scrollTop = messageContainer.scrollHeight;
81
83
  }
82
84
 
85
+ sendAnalytics(product) {
86
+ trackProductClick(product);
87
+ }
88
+
83
89
  displayResults(wines) {
84
90
  const messageContainer = document.getElementById('message-container');
91
+ trackRecommendationsGet(wines.map(value => value.Title));
85
92
  wines.forEach(wine => {
86
93
  const wineDiv = document.createElement('div');
87
94
  wineDiv.className = 'wine-item';
@@ -96,7 +103,7 @@ export class Chatbot {
96
103
  ${translator.translate('price')}: ${wine.Price}<br>
97
104
  ${translator.translate('region')}: ${wine.Region}<br>
98
105
  ${translator.translate('type')}: ${wine.Type}<br>
99
- <a href="${wine.Url}" target="_blank">${translator.translate('moreInfo')}</a>
106
+ <a href="${wine.Url}" onclick="sendAnalytics(${wine.Title})" target="_blank">${translator.translate('moreInfo')}</a>
100
107
  `;
101
108
  wineDiv.appendChild(contentDiv);
102
109
 
package/src/js/ui.js CHANGED
@@ -1,3 +1,6 @@
1
+
2
+ import { trackChatbotOpen, trackChatbotClose } from './analytics.js';
3
+
1
4
  export function toggleChatWindow() {
2
5
  const chatWindow = document.getElementById('chat-window');
3
6
  const chatIcon = document.getElementById('chat-icon');
@@ -6,20 +9,24 @@ export function toggleChatWindow() {
6
9
  const isWindowOpen = chatWindow.classList.contains('visible');
7
10
 
8
11
  if (isWindowOpen) {
12
+ trackChatbotClose();
9
13
  chatWindow.classList.remove('visible');
10
14
  chatIcon.style.display = 'flex'; // Show the chat icon/button
11
15
  } else {
16
+ trackChatbotOpen();
12
17
  chatWindow.classList.add('visible');
13
18
  chatIcon.style.display = 'none'; // Hide the chat icon/button
14
19
  }
15
20
  }
16
21
 
17
22
  export function closeChatWindow() {
23
+ trackChatbotClose();
18
24
  const chatWindow = document.getElementById('chat-window');
19
25
  chatWindow.classList.remove('visible');
20
26
  }
21
27
 
22
28
  export function openChatWindow() {
29
+ trackChatbotOpen();
23
30
  const chatWindow = document.getElementById('chat-window');
24
31
  chatWindow.classList.add('visible');
25
32
  }