wineater-bot 3.0.10 → 3.0.11

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,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="./dist/wineater-chatbot.umd.js"></script> -->
8
- <script>window.wineaterData = {CLIENT_TOKEN: 'Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17', position: 'right-center', TYPE: 'widget', WIDGET_TYPE: 'bar'};</script>
8
+ <script>window.wineaterData = {CLIENT_TOKEN: 'Y3I8Pi1FruGjVmIBqpV24PtOLYjzdROuxWX9tCXh82zjz7uUPxV3ETvHhoeiLS17', position: 'right-center', TYPE: 'widget', WIDGET_TYPE: 'store'};</script>
9
9
  <script type="module" src="./src/index.js"></script>
10
10
  </head>
11
11
  <body style="margin: 0;">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wineater-bot",
3
- "version": "3.0.10",
3
+ "version": "3.0.11",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
package/src/js/i18n.js CHANGED
@@ -46,6 +46,11 @@ class Translator {
46
46
  barResetButton: "Réinitialiser",
47
47
  barName: "Nom du bar",
48
48
  barNotesPlaceholder: "Entrez vos souhaits ici...",
49
+ placeholderSuggestions: [
50
+ "Vin pour les pâtes",
51
+ "Parfait avec du poisson",
52
+ "Recommandé pour une soirée"
53
+ ],
49
54
  },
50
55
  es: {
51
56
  welcomeMessage: "¿Qué vas a comer? Cuéntame tu plato y te recomendaré el maridaje perfecto.",
@@ -88,6 +93,11 @@ class Translator {
88
93
  barResetButton: "Reiniciar",
89
94
  barName: "Nombre del bar",
90
95
  barNotesPlaceholder: "Agrega tus comentarios aquí...",
96
+ placeholderSuggestions: [
97
+ "Vino para pasta",
98
+ "Perfecto con pescado",
99
+ "Recomendado para una fiesta"
100
+ ],
91
101
  },
92
102
  en: {
93
103
  welcomeMessage: "What are you planning to eat? Share your dish and I'll recommend the perfect wine pairing for your meal.",
@@ -130,6 +140,11 @@ class Translator {
130
140
  barResetButton: "Reset",
131
141
  barName: "Bar Name",
132
142
  barNotesPlaceholder: "Add your wishes here...",
143
+ placeholderSuggestions: [
144
+ "Wine for pasta",
145
+ "Perfect with fish",
146
+ "Recommended for a party"
147
+ ],
133
148
  },
134
149
  de: {
135
150
  welcomeMessage: "Was möchten Sie essen? Beschreiben Sie Ihr Gericht und ich empfehle Ihnen den perfekten Wein dazu.",
@@ -17,6 +17,9 @@ const widgetStyles = `
17
17
  margin: 40px auto;
18
18
  }
19
19
 
20
+ .wine-widget-wrapper {
21
+ width: 100%;
22
+ }
20
23
  /* Левая часть */
21
24
  #wine-widget-left {
22
25
  flex: 0 0 40%;
@@ -34,6 +37,7 @@ const widgetStyles = `
34
37
  display: grid;
35
38
  grid-template-columns: repeat(2, 1fr);
36
39
  gap: 24px;
40
+ min-height: 300px;
37
41
  }
38
42
 
39
43
  /* Заголовок */
@@ -42,12 +46,14 @@ const widgetStyles = `
42
46
  font-weight: bold;
43
47
  margin: 0;
44
48
  color: #333;
49
+ text-align: center;
45
50
  }
46
51
 
47
52
  #wine-widget-header p {
48
53
  font-size: 16px;
49
54
  color: #666;
50
55
  margin-top: 8px;
56
+ text-align: center;
51
57
  }
52
58
 
53
59
  /* Поле ввода */
@@ -57,6 +63,19 @@ const widgetStyles = `
57
63
  align-items: center;
58
64
  margin: 12px 0;
59
65
  }
66
+ #wine-search-input::placeholder {
67
+ opacity: 1;
68
+ color: #7B2BEB; /* Фиолетовый цвет для текста placeholder */
69
+ font-style: normal;
70
+ transition: color 0.3s ease, opacity 0.3s ease-in-out;
71
+ }
72
+
73
+ /* При активном фокусе инпута */
74
+ #wine-search-input:focus::placeholder {
75
+ opacity: 0.5; /* Полупрозрачный эффект */
76
+ color: linear-gradient(90deg, #7B2BEB, #0044FF); /* Более светлый фиолетовый */
77
+ font-style: normal;
78
+ }
60
79
 
61
80
  #wine-search-input {
62
81
  flex: 1;
package/src/js/widget.js CHANGED
@@ -28,6 +28,7 @@ export class WineWidget {
28
28
 
29
29
  // Инициализируем виджет
30
30
  this.initializeWidget();
31
+ this.initializeSearchAnimation();
31
32
 
32
33
  // Если нужна мгновенная загрузка рекомендаций только в store
33
34
  if (this.widgetType === 'store') {
@@ -40,8 +41,8 @@ export class WineWidget {
40
41
  if (this.widgetType === 'store') {
41
42
  const widgetHTML = `
42
43
  <div id="wine-widget-container">
43
- <div id="wine-widget-left">
44
- <div id="wine-widget-header">
44
+ <div class="wine-widget-wrapper">
45
+ <div id="wine-widget-header">
45
46
  <h1>${translator.translate('widgetTitle')}</h1>
46
47
  <p>${translator.translate('widgetSubtitle')}</p>
47
48
  </div>
@@ -49,42 +50,6 @@ export class WineWidget {
49
50
  <input type="text" id="wine-search-input" placeholder="${translator.translate('searchPlaceholder')}">
50
51
  <button id="wine-search-button">${translator.translate('searchButton')}</button>
51
52
  </div>
52
- <div id="wine-widget-filters">
53
- <div class="filter-group">
54
- <span class="filter-label">${translator.translate('priceRange')}:</span>
55
- <div class="filter-buttons" id="price-buttons">
56
- <button data-value="< 500">< $500</button>
57
- <button data-value="500 - 1000">$500 - $1000</button>
58
- <button data-value="> 1000">> $1000</button>
59
- <button data-value=" " class="selected">Any</button>
60
- </div>
61
- </div>
62
- <div class="filter-group">
63
- <span class="filter-label">${translator.translate('wineColor')}:</span>
64
- <div class="filter-buttons" id="color-buttons">
65
- <button data-value="red">${translator.translate('red')}</button>
66
- <button data-value="white">${translator.translate('white')}</button>
67
- <button data-value="rose">${translator.translate('rose')}</button>
68
- <button data-value=" " class="selected">${translator.translate('Any')}</button>
69
- </div>
70
- </div>
71
- <div class="filter-group">
72
- <span class="filter-label">${translator.translate('intensity')}:</span>
73
- <div class="filter-buttons" id="intensity-buttons">
74
- <button data-value="light">${translator.translate('light')}</button>
75
- <button data-value="medium">${translator.translate('medium')}</button>
76
- <button data-value="full">${translator.translate('full')}</button>
77
- <button data-value=" " class="selected">${translator.translate('Any')}</button>
78
- </div>
79
- </div>
80
- </div>
81
- <div id="powered-by-widget">
82
- <a href="https://wineater.com" target="_blank">
83
- <span>${translator.translate('poweredBy')}</span>
84
- <img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo">
85
- </a>
86
- </div>
87
- </div>
88
53
  <div id="wine-widget-right">
89
54
  <div id="loading-indicator" class="hidden">
90
55
  <div id="typing-indicator" class="typing-indicator">
@@ -93,6 +58,13 @@ export class WineWidget {
93
58
  </div>
94
59
  <div id="wine-placeholder"></div>
95
60
  </div>
61
+ <div id="powered-by-widget">
62
+ <a href="https://wineater.com" target="_blank">
63
+ <span>${translator.translate('poweredBy')}</span>
64
+ <img src="https://czvgkhagwvmknscoerfy.supabase.co/storage/v1/object/public/static-media/logo.svg" alt="Wineater Logo">
65
+ </a>
66
+ </div>
67
+ </div>
96
68
  </div>
97
69
  `;
98
70
  widgetContainer.insertAdjacentHTML('beforeend', widgetHTML);
@@ -147,6 +119,7 @@ export class WineWidget {
147
119
  // Привязка обработчиков "плиток" и кнопки
148
120
  this.addEventListenersBarVersion();
149
121
  }
122
+ this.initializeSearchAnimation();
150
123
  }
151
124
 
152
125
  addEventListenersStoreVersion() {
@@ -408,4 +381,51 @@ export class WineWidget {
408
381
  // 6) «Отправить» и дальше на месте, не меняется
409
382
  });
410
383
  }
384
+
385
+ initializeSearchAnimation() {
386
+ const searchInput = document.getElementById('wine-search-input');
387
+ const suggestions = translator.translate('placeholderSuggestions');
388
+ let index = 0;
389
+ let charIndex = 0;
390
+ let typingForward = true;
391
+ let isInputFocused = false;
392
+
393
+ const typeEffect = () => {
394
+ if (isInputFocused) return; // Если фокус в поле ввода, эффект останавливается
395
+ if (typingForward) {
396
+ searchInput.placeholder = suggestions[index].substring(0, charIndex++);
397
+ if (charIndex > suggestions[index].length) {
398
+ typingForward = false;
399
+ setTimeout(typeEffect, 2000); // Пауза после завершения строки
400
+ } else {
401
+ setTimeout(typeEffect, 100); // Скорость ввода
402
+ }
403
+ } else {
404
+ searchInput.placeholder = suggestions[index].substring(0, charIndex--);
405
+ if (charIndex < 0) {
406
+ typingForward = true;
407
+ index = (index + 1) % suggestions.length; // Переход к следующей подсказке
408
+ setTimeout(typeEffect, 500); // Пауза перед началом следующей строки
409
+ } else {
410
+ setTimeout(typeEffect, 50); // Скорость удаления
411
+ }
412
+ }
413
+ };
414
+
415
+ typeEffect();
416
+
417
+ // Очистка строки и остановка эффекта при фокусе
418
+ searchInput.addEventListener('focus', () => {
419
+ searchInput.placeholder = '';
420
+ isInputFocused = true; // Останавливаем эффект
421
+ });
422
+
423
+ // Возобновление эффекта при потере фокуса
424
+ searchInput.addEventListener('blur', () => {
425
+ isInputFocused = false; // Возобновляем эффект
426
+ charIndex = 0;
427
+ typingForward = true;
428
+ typeEffect();
429
+ });
430
+ }
411
431
  }