wineater-bot 1.1.8 → 1.2.1
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 +137 -70
- package/dist/wineater-chatbot.umd.js +12 -12
- package/package.json +1 -1
- package/src/index.js +11 -6
- package/src/js/api.js +20 -2
- package/src/js/chatbot.js +8 -10
- package/src/js/i18n.js +59 -0
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var g = (i, e, t) => e in i ? p(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
|
|
3
|
-
var r = (i, e, t) => (g(i, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
-
const h = `
|
|
1
|
+
const g = `
|
|
5
2
|
@font-face {
|
|
6
3
|
font-family: 'Poppins';
|
|
7
4
|
src: url('https://fonts.googleapis.com/css2?family=Poppins:wght@400&display=swap');
|
|
@@ -277,13 +274,13 @@ const h = `
|
|
|
277
274
|
visibility: visible;
|
|
278
275
|
height: 50px;
|
|
279
276
|
}`, c = document.createElement("style");
|
|
280
|
-
c.textContent =
|
|
277
|
+
c.textContent = g;
|
|
281
278
|
document.head.appendChild(c);
|
|
282
279
|
function l() {
|
|
283
|
-
const
|
|
284
|
-
|
|
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");
|
|
285
282
|
}
|
|
286
|
-
function
|
|
283
|
+
function h() {
|
|
287
284
|
document.getElementById("chat-window").classList.remove("visible");
|
|
288
285
|
}
|
|
289
286
|
function u() {
|
|
@@ -292,52 +289,120 @@ function u() {
|
|
|
292
289
|
document.addEventListener("DOMContentLoaded", () => {
|
|
293
290
|
setupCloseButton(), setupOutsideClick();
|
|
294
291
|
});
|
|
295
|
-
const
|
|
296
|
-
class
|
|
297
|
-
constructor(
|
|
298
|
-
this.
|
|
292
|
+
const m = ["climats", "telckel", "biobio", "weinpoint"];
|
|
293
|
+
class p {
|
|
294
|
+
constructor(t) {
|
|
295
|
+
this.baseURL = "https://api.wineater.com/", this.store = m.find((e) => window.location.href.includes(e)), console.log(this.store);
|
|
299
296
|
}
|
|
300
|
-
async
|
|
297
|
+
async getStoreConfig(t) {
|
|
298
|
+
console.log(t);
|
|
299
|
+
try {
|
|
300
|
+
const e = await fetch(`${this.baseURL}stores/store`, {
|
|
301
|
+
method: "POST",
|
|
302
|
+
headers: {
|
|
303
|
+
"Content-Type": "application/json"
|
|
304
|
+
},
|
|
305
|
+
body: JSON.stringify({ store: t })
|
|
306
|
+
});
|
|
307
|
+
if (!e.ok)
|
|
308
|
+
throw new Error(`HTTP error! Status: ${e.status}`);
|
|
309
|
+
return await e.json();
|
|
310
|
+
} catch (e) {
|
|
311
|
+
throw console.error("Error fetching store configuration:", e), e;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
async getWineRecommendations(t) {
|
|
301
315
|
console.log(window.location.href);
|
|
302
316
|
try {
|
|
303
|
-
const
|
|
317
|
+
const e = await fetch(`${this.baseURL}dish/recommendations`, {
|
|
304
318
|
method: "POST",
|
|
305
319
|
headers: {
|
|
306
320
|
"Content-Type": "application/json"
|
|
307
321
|
},
|
|
308
|
-
body: JSON.stringify({ text:
|
|
309
|
-
}), o = await
|
|
310
|
-
if (!
|
|
311
|
-
throw new Error(`API call failed with status ${
|
|
322
|
+
body: JSON.stringify({ text: t, store: this.store ? this.store.toString().charAt(0).toUpperCase() + this.store.slice(1) : void 0 })
|
|
323
|
+
}), o = await e.json();
|
|
324
|
+
if (!e.ok)
|
|
325
|
+
throw new Error(`API call failed with status ${e.status}: ${o.message || "No additional error information"}`);
|
|
312
326
|
return o;
|
|
313
|
-
} catch (
|
|
314
|
-
throw console.error("Fetching wine recommendations failed:",
|
|
327
|
+
} catch (e) {
|
|
328
|
+
throw console.error("Fetching wine recommendations failed:", e.message), new Error(`Error in getWineRecommendations: ${e.message}`);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
class f {
|
|
333
|
+
constructor() {
|
|
334
|
+
this.api = new p(), this.language = "en", this.translations = {
|
|
335
|
+
fr: {
|
|
336
|
+
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?",
|
|
337
|
+
noResultsFound: "Aucun résultat trouvé.",
|
|
338
|
+
somethingWentWrong: "Désolé, quelque chose a mal tourné.",
|
|
339
|
+
chatButton: "Accorder le vin au dîner",
|
|
340
|
+
inputPlaceholder: "ex., Salade de thon",
|
|
341
|
+
sendButton: "Accorder",
|
|
342
|
+
price: "Prix",
|
|
343
|
+
region: "Région",
|
|
344
|
+
type: "Type",
|
|
345
|
+
moreInfo: "Plus d'infos"
|
|
346
|
+
},
|
|
347
|
+
es: {
|
|
348
|
+
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?",
|
|
349
|
+
noResultsFound: "No se encontraron resultados.",
|
|
350
|
+
somethingWentWrong: "Lo sentimos, algo salió mal.",
|
|
351
|
+
chatButton: "Maridar vino con cena",
|
|
352
|
+
inputPlaceholder: "ej., Ensalada de atún",
|
|
353
|
+
sendButton: "Maridar",
|
|
354
|
+
price: "Precio",
|
|
355
|
+
region: "Región",
|
|
356
|
+
type: "Tipo",
|
|
357
|
+
moreInfo: "Más info"
|
|
358
|
+
},
|
|
359
|
+
en: {
|
|
360
|
+
welcomeMessage: "Enhance your dining experience. Just provide your dish details and get the ideal wine pairing. What would you like to eat?",
|
|
361
|
+
noResultsFound: "No results found.",
|
|
362
|
+
somethingWentWrong: "Sorry, something went wrong.",
|
|
363
|
+
chatButton: "Pair wine with dinner",
|
|
364
|
+
inputPlaceholder: "e.g., Tuna Salad",
|
|
365
|
+
sendButton: "Pair",
|
|
366
|
+
price: "Price",
|
|
367
|
+
region: "Region",
|
|
368
|
+
type: "Type",
|
|
369
|
+
moreInfo: "More info"
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
async fetchConfig(t) {
|
|
374
|
+
if (t) {
|
|
375
|
+
const e = await this.api.getStoreConfig(t);
|
|
376
|
+
this.language = e.lang;
|
|
315
377
|
}
|
|
316
378
|
}
|
|
379
|
+
translate(t) {
|
|
380
|
+
return this.translations[this.language][t] || t;
|
|
381
|
+
}
|
|
317
382
|
}
|
|
383
|
+
const s = new f();
|
|
318
384
|
class y {
|
|
319
385
|
constructor() {
|
|
320
|
-
|
|
321
|
-
this.api = new b(), this.displayFirstMessage(this.welcomeMessage);
|
|
386
|
+
this.api = new p(), this.displayFirstMessage(s.translate("welcomeMessage"));
|
|
322
387
|
}
|
|
323
388
|
initialize() {
|
|
324
389
|
document.getElementById("send-button").addEventListener("click", () => this.handleUserInput()), document.getElementById("user-input").addEventListener("keypress", (o) => {
|
|
325
390
|
o.key === "Enter" && this.handleUserInput();
|
|
326
391
|
});
|
|
327
392
|
}
|
|
328
|
-
displayFirstMessage(
|
|
329
|
-
const o = document.getElementById("message-container"),
|
|
330
|
-
|
|
393
|
+
displayFirstMessage(t, e = "api") {
|
|
394
|
+
const o = document.getElementById("message-container"), i = document.createElement("div");
|
|
395
|
+
i.className = `message ${e}`, i.textContent = t, o.appendChild(i), o.scrollTop = o.scrollHeight;
|
|
331
396
|
}
|
|
332
397
|
async handleUserInput() {
|
|
333
|
-
const
|
|
334
|
-
if (
|
|
335
|
-
this.displayMessage(
|
|
398
|
+
const t = document.getElementById("user-input"), e = t.value.trim();
|
|
399
|
+
if (e) {
|
|
400
|
+
this.displayMessage(e, "user"), t.value = "", this.showTypingIndicator();
|
|
336
401
|
try {
|
|
337
|
-
const o = await this.api.getWineRecommendations(
|
|
402
|
+
const o = await this.api.getWineRecommendations(e);
|
|
338
403
|
this.hideTypingIndicator(), o && o.length ? this.displayResults(o) : this.displayMessage("No results found.", "api");
|
|
339
|
-
} catch
|
|
340
|
-
this.hideTypingIndicator(),
|
|
404
|
+
} catch {
|
|
405
|
+
this.hideTypingIndicator(), this.displayMessage(s.translate("somethingWentWrong"), "api");
|
|
341
406
|
}
|
|
342
407
|
}
|
|
343
408
|
}
|
|
@@ -347,37 +412,37 @@ class y {
|
|
|
347
412
|
hideTypingIndicator() {
|
|
348
413
|
document.getElementById("typing-indicator").classList.remove("visible");
|
|
349
414
|
}
|
|
350
|
-
displayMessage(
|
|
351
|
-
const o = document.getElementById("message-container"),
|
|
352
|
-
|
|
415
|
+
displayMessage(t, e) {
|
|
416
|
+
const o = document.getElementById("message-container"), i = document.createElement("div");
|
|
417
|
+
i.textContent = t, i.className = "message " + e, o.appendChild(i), o.scrollTop = o.scrollHeight;
|
|
353
418
|
}
|
|
354
|
-
displayResults(
|
|
355
|
-
const
|
|
356
|
-
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
`,
|
|
369
|
-
}),
|
|
419
|
+
displayResults(t) {
|
|
420
|
+
const e = document.getElementById("message-container");
|
|
421
|
+
t.forEach((o) => {
|
|
422
|
+
const i = document.createElement("div");
|
|
423
|
+
i.className = "wine-item";
|
|
424
|
+
const a = document.createElement("img");
|
|
425
|
+
a.src = o.Image, i.appendChild(a);
|
|
426
|
+
const r = document.createElement("div");
|
|
427
|
+
r.innerHTML = `
|
|
428
|
+
<strong>${o.Title}</strong><br>
|
|
429
|
+
${s.translate("price")}: ${o.Price}<br>
|
|
430
|
+
${s.translate("region")}: ${o.Region}<br>
|
|
431
|
+
${s.translate("type")}: ${o.Type}<br>
|
|
432
|
+
<a href="${o.Url}" target="_blank">${s.translate("moreInfo")}</a>
|
|
433
|
+
`, i.appendChild(r), e.appendChild(i);
|
|
434
|
+
}), e.scrollTop = e.scrollHeight;
|
|
370
435
|
}
|
|
371
436
|
}
|
|
372
437
|
document.addEventListener("DOMContentLoaded", () => {
|
|
373
|
-
window.toggleChatWindow = l, window.closeChatWindow =
|
|
438
|
+
window.toggleChatWindow = l, window.closeChatWindow = h, window.openChatWindow = u;
|
|
374
439
|
});
|
|
375
|
-
function
|
|
376
|
-
|
|
440
|
+
function b() {
|
|
441
|
+
const n = `
|
|
377
442
|
<div id="chatbot-container">
|
|
378
443
|
<div id="chat-icon" onclick="toggleChatWindow()">
|
|
379
444
|
<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 -->
|
|
380
|
-
<span
|
|
445
|
+
<span>${s.translate("chatButton")}</span>
|
|
381
446
|
</div>
|
|
382
447
|
|
|
383
448
|
<div id="chat-window" class="hidden">
|
|
@@ -394,33 +459,35 @@ function w() {
|
|
|
394
459
|
<span></span><span></span><span></span>
|
|
395
460
|
</div>
|
|
396
461
|
<div id="input-container">
|
|
397
|
-
<input type="text" id="user-input" placeholder="
|
|
398
|
-
<button id="send-button"
|
|
462
|
+
<input type="text" id="user-input" placeholder="${s.translate("inputPlaceholder")}">
|
|
463
|
+
<button id="send-button">${s.translate("sendButton")}</button>
|
|
399
464
|
</div>
|
|
400
465
|
</div>
|
|
401
466
|
</div>
|
|
402
|
-
|
|
467
|
+
`;
|
|
468
|
+
document.body.insertAdjacentHTML("beforeend", n);
|
|
403
469
|
}
|
|
404
|
-
function
|
|
470
|
+
function w() {
|
|
405
471
|
document.getElementById("close-btn").addEventListener("click", l);
|
|
406
472
|
}
|
|
407
|
-
function
|
|
408
|
-
window.addEventListener("click", function(
|
|
409
|
-
const
|
|
410
|
-
!
|
|
473
|
+
function x() {
|
|
474
|
+
window.addEventListener("click", function(n) {
|
|
475
|
+
const t = document.getElementById("chat-window"), e = document.getElementById("chat-icon");
|
|
476
|
+
!t.contains(n.target) && !e.contains(n.target) && (t.classList.remove("visible"), e.style.display = "flex");
|
|
411
477
|
});
|
|
412
478
|
}
|
|
413
|
-
function d(
|
|
414
|
-
console.log(
|
|
415
|
-
const
|
|
416
|
-
|
|
479
|
+
function d(n) {
|
|
480
|
+
console.log(n);
|
|
481
|
+
const t = document.getElementById("chat-icon"), e = document.getElementById("chat-window");
|
|
482
|
+
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");
|
|
417
483
|
}
|
|
418
|
-
typeof window < "u" && window.addEventListener("DOMContentLoaded", () => {
|
|
419
|
-
const
|
|
420
|
-
|
|
484
|
+
typeof window < "u" && window.addEventListener("DOMContentLoaded", async () => {
|
|
485
|
+
const t = ["climats", "telckel", "biobio", "weinpoint"].find((i) => window.location.href.includes(i)) || null;
|
|
486
|
+
let e;
|
|
487
|
+
t && (e = t.charAt(0).toUpperCase() + t.slice(1)), await s.fetchConfig(e || null), b(), w(), x(), d(t && t === "biobio" ? "right-center" : "bottom-right"), new y().initialize();
|
|
421
488
|
});
|
|
422
489
|
export {
|
|
423
|
-
|
|
490
|
+
h as closeChatWindow,
|
|
424
491
|
u as openChatWindow,
|
|
425
492
|
l as toggleChatWindow
|
|
426
493
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(
|
|
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";const r=`
|
|
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
|
-
}`,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
`,
|
|
276
|
+
}`,c=document.createElement("style");c.textContent=r,document.head.appendChild(c);function d(){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 l(){document.getElementById("chat-window").classList.remove("visible")}function p(){document.getElementById("chat-window").classList.add("visible")}document.addEventListener("DOMContentLoaded",()=>{setupCloseButton(),setupOutsideClick()});const f=["climats","telckel","biobio","weinpoint"];class g{constructor(t){this.baseURL="https://api.wineater.com/",this.store=f.find(e=>window.location.href.includes(e)),console.log(this.store)}async getStoreConfig(t){console.log(t);try{const e=await fetch(`${this.baseURL}stores/store`,{method:"POST",headers:{"Content-Type":"application/json"},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"},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 y{constructor(){this.api=new g,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 y;class b{constructor(){this.api=new g,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 u=document.createElement("img");u.src=o.Image,i.appendChild(u);const m=document.createElement("div");m.innerHTML=`
|
|
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=d,window.closeChatWindow=l,window.openChatWindow=p});function w(){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>${s.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="${s.translate("inputPlaceholder")}">
|
|
304
|
+
<button id="send-button">${s.translate("sendButton")}</button>
|
|
305
305
|
</div>
|
|
306
306
|
</div>
|
|
307
307
|
</div>
|
|
308
|
-
|
|
308
|
+
`;document.body.insertAdjacentHTML("beforeend",n)}function x(){document.getElementById("close-btn").addEventListener("click",d)}function v(){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 h(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")}typeof window<"u"&&window.addEventListener("DOMContentLoaded",async()=>{const t=["climats","telckel","biobio","weinpoint"].find(i=>window.location.href.includes(i))||null;let e;t&&(e=t.charAt(0).toUpperCase()+t.slice(1)),await s.fetchConfig(e||null),w(),x(),v(),h(t&&t==="biobio"?"right-center":"bottom-right"),new b().initialize()}),a.closeChatWindow=l,a.openChatWindow=p,a.toggleChatWindow=d,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import './js/styles.js';
|
|
|
7
7
|
import { toggleChatWindow, closeChatWindow, openChatWindow } from './js/ui.js';
|
|
8
8
|
import { Chatbot } from './js/chatbot.js';
|
|
9
9
|
import './js/api.js';
|
|
10
|
+
import translator from './js/i18n.js';
|
|
10
11
|
|
|
11
12
|
document.addEventListener('DOMContentLoaded', () => {
|
|
12
13
|
// Attach any necessary initialization code here
|
|
@@ -14,7 +15,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
14
15
|
window.toggleChatWindow = toggleChatWindow;
|
|
15
16
|
window.closeChatWindow = closeChatWindow;
|
|
16
17
|
window.openChatWindow = openChatWindow;
|
|
17
|
-
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
export {
|
|
@@ -28,7 +28,7 @@ function createChatbotUI() {
|
|
|
28
28
|
<div id="chatbot-container">
|
|
29
29
|
<div id="chat-icon" onclick="toggleChatWindow()">
|
|
30
30
|
<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 -->
|
|
31
|
-
<span
|
|
31
|
+
<span>${translator.translate('chatButton')}</span>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
34
|
<div id="chat-window" class="hidden">
|
|
@@ -45,8 +45,8 @@ function createChatbotUI() {
|
|
|
45
45
|
<span></span><span></span><span></span>
|
|
46
46
|
</div>
|
|
47
47
|
<div id="input-container">
|
|
48
|
-
<input type="text" id="user-input" placeholder="
|
|
49
|
-
<button id="send-button"
|
|
48
|
+
<input type="text" id="user-input" placeholder="${translator.translate('inputPlaceholder')}">
|
|
49
|
+
<button id="send-button">${translator.translate('sendButton')}</button>
|
|
50
50
|
</div>
|
|
51
51
|
</div>
|
|
52
52
|
</div>
|
|
@@ -91,9 +91,14 @@ function toggleChatIconPosition(position) {
|
|
|
91
91
|
|
|
92
92
|
// If you want to initialize your chatbot automatically when the script is loaded
|
|
93
93
|
if (typeof window !== 'undefined') {
|
|
94
|
-
window.addEventListener('DOMContentLoaded', () => {
|
|
94
|
+
window.addEventListener('DOMContentLoaded', async () => {
|
|
95
95
|
const stores = ['climats', 'telckel', 'biobio', 'weinpoint'];
|
|
96
96
|
const store = stores.find(value => window.location.href.includes(value)) || null;
|
|
97
|
+
let capitalizeStore;
|
|
98
|
+
if (store) {
|
|
99
|
+
capitalizeStore = store.charAt(0).toUpperCase() + store.slice(1)
|
|
100
|
+
}
|
|
101
|
+
await translator.fetchConfig(capitalizeStore || null);
|
|
97
102
|
createChatbotUI(); // Create the UI
|
|
98
103
|
setupCloseButton();
|
|
99
104
|
setupOutsideClick();
|
|
@@ -101,7 +106,7 @@ if (typeof window !== 'undefined') {
|
|
|
101
106
|
toggleChatIconPosition('right-center');
|
|
102
107
|
} else {
|
|
103
108
|
toggleChatIconPosition('bottom-right');
|
|
104
|
-
}
|
|
109
|
+
}
|
|
105
110
|
const myChatbot = new Chatbot();
|
|
106
111
|
myChatbot.initialize();
|
|
107
112
|
});
|
package/src/js/api.js
CHANGED
|
@@ -5,15 +5,33 @@ const stores = ['climats', 'telckel', 'biobio', 'weinpoint'];
|
|
|
5
5
|
export class Api {
|
|
6
6
|
constructor(apiEndpoint) {
|
|
7
7
|
// Allow users of the library to specify their own endpoint if needed
|
|
8
|
-
this.
|
|
8
|
+
this.baseURL = 'https://api.wineater.com/';
|
|
9
9
|
this.store = stores.find(value => window.location.href.includes(value));
|
|
10
10
|
console.log(this.store);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
async getStoreConfig(storeName) {
|
|
14
|
+
console.log(storeName);
|
|
15
|
+
try {
|
|
16
|
+
const response = await fetch(`${this.baseURL}stores/store`, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json'
|
|
20
|
+
},
|
|
21
|
+
body: JSON.stringify({ store: storeName })
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
|
|
24
|
+
return await response.json();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Error fetching store configuration:', error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
13
31
|
async getWineRecommendations(text) {
|
|
14
32
|
console.log(window.location.href);
|
|
15
33
|
try {
|
|
16
|
-
const response = await fetch(this.
|
|
34
|
+
const response = await fetch(`${this.baseURL}dish/recommendations`, {
|
|
17
35
|
method: 'POST',
|
|
18
36
|
headers: {
|
|
19
37
|
'Content-Type': 'application/json'
|
package/src/js/chatbot.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// chatbot.js
|
|
2
2
|
import { Api } from './api.js';
|
|
3
|
+
import translator from './i18n.js';
|
|
3
4
|
|
|
4
5
|
export class Chatbot {
|
|
5
6
|
constructor() {
|
|
6
7
|
this.api = new Api(); // Instantiate the Api class
|
|
7
|
-
this.displayFirstMessage(
|
|
8
|
+
this.displayFirstMessage(translator.translate('welcomeMessage'));
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
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?";
|
|
11
|
-
|
|
12
11
|
initialize() {
|
|
13
12
|
// Attach event listeners
|
|
14
13
|
const sendButton = document.getElementById('send-button');
|
|
@@ -58,8 +57,7 @@ export class Chatbot {
|
|
|
58
57
|
// Hide the loader
|
|
59
58
|
this.hideTypingIndicator();
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
this.displayMessage('Sorry, something went wrong.', 'api');
|
|
60
|
+
this.displayMessage(translator.translate('somethingWentWrong'), 'api');
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
63
|
|
|
@@ -94,11 +92,11 @@ export class Chatbot {
|
|
|
94
92
|
|
|
95
93
|
const contentDiv = document.createElement('div');
|
|
96
94
|
contentDiv.innerHTML = `
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
95
|
+
<strong>${wine.Title}</strong><br>
|
|
96
|
+
${translator.translate('price')}: ${wine.Price}<br>
|
|
97
|
+
${translator.translate('region')}: ${wine.Region}<br>
|
|
98
|
+
${translator.translate('type')}: ${wine.Type}<br>
|
|
99
|
+
<a href="${wine.Url}" target="_blank">${translator.translate('moreInfo')}</a>
|
|
102
100
|
`;
|
|
103
101
|
wineDiv.appendChild(contentDiv);
|
|
104
102
|
|
package/src/js/i18n.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Api } from './api.js';
|
|
2
|
+
|
|
3
|
+
class Translator {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.api = new Api();
|
|
6
|
+
this.language = 'en'; // Default to French
|
|
7
|
+
this.translations = {
|
|
8
|
+
fr: {
|
|
9
|
+
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?",
|
|
10
|
+
noResultsFound: "Aucun résultat trouvé.",
|
|
11
|
+
somethingWentWrong: "Désolé, quelque chose a mal tourné.",
|
|
12
|
+
chatButton: "Accorder le vin au dîner",
|
|
13
|
+
inputPlaceholder: "ex., Salade de thon",
|
|
14
|
+
sendButton: "Accorder",
|
|
15
|
+
price: "Prix",
|
|
16
|
+
region: "Région",
|
|
17
|
+
type: "Type",
|
|
18
|
+
moreInfo: "Plus d'infos"
|
|
19
|
+
},
|
|
20
|
+
es: {
|
|
21
|
+
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?",
|
|
22
|
+
noResultsFound: "No se encontraron resultados.",
|
|
23
|
+
somethingWentWrong: "Lo sentimos, algo salió mal.",
|
|
24
|
+
chatButton: "Maridar vino con cena",
|
|
25
|
+
inputPlaceholder: "ej., Ensalada de atún",
|
|
26
|
+
sendButton: "Maridar",
|
|
27
|
+
price: "Precio",
|
|
28
|
+
region: "Región",
|
|
29
|
+
type: "Tipo",
|
|
30
|
+
moreInfo: "Más info"
|
|
31
|
+
},
|
|
32
|
+
en: {
|
|
33
|
+
welcomeMessage: "Enhance your dining experience. Just provide your dish details and get the ideal wine pairing. What would you like to eat?",
|
|
34
|
+
noResultsFound: "No results found.",
|
|
35
|
+
somethingWentWrong: "Sorry, something went wrong.",
|
|
36
|
+
chatButton: "Pair wine with dinner",
|
|
37
|
+
inputPlaceholder: "e.g., Tuna Salad",
|
|
38
|
+
sendButton: "Pair",
|
|
39
|
+
price: "Price",
|
|
40
|
+
region: "Region",
|
|
41
|
+
type: "Type",
|
|
42
|
+
moreInfo: "More info"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async fetchConfig(storeName) {
|
|
48
|
+
if (storeName) {
|
|
49
|
+
const config = await this.api.getStoreConfig(storeName);
|
|
50
|
+
this.language = config.lang;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
translate(key) {
|
|
55
|
+
return this.translations[this.language][key] || key;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default new Translator();
|