wineater-bot 3.0.0 → 3.0.2
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 +32 -14
- package/dist/wineater-chatbot.umd.js +5 -5
- package/index.html +1 -1
- package/package.json +1 -1
- package/src/index.js +2 -2
- package/src/js/api.js +30 -3
- package/src/js/widget.js +27 -12
|
@@ -7161,11 +7161,11 @@ const Oa = `
|
|
|
7161
7161
|
`, Ti = document.createElement("style");
|
|
7162
7162
|
Ti.textContent = Oa;
|
|
7163
7163
|
document.head.appendChild(Ti);
|
|
7164
|
-
const Ra = ["climats", "telckel", "biobio", "weinpoint", "vinigrandi", "ampely"], Fa = "
|
|
7164
|
+
const Ra = ["climats", "telckel", "biobio", "weinpoint", "vinigrandi", "ampely"], Fa = "Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17";
|
|
7165
7165
|
class Ft {
|
|
7166
7166
|
constructor(e) {
|
|
7167
7167
|
var n;
|
|
7168
|
-
this.baseURL = "
|
|
7168
|
+
this.baseURL = "https://wineater-backend.vercel.app/", this.store = Ra.find((s) => window.location.href.includes(s)), this.token = ((n = window == null ? void 0 : window.wineaterData) == null ? void 0 : n.CLIENT_TOKEN) || Fa;
|
|
7169
7169
|
}
|
|
7170
7170
|
async getStoreConfig(e) {
|
|
7171
7171
|
console.log(e);
|
|
@@ -7203,6 +7203,24 @@ class Ft {
|
|
|
7203
7203
|
throw console.error("Fetching wine recommendations failed:", n.message), new Error(`Error in getWineRecommendations: ${n.message}`);
|
|
7204
7204
|
}
|
|
7205
7205
|
}
|
|
7206
|
+
async getWineRecommendationsSearch(e) {
|
|
7207
|
+
console.log(window.location.href);
|
|
7208
|
+
try {
|
|
7209
|
+
const n = await fetch(`${this.baseURL}dish/recommendations/search`, {
|
|
7210
|
+
method: "POST",
|
|
7211
|
+
headers: {
|
|
7212
|
+
"Content-Type": "application/json",
|
|
7213
|
+
Authorization: `Bearer ${this.token}`
|
|
7214
|
+
},
|
|
7215
|
+
body: JSON.stringify({ text: e, store: this.store ? this.store.toString().charAt(0).toUpperCase() + this.store.slice(1) : void 0 })
|
|
7216
|
+
}), s = await n.json();
|
|
7217
|
+
if (!n.ok)
|
|
7218
|
+
throw new Error(`API call failed with status ${n.status}: ${s.message || "No additional error information"}`);
|
|
7219
|
+
return s;
|
|
7220
|
+
} catch (n) {
|
|
7221
|
+
throw console.error("Fetching wine recommendations failed:", n.message), new Error(`Error in getWineRecommendations: ${n.message}`);
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7206
7224
|
async getPossibleDishesWithMeta(e, n) {
|
|
7207
7225
|
try {
|
|
7208
7226
|
const s = await fetch(`${this.baseURL}dish/possible_dishes`, {
|
|
@@ -7447,7 +7465,7 @@ class Da {
|
|
|
7447
7465
|
<div id="powered-by-widget">
|
|
7448
7466
|
<a href="https://wineater.com" target="_blank">
|
|
7449
7467
|
<span>${G.translate("poweredBy")}</span>
|
|
7450
|
-
<img src="https://
|
|
7468
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo">
|
|
7451
7469
|
</a>
|
|
7452
7470
|
</div>
|
|
7453
7471
|
</div>
|
|
@@ -7470,20 +7488,20 @@ class Da {
|
|
|
7470
7488
|
const s = document.querySelectorAll(`#${e} button`);
|
|
7471
7489
|
s.forEach((i) => {
|
|
7472
7490
|
i.addEventListener("click", (r) => {
|
|
7473
|
-
s.forEach((o) => o.classList.remove("selected")), r.target.classList.add("selected"), this.selectedFilters[n] = r.target.dataset.value;
|
|
7491
|
+
s.forEach((o) => o.classList.remove("selected")), r.target.classList.add("selected"), this.selectedFilters[n] = r.target.dataset.value, this.handleSearch();
|
|
7474
7492
|
});
|
|
7475
7493
|
});
|
|
7476
7494
|
}
|
|
7477
7495
|
async handleSearch() {
|
|
7478
|
-
const e = document.getElementById("wine-search-input").value;
|
|
7479
|
-
|
|
7480
|
-
const
|
|
7481
|
-
console.log("Searching for:",
|
|
7496
|
+
const e = "wine for" + document.getElementById("wine-search-input").value.trim(), n = this.selectedFilters, s = [];
|
|
7497
|
+
n.price && s.push(`with price ${n.price}`), n.color && s.push(`of color ${n.color}`), n.intensity && s.push(`with intensity ${n.intensity}`);
|
|
7498
|
+
const i = s.length > 0 ? `${e} ${s.join(", ")}` : e;
|
|
7499
|
+
console.log("Searching for:", i), console.log("Applied filters:", n), this.animateCardDisappearance();
|
|
7482
7500
|
try {
|
|
7483
|
-
const
|
|
7484
|
-
|
|
7485
|
-
} catch (
|
|
7486
|
-
console.error("Error fetching wine recommendations:",
|
|
7501
|
+
const r = await this.api.getWineRecommendationsSearch(i);
|
|
7502
|
+
r && r.length > 0 ? (console.log("Recommendations:", r), this.displayResults(r, !0)) : (console.log("No recommendations found."), this.displayNoResultsMessage());
|
|
7503
|
+
} catch (r) {
|
|
7504
|
+
console.error("Error fetching wine recommendations:", r.message), this.displayErrorMessage();
|
|
7487
7505
|
}
|
|
7488
7506
|
}
|
|
7489
7507
|
displayResults(e, n = !1) {
|
|
@@ -7711,7 +7729,7 @@ class Wa {
|
|
|
7711
7729
|
const e = Xn.getValue("chat-btn-txt"), s = `
|
|
7712
7730
|
<div id="chatbot-container">
|
|
7713
7731
|
<div id="chat-icon">
|
|
7714
|
-
<img src="https://
|
|
7732
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/chat-icon.svg" alt="Chat Icon">
|
|
7715
7733
|
<span>${((i = window == null ? void 0 : window.wineaterData) == null ? void 0 : i.BUTTON_TEXT) || G.translate(`chatButton${e}`)}</span>
|
|
7716
7734
|
</div>
|
|
7717
7735
|
<div id="chat-window" class="hidden">
|
|
@@ -7732,7 +7750,7 @@ class Wa {
|
|
|
7732
7750
|
<div id="powered-by">
|
|
7733
7751
|
<a href="https://wineater.com" target="_blank">
|
|
7734
7752
|
<span>${G.translate("poweredBy")}</span>
|
|
7735
|
-
<img src="https://
|
|
7753
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo" id="chatbot-logo">
|
|
7736
7754
|
</a>
|
|
7737
7755
|
</div>
|
|
7738
7756
|
</div>
|
|
@@ -970,7 +970,7 @@ If you're using serverside rendering in your app, make sure that tracker is load
|
|
|
970
970
|
max-width: 100px;
|
|
971
971
|
}
|
|
972
972
|
}
|
|
973
|
-
`,fi=document.createElement("style");fi.textContent=Oa,document.head.appendChild(fi);const Ra=["climats","telckel","biobio","weinpoint","vinigrandi","ampely"],Fa="
|
|
973
|
+
`,fi=document.createElement("style");fi.textContent=Oa,document.head.appendChild(fi);const Ra=["climats","telckel","biobio","weinpoint","vinigrandi","ampely"],Fa="Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17";class Rt{constructor(e){var n;this.baseURL="https://wineater-backend.vercel.app/",this.store=Ra.find(s=>window.location.href.includes(s)),this.token=((n=window==null?void 0:window.wineaterData)==null?void 0:n.CLIENT_TOKEN)||Fa}async getStoreConfig(e){console.log(e);try{const n=await fetch(`${this.baseURL}stores/store`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({store:e})});if(console.log(n),!n.ok)throw new Error(`HTTP error! Status: ${n.status}`);return await n.json()}catch(n){throw console.error("Error fetching store configuration:",n),n}}async getWineRecommendations(e){console.log(window.location.href);try{const n=await fetch(`${this.baseURL}dish/recommendations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({text:e,store:this.store?this.store.toString().charAt(0).toUpperCase()+this.store.slice(1):void 0})}),s=await n.json();if(!n.ok)throw new Error(`API call failed with status ${n.status}: ${s.message||"No additional error information"}`);return s}catch(n){throw console.error("Fetching wine recommendations failed:",n.message),new Error(`Error in getWineRecommendations: ${n.message}`)}}async getWineRecommendationsSearch(e){console.log(window.location.href);try{const n=await fetch(`${this.baseURL}dish/recommendations/search`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({text:e,store:this.store?this.store.toString().charAt(0).toUpperCase()+this.store.slice(1):void 0})}),s=await n.json();if(!n.ok)throw new Error(`API call failed with status ${n.status}: ${s.message||"No additional error information"}`);return s}catch(n){throw console.error("Fetching wine recommendations failed:",n.message),new Error(`Error in getWineRecommendations: ${n.message}`)}}async getPossibleDishesWithMeta(e,n){try{const s=await fetch(`${this.baseURL}dish/possible_dishes`,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"Content-Type":"application/json"},body:JSON.stringify({title:e,description:n})}),i=await s.json();if(console.log(i),!s.ok)throw new Error(`API call failed with status ${s.status}: ${i.message||"No additional error information"}`);return i}catch(s){throw console.error("Error fetching possible dishes:",s),s}}async getInstantRecommendations(){console.log("Fetching instant recommendations...");try{const e=await fetch(`${this.baseURL}dish/recommendations/instant`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.token}`},body:JSON.stringify({store:this.store})}),n=await e.json();if(!e.ok)throw new Error(`API call failed with status ${e.status}: ${n.message||"No additional error information"}`);return console.log("Instant recommendations:",n),n}catch(e){throw console.error("Fetching instant recommendations failed:",e.message),new Error(`Error in getInstantRecommendations: ${e.message}`)}}}class Aa{constructor(){this.api=new Rt,this.language="en",this.translations={fr:{welcomeMessage:"Quel plat allez-vous déguster ? Décrivez-le-moi et je vous proposerai le vin qui l'accompagnera parfaitement.",noResultsFound:"Aucun résultat trouvé.",somethingWentWrong:"Désolé, quelque chose a mal tourné.",chatButton1:"Trouvez l'accord parfait",chatButton2:"Associez le vin",chatButton3:"Obtenez des conseils",chatTitle:"Accord Mets & Vins 🍷",chatSubtitle:"Décrivez votre plat et obtenez une recommandation en 30 secondes",inputPlaceholder:"ex., Salade de thon",sendButton:"Accorder",poweredBy:"Propulsé par",price:"Prix",region:"Région",type:"Type",reason:"Suggestion",moreInfo:"Plus d'infos",winePairingIntro:"Pour ce vin, voici quelques suggestions de plats :",askForDinner:"Que voulez-vous manger ce soir?",clearChatButton:"Effacer le chat",widgetTitle:"Découvrez votre vin",widgetSubtitle:"Recherchez par vos préférences",searchPlaceholder:"Entrez un mot-clé ou une description",searchButton:"Rechercher",priceRange:"Gamme de prix",wineColor:"Couleur du vin",intensity:"Intensité",red:"Rouge",white:"Blanc",rose:"Rosé",light:"Léger",medium:"Moyen",full:"Puissant"},es:{welcomeMessage:"¿Qué vas a comer? Cuéntame tu plato y te recomendaré el maridaje perfecto.",noResultsFound:"No se encontraron resultados.",somethingWentWrong:"Lo sentimos, algo salió mal.",chatButton1:"Encuentra tu maridaje",chatButton2:"Combina vino ya",chatButton3:"Recibe asesoría ahora",chatTitle:"Maridaje de Vinos 🍷",chatSubtitle:"Describe tu comida y obtén una recomendación en 30 segundos",inputPlaceholder:"ej., Ensalada de atún",sendButton:"Combinar",poweredBy:"Desarrollado por",price:"Precio",region:"Región",type:"Tipo",reason:"Sugerencia",moreInfo:"Más info",winePairingIntro:"Para este vino, aquí tienes algunas sugerencias de platos:",askForDinner:"¿Qué te gustaría cenar?",clearChatButton:"Limpiar el chat",widgetTitle:"Encuentra tu vino",widgetSubtitle:"Busca según tus preferencias",searchPlaceholder:"Escribe una palabra clave o descripción",searchButton:"Buscar",priceRange:"Rango de precios",wineColor:"Color del vino",intensity:"Intensidad",red:"Tinto",white:"Blanco",rose:"Rosado",light:"Ligero",medium:"Medio",full:"Intenso"},en:{welcomeMessage:"What are you planning to eat? Share your dish and I'll recommend the perfect wine pairing for your meal.",noResultsFound:"No results found.",somethingWentWrong:"Sorry, something went wrong.",chatButton1:"Find Your Pairing",chatButton2:"Pair Wine Now",chatButton3:"Get Wine Advice",chatTitle:"Wine Pairing Assistant 🍷",chatSubtitle:"Describe your meal and get a recommendation in 30 seconds",inputPlaceholder:"e.g., Tuna salad",sendButton:"Match",poweredBy:"Powered by",price:"Price",region:"Region",type:"Type",reason:"Suggestion",moreInfo:"More info",winePairingIntro:"For this wine, here are some suggested dishes:",askForDinner:"What would you like to have for dinner?",clearChatButton:"Clear Chat",widgetTitle:"Discover Your Wine",widgetSubtitle:"Search by your preferences",searchPlaceholder:"Enter a keyword or description",searchButton:"Search",priceRange:"Price Range",wineColor:"Wine Color",intensity:"Intensity",red:"Red",white:"White",rose:"Rosé",light:"Light",medium:"Medium",full:"Full"},de:{welcomeMessage:"Was möchten Sie essen? Beschreiben Sie Ihr Gericht und ich empfehle Ihnen den perfekten Wein dazu.",noResultsFound:"Keine Ergebnisse gefunden.",somethingWentWrong:"Entschuldigung, etwas ist schief gelaufen.",chatButton1:"Finde Dein Pairing",chatButton2:"Wein jetzt wählen",chatButton3:"Erhalte Weinberatung",chatTitle:"Wein & Speisen 🍷",chatSubtitle:"Beschreiben Sie Ihr Gericht und erhalten Sie in 30 Sekunden eine Empfehlung",inputPlaceholder:"z.B., Thunfischsalat",sendButton:"Kombinieren",poweredBy:"Unterstützt von",price:"Preis",region:"Region",type:"Typ",reason:"Anregung",moreInfo:"Mehr Info",winePairingIntro:"Für diesen Wein gibt es folgende Essensvorschläge:",askForDinner:"Was möchten Sie zum Abendessen essen?",clearChatButton:"Chat löschen",widgetTitle:"Finden Sie Ihren Wein",widgetSubtitle:"Suchen Sie nach Ihren Vorlieben",searchPlaceholder:"Geben Sie ein Stichwort oder eine Beschreibung ein",searchButton:"Suche",priceRange:"Preisspanne",wineColor:"Weinfarbe",intensity:"Intensität",red:"Rot",white:"Weiß",rose:"Rosé",light:"Leicht",medium:"Mittel",full:"Voll"}}}async fetchConfig(e){console.log(e);try{const n=await this.api.getStoreConfig(e);console.log(n),this.language=n.lang}catch{this.language="en"}console.log(this.language)}translate(e){return this.translations[this.language][e]||e}}const V=new Aa;class Da{constructor(){this.api=new Rt,this.selectedFilters={price:null,color:null,intensity:null},this.initializeWidget(),this.loadInstantRecommendations()}initializeWidget(){const e=`
|
|
974
974
|
<div id="wine-widget-container">
|
|
975
975
|
<div id="wine-widget-left">
|
|
976
976
|
<div id="wine-widget-header">
|
|
@@ -1010,7 +1010,7 @@ If you're using serverside rendering in your app, make sure that tracker is load
|
|
|
1010
1010
|
<div id="powered-by-widget">
|
|
1011
1011
|
<a href="https://wineater.com" target="_blank">
|
|
1012
1012
|
<span>${V.translate("poweredBy")}</span>
|
|
1013
|
-
<img src="https://
|
|
1013
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo">
|
|
1014
1014
|
</a>
|
|
1015
1015
|
</div>
|
|
1016
1016
|
</div>
|
|
@@ -1021,7 +1021,7 @@ If you're using serverside rendering in your app, make sure that tracker is load
|
|
|
1021
1021
|
<div id="wine-placeholder"></div>
|
|
1022
1022
|
</div>
|
|
1023
1023
|
</div>
|
|
1024
|
-
`;document.body.insertAdjacentHTML("beforeend",e),this.addEventListeners()}addEventListeners(){document.getElementById("wine-search-button").addEventListener("click",()=>this.handleSearch()),this.setupFilterButtons("price-buttons","price"),this.setupFilterButtons("color-buttons","color"),this.setupFilterButtons("intensity-buttons","intensity"),document.getElementById("wine-search-input").addEventListener("keydown",e=>{e.key==="Enter"&&this.handleSearch()})}setupFilterButtons(e,n){const s=document.querySelectorAll(`#${e} button`);s.forEach(i=>{i.addEventListener("click",r=>{s.forEach(o=>o.classList.remove("selected")),r.target.classList.add("selected"),this.selectedFilters[n]=r.target.dataset.value})})}async handleSearch(){const e=document.getElementById("wine-search-input").value
|
|
1024
|
+
`;document.body.insertAdjacentHTML("beforeend",e),this.addEventListeners()}addEventListeners(){document.getElementById("wine-search-button").addEventListener("click",()=>this.handleSearch()),this.setupFilterButtons("price-buttons","price"),this.setupFilterButtons("color-buttons","color"),this.setupFilterButtons("intensity-buttons","intensity"),document.getElementById("wine-search-input").addEventListener("keydown",e=>{e.key==="Enter"&&this.handleSearch()})}setupFilterButtons(e,n){const s=document.querySelectorAll(`#${e} button`);s.forEach(i=>{i.addEventListener("click",r=>{s.forEach(o=>o.classList.remove("selected")),r.target.classList.add("selected"),this.selectedFilters[n]=r.target.dataset.value,this.handleSearch()})})}async handleSearch(){const e="wine for"+document.getElementById("wine-search-input").value.trim(),n=this.selectedFilters,s=[];n.price&&s.push(`with price ${n.price}`),n.color&&s.push(`of color ${n.color}`),n.intensity&&s.push(`with intensity ${n.intensity}`);const i=s.length>0?`${e} ${s.join(", ")}`:e;console.log("Searching for:",i),console.log("Applied filters:",n),this.animateCardDisappearance();try{const r=await this.api.getWineRecommendationsSearch(i);r&&r.length>0?(console.log("Recommendations:",r),this.displayResults(r,!0)):(console.log("No recommendations found."),this.displayNoResultsMessage())}catch(r){console.error("Error fetching wine recommendations:",r.message),this.displayErrorMessage()}}displayResults(e,n=!1){const s=document.getElementById("wine-placeholder");this.hideLoadingIndicator(),s.innerHTML="",e.forEach((i,r)=>{const o=`
|
|
1025
1025
|
<div class="wine-recommendation-tile ${r===e.length-1?"somm-selection":""}">
|
|
1026
1026
|
${r===e.length-1?'<div class="somm-selection-badge">Somm Selection</div>':""}
|
|
1027
1027
|
<img src="${i.Image}" alt="${i.Title}" />
|
|
@@ -1050,7 +1050,7 @@ If you're using serverside rendering in your app, make sure that tracker is load
|
|
|
1050
1050
|
`,l.querySelector("a").addEventListener("click",c=>{c.preventDefault(),this.sendAnalytics(s.Title),window.open(s.Url,"_blank")}),r.appendChild(l);const h=document.createElement("div");h.className="wine-description",h.innerHTML=s.Reason,i.appendChild(h),console.log(i),n.appendChild(i)}),n.scrollTop=n.scrollHeight}}const La=3;let Ft=null;function Pa(){const t=document.getElementById("chat-window"),e=document.getElementById("chat-icon");t.classList.contains("visible")?(qn(),Ba(),e.style.display="flex"):(Ft&&(clearTimeout(Ft),Ft=null),Ni(),t.classList.add("visible"),e.style.display="none")}function Ba(){console.log("ghbdtn"),qn(),document.getElementById("chat-window").classList.remove("visible");let e=parseInt(se("chatCloseCount"))||0;e+=1,e>=La?(console.log(e),rt("disableAutoOpen","true",1),Ci("chatCloseCount")):(console.log(e),rt("chatCloseCount",e,1))}document.addEventListener("DOMContentLoaded",()=>{setupCloseButton(),setupOutsideClick()});function ja(t){Ft=t}new Rt;const At={PRODUCT_PAGES:/producto\/[^\/]+\/$/},pi={FESTIVAL_PAGES:/festival/,TASTING_PAGES:/tasting/},Ua={FESTIVAL_PAGES:((mi=window.wineaterData)==null?void 0:mi.FESTIVAL_PAGES)||pi.FESTIVAL_PAGES,TASTING_PAGES:((bi=window.wineaterData)==null?void 0:bi.TASTING_PAGES)||pi.TASTING_PAGES},za={PRODUCT_PAGES:((vi=window.wineaterData)==null?void 0:vi.PRODUCT_PAGES)||At.PRODUCT_PAGES,CART_PAGE:((yi=window.wineaterData)==null?void 0:yi.CART_PAGE)||(At==null?void 0:At.CART_PAGE)};async function Ha(){const t=window.location.href;for(const[e,n]of Object.entries(Ua))if(n.test(t))return!1;for(const[e,n]of Object.entries(za))if(n.test(t))try{console.log(dishes);const s=setTimeout(()=>{openChatWindow()},15e3);return ja(s),!0}catch(s){return console.error("Error fetching dishes:",s),!1}return!1}const $a="tbMTFzLbWcXFgXK8SzyFHA6kIjelFcz5VQABVPbXdXh5XZJCDQH9BcVlrv3DF3kA";class Wa{constructor(){var e,n;this.stores=["climats","telckel","biobio","weinpoint","vinigrandi","ampely"],this.tracker=new Na({projectKey:"PA8j9fAi49i6g2QnvpNs",__DISABLE_SECURE_MODE:!0}),this.position=((e=window==null?void 0:window.wineaterData)==null?void 0:e.POSITION)||"right-center",this.type=((n=window==null?void 0:window.wineaterData)==null?void 0:n.TYPE)||"chatbot",this.store=this.detectStore()}detectStore(){return this.stores.find(e=>window.location.href.includes(e))||null}async initFlagsmith(){try{await Gn.init({environmentID:"5RfiDoiqb4dHrNdQvzbkfM",cacheFlags:!1,enableAnalytics:!0,identity:se("uniqueUserID")})}catch(e){console.error("Flagsmith initialization failed:",e)}}async initTranslator(){const e=this.store?this.store.charAt(0).toUpperCase()+this.store.slice(1):"Climats";await V.fetchConfig(e||"Climats")}initCookies(){var e;rt("chatbotToken",((e=window.wineaterData)==null?void 0:e.CLIENT_TOKEN)||$a,365),_i()}async initializeChatbotOrWidget(){this.type==="widget"?new Da:(this.createChatbotUI(),this.setupChatListeners(),this.setupChatButtonListener(),qa(this.position),new Ma().initialize())}createChatbotUI(){var i;const e=Gn.getValue("chat-btn-txt"),s=`
|
|
1051
1051
|
<div id="chatbot-container">
|
|
1052
1052
|
<div id="chat-icon">
|
|
1053
|
-
<img src="https://
|
|
1053
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/chat-icon.svg" alt="Chat Icon">
|
|
1054
1054
|
<span>${((i=window==null?void 0:window.wineaterData)==null?void 0:i.BUTTON_TEXT)||V.translate(`chatButton${e}`)}</span>
|
|
1055
1055
|
</div>
|
|
1056
1056
|
<div id="chat-window" class="hidden">
|
|
@@ -1071,7 +1071,7 @@ If you're using serverside rendering in your app, make sure that tracker is load
|
|
|
1071
1071
|
<div id="powered-by">
|
|
1072
1072
|
<a href="https://wineater.com" target="_blank">
|
|
1073
1073
|
<span>${V.translate("poweredBy")}</span>
|
|
1074
|
-
<img src="https://
|
|
1074
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo" id="chatbot-logo">
|
|
1075
1075
|
</a>
|
|
1076
1076
|
</div>
|
|
1077
1077
|
</div>
|
package/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Chatbot</title>
|
|
7
7
|
<!-- <script type="module" src="https://unpkg.com/wineater-bot@1.0.0/dist/wineater-chatbot.umd.js"></script> -->
|
|
8
|
-
<script>window.wineaterData = {CLIENT_TOKEN: '
|
|
8
|
+
<script>window.wineaterData = {CLIENT_TOKEN: 'Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17', position: 'right-center'};</script>
|
|
9
9
|
<script type="module" src="./src/index.js"></script>
|
|
10
10
|
</head>
|
|
11
11
|
<body style="margin: 0;">
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -65,7 +65,7 @@ class App {
|
|
|
65
65
|
const chatbotHTML = `
|
|
66
66
|
<div id="chatbot-container">
|
|
67
67
|
<div id="chat-icon">
|
|
68
|
-
<img src="https://
|
|
68
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/chat-icon.svg" alt="Chat Icon">
|
|
69
69
|
<span>${buttonText}</span>
|
|
70
70
|
</div>
|
|
71
71
|
<div id="chat-window" class="hidden">
|
|
@@ -86,7 +86,7 @@ class App {
|
|
|
86
86
|
<div id="powered-by">
|
|
87
87
|
<a href="https://wineater.com" target="_blank">
|
|
88
88
|
<span>${translator.translate('poweredBy')}</span>
|
|
89
|
-
<img src="https://
|
|
89
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo" id="chatbot-logo">
|
|
90
90
|
</a>
|
|
91
91
|
</div>
|
|
92
92
|
</div>
|
package/src/js/api.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// api.js
|
|
2
2
|
|
|
3
3
|
const stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi', 'ampely'];
|
|
4
|
-
const DEMO_TOKEN='
|
|
4
|
+
const DEMO_TOKEN='Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17';
|
|
5
5
|
|
|
6
6
|
export class Api {
|
|
7
7
|
constructor(apiEndpoint) {
|
|
8
8
|
// Allow users of the library to specify their own endpoint if needed
|
|
9
|
-
this.baseURL = 'http://localhost:3000/';
|
|
10
|
-
|
|
9
|
+
// this.baseURL = 'http://localhost:3000/';
|
|
10
|
+
this.baseURL = 'https://wineater-backend.vercel.app/';
|
|
11
11
|
this.store = stores.find(value => window.location.href.includes(value));
|
|
12
12
|
this.token = window?.wineaterData?.CLIENT_TOKEN || DEMO_TOKEN;
|
|
13
13
|
}
|
|
@@ -59,6 +59,33 @@ export class Api {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
async getWineRecommendationsSearch(text) {
|
|
63
|
+
console.log(window.location.href);
|
|
64
|
+
try {
|
|
65
|
+
const response = await fetch(`${this.baseURL}dish/recommendations/search`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
'Authorization': `Bearer ${this.token}`
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify({ text: text, store: this.store ? (this.store.toString().charAt(0).toUpperCase() + this.store.slice(1)) : undefined})
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const data = await response.json();
|
|
75
|
+
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
// Providing more detailed error information
|
|
78
|
+
throw new Error(`API call failed with status ${response.status}: ${data.message || 'No additional error information'}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return data;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
// Log and rethrow to allow consumer of the API to handle or display the error appropriately
|
|
84
|
+
console.error('Fetching wine recommendations failed:', error.message);
|
|
85
|
+
throw new Error(`Error in getWineRecommendations: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
62
89
|
async getPossibleDishesWithMeta(metaTitle, metaDescription) {
|
|
63
90
|
try {
|
|
64
91
|
const response = await fetch(`${this.baseURL}dish/possible_dishes`, {
|
package/src/js/widget.js
CHANGED
|
@@ -56,7 +56,7 @@ export class WineWidget {
|
|
|
56
56
|
<div id="powered-by-widget">
|
|
57
57
|
<a href="https://wineater.com" target="_blank">
|
|
58
58
|
<span>${translator.translate('poweredBy')}</span>
|
|
59
|
-
<img src="https://
|
|
59
|
+
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo">
|
|
60
60
|
</a>
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
@@ -92,29 +92,44 @@ export class WineWidget {
|
|
|
92
92
|
buttons.forEach(btn => btn.classList.remove('selected'));
|
|
93
93
|
e.target.classList.add('selected');
|
|
94
94
|
this.selectedFilters[filterKey] = e.target.dataset.value;
|
|
95
|
+
this.handleSearch();
|
|
95
96
|
});
|
|
96
97
|
});
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
async handleSearch() {
|
|
100
|
-
const query = document.getElementById('wine-search-input').value;
|
|
101
|
-
|
|
102
|
-
// Показать эффект исчезновения карточек
|
|
103
|
-
this.animateCardDisappearance();
|
|
104
|
-
|
|
105
|
-
// Показать индикатор загрузки
|
|
106
|
-
|
|
101
|
+
const query = 'wine for' + document.getElementById('wine-search-input').value.trim();
|
|
107
102
|
|
|
108
103
|
// Учитываем текущие выбранные фильтры
|
|
109
104
|
const filters = this.selectedFilters;
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
|
|
105
|
+
|
|
106
|
+
// Формируем органичную фразу с фильтрами
|
|
107
|
+
const filterPhrases = [];
|
|
108
|
+
if (filters.price) {
|
|
109
|
+
filterPhrases.push(`with price ${filters.price}`);
|
|
110
|
+
}
|
|
111
|
+
if (filters.color) {
|
|
112
|
+
filterPhrases.push(`of color ${filters.color}`);
|
|
113
|
+
}
|
|
114
|
+
if (filters.intensity) {
|
|
115
|
+
filterPhrases.push(`with intensity ${filters.intensity}`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Объединяем фильтры с основным запросом
|
|
119
|
+
const fullQuery = filterPhrases.length > 0
|
|
120
|
+
? `${query} ${filterPhrases.join(', ')}`
|
|
121
|
+
: query;
|
|
122
|
+
|
|
123
|
+
// Логирование запроса
|
|
124
|
+
console.log('Searching for:', fullQuery);
|
|
113
125
|
console.log('Applied filters:', filters);
|
|
114
126
|
|
|
127
|
+
// Показать эффект исчезновения карточек и индикатор загрузки
|
|
128
|
+
this.animateCardDisappearance();
|
|
129
|
+
|
|
115
130
|
try {
|
|
116
131
|
// Вызываем API метод для получения рекомендаций
|
|
117
|
-
const results = await this.api.
|
|
132
|
+
const results = await this.api.getWineRecommendationsSearch(fullQuery);
|
|
118
133
|
|
|
119
134
|
// Проверяем, есть ли данные
|
|
120
135
|
if (results && results.length > 0) {
|