wineater-bot 2.1.4 → 3.0.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/index.html CHANGED
@@ -5,9 +5,10 @@
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: 'K0ZzlrfT0z00J6dSAt8ZEIKWiUfypG1Tyb1ZGtgwuJaF8WZuRKlHfvEMCF9DyytZ', position: 'right-center'};</script><script type="module" src="./src/index.js"></script>
8
+ <script>window.wineaterData = {CLIENT_TOKEN: 'K0ZzlrfT0z00J6dSAt8ZEIKWiUfypG1Tyb1ZGtgwuJaF8WZuRKlHfvEMCF9DyytZ', position: 'right-center'};</script>
9
+ <script type="module" src="./src/index.js"></script>
9
10
  </head>
10
11
  <body style="margin: 0;">
11
- <img src="./src/assets/biobio.png" style="width: 100vw; height: 100vh; margin: 0;">
12
+ <div id="widget-container"></div> <!-- Контейнер для виджета -->
12
13
  </body>
13
14
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wineater-bot",
3
- "version": "2.1.4",
3
+ "version": "3.0.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
package/src/index.js CHANGED
@@ -1,58 +1,74 @@
1
- // src/index.js
2
-
3
- // Import your CSS here
4
1
  import './js/styles.js';
5
2
  import { setCookie, setUniqueUserCookie, getCookie } from './js/analytics.js';
6
- import flagsmith from 'flagsmith'; //Add this line if you're using flagsmith via npm
7
-
8
-
3
+ import flagsmith from 'flagsmith';
9
4
  import Tracker from '@openreplay/tracker';
5
+ import { WineWidget } from './js/widget.js';
6
+ import { Chatbot } from './js/chatbot.js';
7
+ import translator from './js/i18n.js';
8
+ import { shouldOpenChatAutomatically } from './js/auto-open.js';
9
+ import { toggleChatWindow, closeChatWindow, openChatWindow } from './js/ui.js';
10
10
 
11
- const tracker = new Tracker({
12
- projectKey: "PA8j9fAi49i6g2QnvpNs",
13
- '__DISABLE_SECURE_MODE': true
14
- });
11
+ const DEMO_TOKEN = 'tbMTFzLbWcXFgXK8SzyFHA6kIjelFcz5VQABVPbXdXh5XZJCDQH9BcVlrv3DF3kA';
15
12
 
16
- // Import your JavaScript modules here
17
- import { toggleChatWindow, closeChatWindow, openChatWindow } from './js/ui.js';
18
- import { Chatbot } from './js/chatbot.js';
19
- import './js/api.js';
20
- import translator from './js/i18n.js';
21
- import {shouldOpenChatAutomatically} from './js/auto-open.js'
13
+ class App {
14
+ constructor() {
15
+ this.stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi', 'ampely'];
16
+ this.tracker = new Tracker({ projectKey: "PA8j9fAi49i6g2QnvpNs", '__DISABLE_SECURE_MODE': true });
17
+ this.position = window?.wineaterData?.POSITION || 'right-center';
18
+ this.type = window?.wineaterData?.TYPE || 'chatbot';
19
+ this.store = this.detectStore();
20
+ }
21
+
22
+ detectStore() {
23
+ return this.stores.find(store => window.location.href.includes(store)) || null;
24
+ }
22
25
 
23
- const DEMO_TOKEN='tbMTFzLbWcXFgXK8SzyFHA6kIjelFcz5VQABVPbXdXh5XZJCDQH9BcVlrv3DF3kA';
26
+ async initFlagsmith() {
27
+ try {
28
+ await flagsmith.init({
29
+ environmentID: '5RfiDoiqb4dHrNdQvzbkfM',
30
+ cacheFlags: false,
31
+ enableAnalytics: true,
32
+ identity: getCookie('uniqueUserID'),
33
+ });
34
+ } catch (error) {
35
+ console.error('Flagsmith initialization failed:', error);
36
+ }
37
+ }
24
38
 
39
+ async initTranslator() {
40
+ const storeName = this.store ? this.store.charAt(0).toUpperCase() + this.store.slice(1) : 'Climats';
41
+ await translator.fetchConfig(storeName || 'Climats');
42
+ }
25
43
 
26
- document.addEventListener('DOMContentLoaded', () => {
27
- // Attach any necessary initialization code here
28
- // For example, expose functions to global scope if absolutely necessary
29
- window.toggleChatWindow = toggleChatWindow;
30
- window.closeChatWindow = closeChatWindow;
31
- window.openChatWindow = openChatWindow;
32
- });
33
-
34
- export {
35
- toggleChatWindow,
36
- closeChatWindow,
37
- openChatWindow
38
- };
39
-
40
- function getUniqueId() {
41
- const uniqueId = getCookie()
42
- }
44
+ initCookies() {
45
+ setCookie('chatbotToken', window.wineaterData?.CLIENT_TOKEN || DEMO_TOKEN, 365);
46
+ setUniqueUserCookie();
47
+ }
43
48
 
44
- function createChatbotUI() {
45
- tracker.start();
46
- const btnTextOption = flagsmith.getValue('chat-btn-txt');
47
- const buttonText = window?.wineaterData?.BUTTON_TEXT || translator.translate(`chatButton${btnTextOption}`);
48
- const chatbotHTML = `
49
- <div id="chatbot-container">
50
- <div id="chat-icon" onclick="toggleChatWindow()">
51
- <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 -->
52
- <span>${buttonText}</span>
53
- </div>
49
+ async initializeChatbotOrWidget() {
50
+ if (this.type === 'widget') {
51
+ new WineWidget();
52
+ } else {
53
+ this.createChatbotUI();
54
+ this.setupChatListeners();
55
+ this.setupChatButtonListener();
56
+ applyPositionToChat(this.position);
57
+ const chatbot = new Chatbot();
58
+ chatbot.initialize();
59
+ }
60
+ }
54
61
 
55
- <div id="chat-window" class="hidden">
62
+ createChatbotUI() {
63
+ const btnTextOption = flagsmith.getValue('chat-btn-txt');
64
+ const buttonText = window?.wineaterData?.BUTTON_TEXT || translator.translate(`chatButton${btnTextOption}`);
65
+ const chatbotHTML = `
66
+ <div id="chatbot-container">
67
+ <div id="chat-icon">
68
+ <img src="https://landing-static.s3.eu-central-1.amazonaws.com/images/chat-icon.svg" alt="Chat Icon">
69
+ <span>${buttonText}</span>
70
+ </div>
71
+ <div id="chat-window" class="hidden">
56
72
  <div id="chat-header">
57
73
  <div id="chat-title">
58
74
  <h1>${translator.translate('chatTitle')}</h1>
@@ -73,98 +89,73 @@ function createChatbotUI() {
73
89
  <img src="https://landing-static.s3.eu-central-1.amazonaws.com/images/logo.svg" alt="Wineater Logo" id="chatbot-logo">
74
90
  </a>
75
91
  </div>
76
- </div>
77
- </div>
78
- `;
92
+ </div>
93
+ `;
94
+ document.body.insertAdjacentHTML('beforeend', chatbotHTML);
95
+ }
79
96
 
80
- document.body.insertAdjacentHTML('beforeend', chatbotHTML);
81
- }
97
+ setupChatListeners() {
98
+ const closeButton = document.getElementById('close-btn');
99
+ closeButton.addEventListener('click', toggleChatWindow);
100
+
101
+ window.addEventListener('click', event => {
102
+ const chatWindow = document.getElementById('chat-window');
103
+ const chatIcon = document.getElementById('chat-icon');
104
+ if (!chatWindow.contains(event.target) && !chatIcon.contains(event.target)) {
105
+ chatWindow.classList.remove('visible');
106
+ chatIcon.style.display = 'flex';
107
+ }
108
+ });
109
+ }
82
110
 
83
- function setupCloseButton() {
84
- const closeButton = document.getElementById('close-btn');
85
- closeButton.addEventListener('click', toggleChatWindow);
86
- }
111
+ autoOpenChatIfNeeded() {
112
+ const disableAutoOpen = getCookie('disableAutoOpen');
113
+ if (!disableAutoOpen) {
114
+ shouldOpenChatAutomatically();
115
+ }
116
+ }
87
117
 
88
- function setupOutsideClick() {
89
- window.addEventListener('click', function(event) {
90
- const chatWindow = document.getElementById('chat-window');
118
+ setupChatButtonListener() {
91
119
  const chatIcon = document.getElementById('chat-icon');
92
- if (!chatWindow.contains(event.target) && !chatIcon.contains(event.target)) {
93
- chatWindow.classList.remove('visible');
94
- chatIcon.style.display = 'flex'; // Show the chat icon/button
120
+ const chatWindow = document.getElementById('chat-window');
121
+
122
+ if (!chatIcon || !chatWindow) {
123
+ console.error('Chat icon or chat window element not found!');
124
+ return;
95
125
  }
96
- });
97
- }
98
126
 
99
- // Function to toggle the chat icon position
100
- function toggleChatIconPosition(position) {
101
- console.log(position);
102
- const chatIcon = document.getElementById('chat-icon');
103
- const chatWindow = document.getElementById('chat-window');
104
-
105
- chatIcon.className = ''; // Reset classes
106
- chatWindow.className = ''; // Reset classes
107
-
108
- if (position === 'right-center') {
109
- chatIcon.classList.add('chat-icon-right-center');
110
- chatWindow.classList.add('right-center-aligned');
111
- } else {
112
- // Apply bottom-right or other default classes as needed
113
- chatIcon.classList.add('chat-icon-bottom-right');
127
+ chatIcon.addEventListener('click', () => {
128
+ const isVisible = chatWindow.classList.contains('visible');
129
+ if (isVisible) {
130
+ chatWindow.classList.remove('visible');
131
+ chatIcon.style.display = 'flex';
132
+ } else {
133
+ chatWindow.classList.add('visible');
134
+ chatIcon.style.display = 'none';
135
+ }
136
+ });
114
137
  }
138
+
139
+ async initialize() {
140
+ this.tracker.start();
141
+ await this.initFlagsmith();
142
+ await this.initTranslator();
143
+ this.initCookies();
144
+ await this.initializeChatbotOrWidget();
145
+ this.autoOpenChatIfNeeded();
146
+ }
115
147
  }
116
148
 
117
- function openChatAfterDelay(delay = 10000) { // delay is in milliseconds
118
- setTimeout(() => {
119
- openChatWindow(window.location.href); // Ensure openChatWindow is available globally
120
- }, delay);
149
+ function applyPositionToChat(position = 'right-center') {
150
+ const chatIcon = document.getElementById('chat-icon');
151
+ if (!chatIcon) return;
152
+
153
+ // Применение классов для позиции
154
+ chatIcon.className = `chat-icon-${position}`;
121
155
  }
122
156
 
157
+ // Initialize the application on DOM ready
123
158
  document.addEventListener('DOMContentLoaded', () => {
124
- // Check if auto-opening is disabled by cookie
125
- const disableAutoOpen = getCookie('disableAutoOpen');
126
-
127
- if (!disableAutoOpen) {
128
- shouldOpenChatAutomatically()
129
- }
130
- });
131
-
132
- // If you want to initialize your chatbot automatically when the script is loaded
133
- if (typeof window !== 'undefined') {
134
- let position = window?.wineaterData?.POSITION || 'right-center';
135
- window.addEventListener('DOMContentLoaded', async () => {
136
- const stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi'];
137
- const store = stores.find(value => window.location.href.includes(value)) || null;
138
- let capitalizeStore;
139
- if (store) {
140
- capitalizeStore = store.charAt(0).toUpperCase() + store.slice(1);
141
- if (capitalizeStore === 'Climats') {
142
- position = 'right-center';
143
- }
144
- }
145
- await translator.fetchConfig(capitalizeStore || 'Climats');
146
- setCookie('chatbotToken', window.wineaterData?.CLIENT_TOKEN || DEMO_TOKEN, 365);
147
- setUniqueUserCookie();
148
- flagsmith.init({
149
- environmentID: '5RfiDoiqb4dHrNdQvzbkfM',
150
- // api:"http://localhost:8000/api/v1/" set this if you are self hosting, and point it to your API
151
- cacheFlags: false, // stores flags in localStorage cache
152
- enableAnalytics: true,
153
- identity: getCookie('uniqueUserID') // See https://docs.flagsmith.com/flag-analytics/ for more info.
154
- }).then(() => {
155
- createChatbotUI(); // Create the UI
156
- setupCloseButton();
157
- setupOutsideClick();
158
- toggleChatIconPosition(position);
159
- const myChatbot = new Chatbot();
160
- myChatbot.initialize();
161
- }).catch(() => {
162
- createChatbotUI(); // Create the UI
163
- setupCloseButton();
164
- setupOutsideClick();
165
- toggleChatIconPosition(position);
166
- const myChatbot = new Chatbot();
167
- myChatbot.initialize();
168
- });
169
- });
170
- }
159
+ const app = new App();
160
+ app.initialize();
161
+ });
package/src/js/api.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // api.js
2
2
 
3
- const stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi'];
3
+ const stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi', 'ampely'];
4
4
  const DEMO_TOKEN='bMTFzLbWcXFgXK8SzyFHA6kIjelFcz5VQABVPbXdXh5XZJCDQH9BcVlrv3DF3kA';
5
5
 
6
6
  export class Api {
@@ -83,4 +83,29 @@ export class Api {
83
83
  throw error;
84
84
  }
85
85
  }
86
+ async getInstantRecommendations() {
87
+ console.log('Fetching instant recommendations...');
88
+ try {
89
+ const response = await fetch(`${this.baseURL}dish/recommendations/instant`, {
90
+ method: 'POST',
91
+ headers: {
92
+ 'Content-Type': 'application/json',
93
+ 'Authorization': `Bearer ${this.token}`
94
+ },
95
+ body: JSON.stringify({ store: this.store })
96
+ });
97
+
98
+ const data = await response.json();
99
+
100
+ if (!response.ok) {
101
+ throw new Error(`API call failed with status ${response.status}: ${data.message || 'No additional error information'}`);
102
+ }
103
+
104
+ console.log('Instant recommendations:', data);
105
+ return data;
106
+ } catch (error) {
107
+ console.error('Fetching instant recommendations failed:', error.message);
108
+ throw new Error(`Error in getInstantRecommendations: ${error.message}`);
109
+ }
110
+ }
86
111
  }
package/src/js/i18n.js CHANGED
@@ -24,7 +24,20 @@ class Translator {
24
24
  moreInfo: "Plus d'infos",
25
25
  winePairingIntro: "Pour ce vin, voici quelques suggestions de plats :",
26
26
  askForDinner: "Que voulez-vous manger ce soir?",
27
- clearChatButton: "Effacer le chat"
27
+ clearChatButton: "Effacer le chat",
28
+ widgetTitle: "Découvrez votre vin",
29
+ widgetSubtitle: "Recherchez par vos préférences",
30
+ searchPlaceholder: "Entrez un mot-clé ou une description",
31
+ searchButton: "Rechercher",
32
+ priceRange: "Gamme de prix",
33
+ wineColor: "Couleur du vin",
34
+ intensity: "Intensité",
35
+ red: "Rouge",
36
+ white: "Blanc",
37
+ rose: "Rosé",
38
+ light: "Léger",
39
+ medium: "Moyen",
40
+ full: "Puissant"
28
41
  },
29
42
  es: {
30
43
  welcomeMessage: "¿Qué vas a comer? Cuéntame tu plato y te recomendaré el maridaje perfecto.",
@@ -45,7 +58,20 @@ class Translator {
45
58
  moreInfo: "Más info",
46
59
  winePairingIntro: "Para este vino, aquí tienes algunas sugerencias de platos:",
47
60
  askForDinner: "¿Qué te gustaría cenar?",
48
- clearChatButton: "Limpiar el chat"
61
+ clearChatButton: "Limpiar el chat",
62
+ widgetTitle: "Encuentra tu vino",
63
+ widgetSubtitle: "Busca según tus preferencias",
64
+ searchPlaceholder: "Escribe una palabra clave o descripción",
65
+ searchButton: "Buscar",
66
+ priceRange: "Rango de precios",
67
+ wineColor: "Color del vino",
68
+ intensity: "Intensidad",
69
+ red: "Tinto",
70
+ white: "Blanco",
71
+ rose: "Rosado",
72
+ light: "Ligero",
73
+ medium: "Medio",
74
+ full: "Intenso"
49
75
  },
50
76
  en: {
51
77
  welcomeMessage: "What are you planning to eat? Share your dish and I'll recommend the perfect wine pairing for your meal.",
@@ -66,7 +92,20 @@ class Translator {
66
92
  moreInfo: "More info",
67
93
  winePairingIntro: "For this wine, here are some suggested dishes:",
68
94
  askForDinner: "What would you like to have for dinner?",
69
- clearChatButton: "Clear Chat"
95
+ clearChatButton: "Clear Chat",
96
+ widgetTitle: "Discover Your Wine",
97
+ widgetSubtitle: "Search by your preferences",
98
+ searchPlaceholder: "Enter a keyword or description",
99
+ searchButton: "Search",
100
+ priceRange: "Price Range",
101
+ wineColor: "Wine Color",
102
+ intensity: "Intensity",
103
+ red: "Red",
104
+ white: "White",
105
+ rose: "Rosé",
106
+ light: "Light",
107
+ medium: "Medium",
108
+ full: "Full"
70
109
  },
71
110
  de: {
72
111
  welcomeMessage: "Was möchten Sie essen? Beschreiben Sie Ihr Gericht und ich empfehle Ihnen den perfekten Wein dazu.",
@@ -87,7 +126,20 @@ class Translator {
87
126
  moreInfo: "Mehr Info",
88
127
  winePairingIntro: "Für diesen Wein gibt es folgende Essensvorschläge:",
89
128
  askForDinner: "Was möchten Sie zum Abendessen essen?",
90
- clearChatButton: "Chat löschen"
129
+ clearChatButton: "Chat löschen",
130
+ widgetTitle: "Finden Sie Ihren Wein",
131
+ widgetSubtitle: "Suchen Sie nach Ihren Vorlieben",
132
+ searchPlaceholder: "Geben Sie ein Stichwort oder eine Beschreibung ein",
133
+ searchButton: "Suche",
134
+ priceRange: "Preisspanne",
135
+ wineColor: "Weinfarbe",
136
+ intensity: "Intensität",
137
+ red: "Rot",
138
+ white: "Weiß",
139
+ rose: "Rosé",
140
+ light: "Leicht",
141
+ medium: "Mittel",
142
+ full: "Voll"
91
143
  }
92
144
  };
93
145
  }