wineater-bot 3.2.1 → 3.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wineater-bot",
3
- "version": "3.2.1",
3
+ "version": "3.3.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
package/src/index.js CHANGED
@@ -1,39 +1,14 @@
1
- import './js/styles.js';
2
1
  import { setCookie, setUniqueUserCookie, getCookie } from './js/analytics.js';
3
2
  import flagsmith from 'flagsmith';
4
3
  import Tracker from '@openreplay/tracker';
5
4
  import { WineWidget } from './js/widget.js';
6
- import { Chatbot } from './js/chatbot.js';
7
5
  import translator from './js/i18n.js';
8
- import { shouldOpenChatAutomatically } from './js/auto-open.js';
9
- import { toggleChatWindow, closeChatWindow, openChatWindow } from './js/ui.js';
10
6
 
11
7
  const DEMO_TOKEN = 'HeUw6IXuhvz6tRuXdPEGEbj3SGQ3Q2YtEc1Z8jd41Kg9LtyPb4Epu0to31SYIadG';
12
8
 
13
9
  class App {
14
10
  constructor() {
15
- this.stores = ['climats', 'telckel', 'biobio', 'weinpoint', 'vinigrandi', 'ampely', 'test'];
16
11
  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
- }
25
-
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
12
  }
38
13
 
39
14
  async initTranslator() {
@@ -46,84 +21,15 @@ class App {
46
21
  setUniqueUserCookie();
47
22
  }
48
23
 
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
- }
61
-
62
- createChatbotUI() {
63
- const chatbotHTML = ``;
64
- document.body.insertAdjacentHTML('beforeend', chatbotHTML);
65
- }
66
-
67
- setupChatListeners() {
68
- const closeButton = document.getElementById('close-btn');
69
- closeButton.addEventListener('click', toggleChatWindow);
70
-
71
- window.addEventListener('click', event => {
72
- const chatWindow = document.getElementById('chat-window');
73
- const chatIcon = document.getElementById('chat-icon');
74
- if (!chatWindow.contains(event.target) && !chatIcon.contains(event.target)) {
75
- chatWindow.classList.remove('visible');
76
- chatIcon.style.display = 'flex';
77
- }
78
- });
79
- }
80
-
81
- autoOpenChatIfNeeded() {
82
- const disableAutoOpen = getCookie('disableAutoOpen');
83
- if (!disableAutoOpen) {
84
- shouldOpenChatAutomatically();
85
- }
86
- }
87
-
88
- setupChatButtonListener() {
89
- const chatIcon = document.getElementById('chat-icon');
90
- const chatWindow = document.getElementById('chat-window');
91
-
92
- if (!chatIcon || !chatWindow) {
93
- console.error('Chat icon or chat window element not found!');
94
- return;
95
- }
96
-
97
- chatIcon.addEventListener('click', () => {
98
- const isVisible = chatWindow.classList.contains('visible');
99
- if (isVisible) {
100
- chatWindow.classList.remove('visible');
101
- chatIcon.style.display = 'flex';
102
- } else {
103
- chatWindow.classList.add('visible');
104
- chatIcon.style.display = 'none';
105
- }
106
- });
107
- }
108
24
 
109
25
  async initialize() {
110
26
  this.tracker.start();
111
- await this.initFlagsmith();
112
27
  await this.initTranslator();
113
28
  this.initCookies();
114
- await this.initializeChatbotOrWidget();
115
- this.autoOpenChatIfNeeded();
29
+ new WineWidget();
116
30
  }
117
31
  }
118
32
 
119
- function applyPositionToChat(position = 'right-center') {
120
- const chatIcon = document.getElementById('chat-icon');
121
- if (!chatIcon) return;
122
-
123
- // Применение классов для позиции
124
- chatIcon.className = `chat-icon-${position}`;
125
- }
126
-
127
33
  // Initialize the application on DOM ready
128
34
  document.addEventListener('DOMContentLoaded', () => {
129
35
  const app = new App();
package/src/js/i18n.js CHANGED
@@ -4,6 +4,18 @@ class Translator {
4
4
  constructor() {
5
5
  this.api = new Api();
6
6
  this.language = 'en'; // Default to English
7
+ this.currency = 'USD';
8
+ this.currencies = {
9
+ 'USD': {
10
+ label: '$'
11
+ },
12
+ 'EUR': {
13
+ label: '€'
14
+ },
15
+ 'MXN': {
16
+ label: '$'
17
+ }
18
+ }
7
19
  this.translations = {
8
20
  fr: {
9
21
  lang: 'fr',
@@ -400,9 +412,26 @@ class Translator {
400
412
  try {
401
413
  const config = await this.api.getStoreConfig(storeName);
402
414
  this.language = config.lang;
415
+ this.currency = config.currency;
403
416
  } catch (e) {
404
417
  this.language = 'en'; // Fallback to English
418
+ this.currency = 'USD';
419
+ }
420
+ }
421
+
422
+ getCurrency(key) {
423
+ const keys = key.split('.'); // Разбиваем ключ на части
424
+ let value = this.currencies[this.currency];
425
+
426
+ for (const k of keys) {
427
+ if (value && typeof value === 'object' && k in value) {
428
+ value = value[k]; // Переходим к следующему уровню
429
+ } else {
430
+ return this.currency; // Если ключ не найден, возвращаем сам ключ
431
+ }
405
432
  }
433
+
434
+ return value;
406
435
  }
407
436
 
408
437
  translate(key) {
@@ -313,7 +313,7 @@ flex: 0 0 auto;
313
313
 
314
314
  /* Заголовок вина */
315
315
  #wine-widget-container .wine-title {
316
- font-size: 18px; /* крупнее */
316
+ font-size: 15px; /* крупнее */
317
317
  font-weight: 500;
318
318
  margin: 0 0 8px;
319
319
  min-height: 3rem;
@@ -489,6 +489,58 @@ margin-top: auto; /* прижимает .bottom-row к низу
489
489
  animation: spin 1s linear infinite;
490
490
  }
491
491
 
492
+ .typing-indicator {
493
+ display: flex;
494
+ justify-content: center;
495
+ align-items: center;
496
+ height: 0;
497
+ visibility: hidden;
498
+ background-color: white;
499
+ }
500
+
501
+ #loading-indicator .typing-indicator {
502
+ visibility: visible;
503
+ }
504
+
505
+ .typing-indicator span {
506
+ display: block;
507
+ width: 8px;
508
+ height: 8px;
509
+ margin: 0 3px;
510
+ border-radius: 50%;
511
+ background: linear-gradient(90deg, var(--wineater-color), var(--wineater-corp-color));
512
+ opacity: 0.7;
513
+ animation: typing 1s infinite;
514
+ }
515
+
516
+ @keyframes typing {
517
+ 0%, 100% {
518
+ transform: translateY(0);
519
+ opacity: 0.7;
520
+ }
521
+ 50% {
522
+ transform: translateY(-8px);
523
+ opacity: 1;
524
+ }
525
+ }
526
+
527
+ /* Staggered animation for typing dots */
528
+ .typing-indicator span:nth-child(1) {
529
+ animation-delay: 0s;
530
+ }
531
+ .typing-indicator span:nth-child(2) {
532
+ animation-delay: 0.15s;
533
+ }
534
+ .typing-indicator span:nth-child(3) {
535
+ animation-delay: 0.3s;
536
+ }
537
+
538
+ /* Show the typing indicator */
539
+ .typing-indicator.visible {
540
+ visibility: visible;
541
+ height: 40px;
542
+ }
543
+
492
544
  /* ===================== 11) keyframes анимации ===================== */
493
545
  @keyframes spin {
494
546
  from { transform: rotate(0deg); }
@@ -628,6 +680,134 @@ margin-top: auto; /* прижимает .bottom-row к низу
628
680
  }
629
681
  }
630
682
 
683
+ .card-popup {
684
+ position: absolute;
685
+ top: 0;
686
+ left: 0;
687
+ z-index: 10;
688
+ width: 100%;
689
+ background-color: white;
690
+ padding: 16px;
691
+ border-radius: 16px;
692
+ box-shadow: 0 6px 30px rgba(0,0,0,0.2);
693
+ text-align: left;
694
+ font-size: 14px;
695
+ box-sizing: border-box;
696
+ display: flex;
697
+ flex-direction: column;
698
+ }
699
+
700
+ .card-popup p {
701
+ margin: 5px 0;
702
+ }
703
+
704
+ .card-popup.hidden {
705
+ display: none;
706
+ }
707
+
708
+ .card-popup-header {
709
+ display: flex;
710
+ justify-content: space-between;
711
+ align-items: flex-start;
712
+ gap: 12px;
713
+ }
714
+
715
+ .card-popup-header h2 {
716
+ font-size: 16px;
717
+ font-weight: 600;
718
+ margin: 0;
719
+ flex: 1;
720
+ line-height: 1.3;
721
+ }
722
+
723
+ .card-popup-close {
724
+ font-size: 20px;
725
+ font-weight: bold;
726
+ cursor: pointer;
727
+ color: #999;
728
+ border: none;
729
+ background: transparent;
730
+ line-height: 1;
731
+ }
732
+ .card-popup-close:hover {
733
+ color: #000;
734
+ }
735
+
736
+ .global-card-popup {
737
+ position: fixed;
738
+ top: 0;
739
+ left: 0;
740
+ right: 0;
741
+ bottom: 0;
742
+ z-index: 10000;
743
+ padding: 24px 16px;
744
+ background-color: #fff;
745
+ overflow-y: auto;
746
+ border-radius: 0;
747
+ font-size: 14px;
748
+ box-shadow: 0 6px 20px rgba(0,0,0,0.2);
749
+ display: flex;
750
+ flex-direction: column;
751
+ gap: 12px;
752
+ max-width: 100vw;
753
+ max-height: 100vh;
754
+ }
755
+
756
+ .global-card-popup .card-popup-header {
757
+ display: flex;
758
+ justify-content: space-between;
759
+ align-items: flex-start;
760
+ }
761
+
762
+ .global-card-popup .card-popup-close {
763
+ font-size: 24px;
764
+ font-weight: bold;
765
+ cursor: pointer;
766
+ background: transparent;
767
+ border: none;
768
+ }
769
+
770
+ .mobile-fullscreen-popup {
771
+ font-family: 'Bricolage Grotesque', sans-serif;
772
+ position: fixed;
773
+ width: calc(100% - 20px);
774
+ top: 50px;
775
+ left: 10px;
776
+ z-index: 10000;
777
+ background-color: #fff;
778
+ padding: 24px;
779
+ overflow-y: auto;
780
+ border-radius: 0;
781
+ border-radius: 16px;
782
+ font-size: 14px;
783
+ display: flex;
784
+ flex-direction: column;
785
+ gap: 12px;
786
+ }
787
+ .mobile-fullscreen-popup .card-popup-header {
788
+ display: flex;
789
+ justify-content: space-between;
790
+ align-items: flex-start;
791
+ }
792
+ .mobile-fullscreen-overlay {
793
+ position: absolute;
794
+ top: 0;
795
+ left: 0;
796
+ right: 0;
797
+ bottom: 0;
798
+ background: #fff;
799
+ opacity: 0.96;
800
+ z-index: 0;
801
+ }
802
+ .mobile-fullscreen-popup .card-popup-close {
803
+ font-size: 24px;
804
+ font-weight: bold;
805
+ cursor: pointer;
806
+ background: transparent;
807
+ border: none;
808
+ }
809
+
810
+
631
811
  /* Пример более узких экранов (i.e. <480px) можно добавить при необходимости */
632
812
  `;
633
813
  const fontLink = document.createElement('link');