wineater-bot 3.1.12 → 3.2.0
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 +1306 -1266
- package/dist/wineater-chatbot.umd.js +118 -91
- package/index.html +3 -3
- package/package.json +1 -1
- package/src/index.js +2 -32
- package/src/js/analytics.js +1 -1
- package/src/js/widget-styles.js +55 -8
- package/src/js/widget.js +67 -13
package/index.html
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Chatbot</title>
|
|
7
|
-
<script>window.wineaterData = {CLIENT_TOKEN: '
|
|
8
|
-
<script type="module" src="./dist/wineater-chatbot.umd.js"></script>
|
|
9
|
-
|
|
7
|
+
<script>window.wineaterData = {CLIENT_TOKEN: 'emZGQHlITdVpwvK2hLXRopFS2emvorRsHadgaKbJThiVCPRWRzD0JyZrxrtgt10a', TYPE: 'widget', WIDGET_TYPE: 'store', WIDGET_WRAPPER: 'wineater-widget-conteiner'};</script>
|
|
8
|
+
<!-- <script type="module" src="./dist/wineater-chatbot.umd.js"></script> -->
|
|
9
|
+
<script type="module" src="./src/index.js"></script>
|
|
10
10
|
</head>
|
|
11
11
|
<body style="margin: 0;">
|
|
12
12
|
<div id="wineater-widget-conteiner"></div> <!-- Контейнер для виджета -->
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -40,7 +40,7 @@ class App {
|
|
|
40
40
|
const storeName = this.store ? this.store.charAt(0).toUpperCase() + this.store.slice(1) : 'Test';
|
|
41
41
|
await translator.fetchConfig(storeName || 'Test');
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
initCookies() {
|
|
45
45
|
setCookie('chatbotToken', window.wineaterData?.CLIENT_TOKEN || DEMO_TOKEN, 365);
|
|
46
46
|
setUniqueUserCookie();
|
|
@@ -60,37 +60,7 @@ class App {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
createChatbotUI() {
|
|
63
|
-
const
|
|
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://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/chat-icon.svg" alt="Chat Icon">
|
|
69
|
-
<span>${buttonText}</span>
|
|
70
|
-
</div>
|
|
71
|
-
<div id="chat-window" class="hidden">
|
|
72
|
-
<div id="chat-header">
|
|
73
|
-
<div id="chat-title">
|
|
74
|
-
<h1>${translator.translate('chatTitle')}</h1>
|
|
75
|
-
</div>
|
|
76
|
-
<div id="close-btn">×</div>
|
|
77
|
-
</div>
|
|
78
|
-
<div id="message-container"></div>
|
|
79
|
-
<div id="typing-indicator" class="typing-indicator hidden">
|
|
80
|
-
<span></span><span></span><span></span>
|
|
81
|
-
</div>
|
|
82
|
-
<div id="input-container">
|
|
83
|
-
<input type="text" id="user-input" placeholder="${translator.translate('inputPlaceholder')}">
|
|
84
|
-
<button id="send-button">${translator.translate('sendButton')}</button>
|
|
85
|
-
</div>
|
|
86
|
-
<div id="powered-by">
|
|
87
|
-
<a href="https://wineater.com" target="_blank">
|
|
88
|
-
<span>${translator.translate('poweredBy')}</span>
|
|
89
|
-
<img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo" id="chatbot-logo">
|
|
90
|
-
</a>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
`;
|
|
63
|
+
const chatbotHTML = ``;
|
|
94
64
|
document.body.insertAdjacentHTML('beforeend', chatbotHTML);
|
|
95
65
|
}
|
|
96
66
|
|
package/src/js/analytics.js
CHANGED
|
@@ -19,7 +19,7 @@ function setCookie(name, value, days) {
|
|
|
19
19
|
expires = "; expires=" + date.toUTCString();
|
|
20
20
|
}
|
|
21
21
|
document.cookie = name + "=" + (value || "") + expires + "; path=/; secure; samesite=strict";
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
23
|
|
|
24
24
|
// Function to get a cookie by name
|
|
25
25
|
function getCookie(name) {
|
package/src/js/widget-styles.js
CHANGED
|
@@ -25,7 +25,7 @@ body {
|
|
|
25
25
|
display: flex;
|
|
26
26
|
gap: 24px;
|
|
27
27
|
font-family: 'Bricolage Grotesque', sans-serif;
|
|
28
|
-
padding:
|
|
28
|
+
padding: 12px 12px 0px;
|
|
29
29
|
border-radius: 16px;
|
|
30
30
|
background-color: #fff;
|
|
31
31
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
|
@@ -73,7 +73,7 @@ body {
|
|
|
73
73
|
#wine-widget-header h1 {
|
|
74
74
|
font-family: "Bricolage Grotesque", serif;
|
|
75
75
|
font-weight: 600;
|
|
76
|
-
font-size:
|
|
76
|
+
font-size: 24px;
|
|
77
77
|
margin: 0 auto;
|
|
78
78
|
line-height: 1.3;
|
|
79
79
|
color: #333;
|
|
@@ -124,7 +124,7 @@ body {
|
|
|
124
124
|
/* ===================== 6) Поисковая строка (input + кнопка) ===================== */
|
|
125
125
|
#wine-widget-container #wine-widget-search {
|
|
126
126
|
position: relative;
|
|
127
|
-
margin:
|
|
127
|
+
margin: 12px auto;
|
|
128
128
|
display: flex;
|
|
129
129
|
justify-content: center;
|
|
130
130
|
}
|
|
@@ -235,6 +235,7 @@ body {
|
|
|
235
235
|
opacity: 0;
|
|
236
236
|
transform: translateY(20px); /* чтобы анимация была заметна */
|
|
237
237
|
transition: opacity 0.3s ease, transform 0.3s ease;
|
|
238
|
+
position: relative;
|
|
238
239
|
}
|
|
239
240
|
#wine-widget-container .wine-recommendation-tile:last-child {
|
|
240
241
|
border-right: none;
|
|
@@ -251,17 +252,63 @@ body {
|
|
|
251
252
|
|
|
252
253
|
/* Картинка */
|
|
253
254
|
#wine-widget-container .wine-image {
|
|
254
|
-
|
|
255
|
-
max-height: 200px;
|
|
255
|
+
height: 200px;
|
|
256
256
|
object-fit: contain; /* чтобы не обрезалось, если нужно */
|
|
257
257
|
margin: 0 auto 16px; /* отступ снизу */
|
|
258
258
|
display: block;
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
.wine-hover-popup {
|
|
262
|
+
display: none;
|
|
263
|
+
position: absolute;
|
|
264
|
+
top: 0;
|
|
265
|
+
left: 0;
|
|
266
|
+
width: 100%;
|
|
267
|
+
padding: 12px;
|
|
268
|
+
background-color: #fff;
|
|
269
|
+
border: 1px solid #ddd;
|
|
270
|
+
border-radius: 8px;
|
|
271
|
+
box-shadow: 0 4px 16px rgba(0,0,0,0.1);
|
|
272
|
+
transition: transform 0.3s ease;
|
|
273
|
+
z-index: 999;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.wine-hover-popup.slide-in {
|
|
277
|
+
transform: translateY(0);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Стили содержимого внутри попапа */
|
|
281
|
+
.popup-reason {
|
|
282
|
+
font-size: 14px;
|
|
283
|
+
font-weight: 400;
|
|
284
|
+
color: #333;
|
|
285
|
+
margin-bottom: 8px;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.popup-tags {
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-wrap: wrap;
|
|
291
|
+
gap: 8px;
|
|
292
|
+
margin-top: 8px;
|
|
293
|
+
justify-content: center; /* Горизонтальное выравнивание по центру */
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Каждый чип */
|
|
297
|
+
.popup-tag {
|
|
298
|
+
display: inline-block;
|
|
299
|
+
padding: 4px 8px;
|
|
300
|
+
border-radius: 12px;
|
|
301
|
+
background-color: #F5F0FF;
|
|
302
|
+
border: 1px solid #ddd;
|
|
303
|
+
font-size: 13px;
|
|
304
|
+
color: #333;
|
|
305
|
+
text-transform: capitalize; /* Делаем каждое слово с заглавной буквы */
|
|
306
|
+
}
|
|
307
|
+
|
|
261
308
|
/* Детальный блок */
|
|
262
309
|
#wine-widget-container .tile-details {
|
|
263
310
|
/* Можно дополнительные отступы или нет */
|
|
264
|
-
display: flex;
|
|
311
|
+
display: flex;
|
|
265
312
|
flex-direction: column;
|
|
266
313
|
align-items: center;
|
|
267
314
|
/* т.к. заголовок и таблица по центру */
|
|
@@ -269,8 +316,8 @@ body {
|
|
|
269
316
|
|
|
270
317
|
/* Заголовок вина */
|
|
271
318
|
#wine-widget-container .wine-title {
|
|
272
|
-
font-size:
|
|
273
|
-
font-weight:
|
|
319
|
+
font-size: 18px; /* крупнее */
|
|
320
|
+
font-weight: 500;
|
|
274
321
|
margin: 0 0 8px;
|
|
275
322
|
min-height: 3rem;
|
|
276
323
|
line-height: 1.2;
|
package/src/js/widget.js
CHANGED
|
@@ -32,7 +32,8 @@ export class WineWidget {
|
|
|
32
32
|
|
|
33
33
|
// Инициализируем виджет
|
|
34
34
|
this.initializeWidget();
|
|
35
|
-
|
|
35
|
+
this.initializeSearchAnimation();
|
|
36
|
+
this.sendEvent('widgetInitialized', { widgetType: this.widgetType });
|
|
36
37
|
|
|
37
38
|
// Если нужна мгновенная загрузка рекомендаций только в store
|
|
38
39
|
if (this.widgetType === 'store') {
|
|
@@ -40,6 +41,11 @@ export class WineWidget {
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
sendEvent(eventType, data) {
|
|
45
|
+
// Моковая реализация отправки событий в API
|
|
46
|
+
console.log('Event sent:', eventType, data);
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
getTitle(title) {
|
|
44
50
|
return !!title ? `<h1 class="wine-widget-big-title">${title}</h1>` :`<h1 class="wine-widget-big-title">
|
|
45
51
|
${translator.translate('headerLine1')}
|
|
@@ -156,9 +162,12 @@ export class WineWidget {
|
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
addEventListenersStoreVersion() {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
165
|
+
document
|
|
166
|
+
.getElementById('wine-search-button')
|
|
167
|
+
.addEventListener('click', () => {
|
|
168
|
+
this.sendEvent('searchButtonClicked', { query: document.getElementById('wine-search-input').value });
|
|
169
|
+
this.handleSearch();
|
|
170
|
+
});
|
|
162
171
|
|
|
163
172
|
// Привязка фильтров
|
|
164
173
|
this.setupFilterButtons('price-buttons', 'price');
|
|
@@ -213,6 +222,8 @@ export class WineWidget {
|
|
|
213
222
|
// Логирование запроса
|
|
214
223
|
console.log('Searching for:', fullQuery);
|
|
215
224
|
console.log('Applied filters:', filters);
|
|
225
|
+
|
|
226
|
+
this.sendEvent('searchPerformed', { query: fullQuery, filters });
|
|
216
227
|
|
|
217
228
|
// Показать эффект исчезновения карточек и индикатор загрузки
|
|
218
229
|
this.animateCardDisappearance();
|
|
@@ -236,11 +247,32 @@ export class WineWidget {
|
|
|
236
247
|
}
|
|
237
248
|
}
|
|
238
249
|
|
|
250
|
+
enableHoverPopups() {
|
|
251
|
+
const tiles = document.querySelectorAll('.wine-recommendation-tile');
|
|
252
|
+
|
|
253
|
+
tiles.forEach(tile => {
|
|
254
|
+
const popup = tile.querySelector('.wine-hover-popup');
|
|
255
|
+
if (!popup) return;
|
|
256
|
+
|
|
257
|
+
tile.addEventListener('mouseenter', () => {
|
|
258
|
+
popup.style.display = 'block';
|
|
259
|
+
popup.classList.add('slide-in');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
tile.addEventListener('mouseleave', () => {
|
|
263
|
+
popup.classList.remove('slide-in');
|
|
264
|
+
popup.style.display = 'none';
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
239
269
|
displayResults(wines, isAnimated = false) {
|
|
240
270
|
const resultsContainer = document.getElementById('wine-placeholder');
|
|
241
271
|
this.hideLoadingIndicator();
|
|
242
272
|
resultsContainer.innerHTML = '';
|
|
243
273
|
|
|
274
|
+
this.sendEvent('resultsDisplayed', { resultsCount: wines.length });
|
|
275
|
+
|
|
244
276
|
wines.forEach((wine, index) => {
|
|
245
277
|
|
|
246
278
|
|
|
@@ -262,13 +294,32 @@ export class WineWidget {
|
|
|
262
294
|
const paramList = [];
|
|
263
295
|
if (wine.type || wine.Type) paramList.push(wine.type || wine.Type);
|
|
264
296
|
if (wine.country || wine.Country) paramList.push(wine.country || wine.Country);
|
|
265
|
-
if (wine.region || wine.Region) paramList.push(wine.region || wine.Region);
|
|
266
|
-
if (wine.grape || wine.Grape) paramList.push(wine.grape || wine.Grape);
|
|
297
|
+
// if (wine.region || wine.Region) paramList.push(wine.region || wine.Region);
|
|
298
|
+
// if (wine.grape || wine.Grape) paramList.push(wine.grape || wine.Grape);
|
|
267
299
|
|
|
268
300
|
// Допустим, первые 3 идут в одну строку, а если есть 4‑й,
|
|
269
301
|
// мы выведем его на вторую строку. Или всё в одну строку — на вкус.
|
|
270
|
-
const line1 = paramList.
|
|
271
|
-
const line2 = paramList.slice(3).join(' • ');
|
|
302
|
+
const line1 = paramList.join(' • ');
|
|
303
|
+
// const line2 = paramList.slice(3).join(' • ');
|
|
304
|
+
const tags = wine.tags || wine.Tags;
|
|
305
|
+
const reasonPopupHTML = (wine.reason || tags)
|
|
306
|
+
? `
|
|
307
|
+
<div class="wine-hover-popup">
|
|
308
|
+
${wine.reason ? `<div class="popup-reason">${wine.reason}</div>` : ''}
|
|
309
|
+
${
|
|
310
|
+
tags
|
|
311
|
+
? `<div class="popup-tags">${
|
|
312
|
+
Array.isArray(tags)
|
|
313
|
+
// Для каждого тега делаем отдельный span
|
|
314
|
+
? tags.map(tag => `<span class="popup-tag">${tag}</span>`).join('')
|
|
315
|
+
: tags
|
|
316
|
+
}
|
|
317
|
+
</div>`
|
|
318
|
+
: ''
|
|
319
|
+
}
|
|
320
|
+
</div>`
|
|
321
|
+
: '';
|
|
322
|
+
|
|
272
323
|
const wineHTML = `
|
|
273
324
|
<div class="wine-recommendation-tile ${wine.isSommSelection ? 'somm-selection' : ''}">
|
|
274
325
|
${
|
|
@@ -306,11 +357,7 @@ export class WineWidget {
|
|
|
306
357
|
? `<div class="wine-params">${line1}</div>`
|
|
307
358
|
: ''
|
|
308
359
|
}
|
|
309
|
-
|
|
310
|
-
line2
|
|
311
|
-
? `<div class="wine-params">${line2}</div>`
|
|
312
|
-
: ''
|
|
313
|
-
}
|
|
360
|
+
|
|
314
361
|
|
|
315
362
|
<!-- Кнопка Buy, видна только при наведении -->
|
|
316
363
|
<div class="bottom-row">
|
|
@@ -318,6 +365,9 @@ export class WineWidget {
|
|
|
318
365
|
${translator.translate('wineDetails.buy')}
|
|
319
366
|
</a>
|
|
320
367
|
</div>
|
|
368
|
+
|
|
369
|
+
<!-- Добавляем HTML попапа -->
|
|
370
|
+
${reasonPopupHTML}
|
|
321
371
|
</div>
|
|
322
372
|
`;
|
|
323
373
|
resultsContainer.insertAdjacentHTML('beforeend', wineHTML);
|
|
@@ -331,6 +381,8 @@ export class WineWidget {
|
|
|
331
381
|
currentCard.style.transform = 'translateY(0)';
|
|
332
382
|
}, isAnimated ? index * 200 : 0); // Задержка между карточками
|
|
333
383
|
});
|
|
384
|
+
|
|
385
|
+
this.enableHoverPopups();
|
|
334
386
|
}
|
|
335
387
|
|
|
336
388
|
animateCardDisappearance() {
|
|
@@ -430,6 +482,8 @@ export class WineWidget {
|
|
|
430
482
|
const finalQuery = queryParts.join('; ');
|
|
431
483
|
|
|
432
484
|
console.log('Final query =>', finalQuery);
|
|
485
|
+
|
|
486
|
+
this.sendEvent('barSearchPerformed', { query: finalQuery, selectedDishes, notes });
|
|
433
487
|
|
|
434
488
|
try {
|
|
435
489
|
// 4) Делаете запрос к API
|