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.
- package/dist/wineater-chatbot.mjs +125 -75
- package/dist/wineater-chatbot.umd.js +11 -11
- package/package.json +1 -1
- package/src/index.js +2 -0
- package/src/js/analytics.js +65 -0
- package/src/js/chatbot.js +9 -2
- package/src/js/ui.js +7 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
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
|
-
}`,
|
|
277
|
-
|
|
278
|
-
document.head.appendChild(
|
|
279
|
-
function
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
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").
|
|
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
|
|
293
|
-
class
|
|
294
|
-
constructor(
|
|
295
|
-
var
|
|
296
|
-
this.baseURL = "https://api.wineater.com/", this.store =
|
|
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(
|
|
299
|
-
console.log(
|
|
343
|
+
async getStoreConfig(e) {
|
|
344
|
+
console.log(e);
|
|
300
345
|
try {
|
|
301
|
-
const
|
|
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:
|
|
352
|
+
body: JSON.stringify({ store: e })
|
|
308
353
|
});
|
|
309
|
-
if (!
|
|
310
|
-
throw new Error(`HTTP error! Status: ${
|
|
311
|
-
return await
|
|
312
|
-
} catch (
|
|
313
|
-
throw console.error("Error fetching store configuration:",
|
|
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(
|
|
361
|
+
async getWineRecommendations(e) {
|
|
317
362
|
console.log(window.location.href);
|
|
318
363
|
try {
|
|
319
|
-
const
|
|
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:
|
|
326
|
-
}), o = await
|
|
327
|
-
if (!
|
|
328
|
-
throw new Error(`API call failed with status ${
|
|
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 (
|
|
331
|
-
throw console.error("Fetching wine recommendations failed:",
|
|
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
|
|
380
|
+
class I {
|
|
336
381
|
constructor() {
|
|
337
|
-
this.api = new
|
|
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(
|
|
377
|
-
if (
|
|
378
|
-
const
|
|
379
|
-
this.language =
|
|
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(
|
|
383
|
-
return this.translations[this.language][
|
|
427
|
+
translate(e) {
|
|
428
|
+
return this.translations[this.language][e] || e;
|
|
384
429
|
}
|
|
385
430
|
}
|
|
386
|
-
const s = new
|
|
387
|
-
class
|
|
431
|
+
const s = new I();
|
|
432
|
+
class T {
|
|
388
433
|
constructor() {
|
|
389
|
-
this.api = new
|
|
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(
|
|
441
|
+
displayFirstMessage(e, t = "api") {
|
|
397
442
|
const o = document.getElementById("message-container"), i = document.createElement("div");
|
|
398
|
-
i.className = `message ${
|
|
443
|
+
i.className = `message ${t}`, i.textContent = e, o.appendChild(i), o.scrollTop = o.scrollHeight;
|
|
399
444
|
}
|
|
400
445
|
async handleUserInput() {
|
|
401
|
-
const
|
|
402
|
-
if (
|
|
403
|
-
this.displayMessage(
|
|
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
|
-
|
|
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(
|
|
464
|
+
displayMessage(e, t) {
|
|
419
465
|
const o = document.getElementById("message-container"), i = document.createElement("div");
|
|
420
|
-
i.textContent =
|
|
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(
|
|
423
|
-
const
|
|
424
|
-
|
|
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
|
|
430
|
-
|
|
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(
|
|
437
|
-
}),
|
|
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 =
|
|
490
|
+
window.toggleChatWindow = u, window.closeChatWindow = v, window.openChatWindow = k;
|
|
442
491
|
});
|
|
443
|
-
function
|
|
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
|
|
474
|
-
document.getElementById("close-btn").addEventListener("click",
|
|
522
|
+
function L() {
|
|
523
|
+
document.getElementById("close-btn").addEventListener("click", u);
|
|
475
524
|
}
|
|
476
|
-
function
|
|
525
|
+
function P() {
|
|
477
526
|
window.addEventListener("click", function(n) {
|
|
478
|
-
const
|
|
479
|
-
!
|
|
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
|
|
531
|
+
function W(n) {
|
|
483
532
|
console.log(n);
|
|
484
|
-
const
|
|
485
|
-
|
|
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
|
|
536
|
+
var l;
|
|
488
537
|
if (typeof window < "u") {
|
|
489
|
-
const n = ((
|
|
538
|
+
const n = ((l = window.wineaterData) == null ? void 0 : l.POSITION) || "bottom-right";
|
|
490
539
|
window.addEventListener("DOMContentLoaded", async () => {
|
|
491
|
-
|
|
540
|
+
var a;
|
|
541
|
+
const t = ["climats", "telckel", "biobio", "weinpoint"].find((c) => window.location.href.includes(c)) || null;
|
|
492
542
|
let o;
|
|
493
|
-
|
|
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
|
-
|
|
498
|
-
|
|
499
|
-
|
|
547
|
+
v as closeChatWindow,
|
|
548
|
+
k as openChatWindow,
|
|
549
|
+
u as toggleChatWindow
|
|
500
550
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(
|
|
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
|
-
}`,
|
|
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
|
-
${
|
|
279
|
-
${
|
|
280
|
-
${
|
|
281
|
-
<a href="${o.Url}" target="_blank">${
|
|
282
|
-
`,i.appendChild(
|
|
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>${
|
|
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="${
|
|
304
|
-
<button id="send-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
|
|
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
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
|
}
|