PageSourceSearch

https://smtc.ac.ir/assets/js/bluetailapp/welcome.js

js smtc.ac.ir collected 2026-10-06 07:39:13 UTC 20,485 bytes, 552 lines download raw bytes

1/**
2 * Welcome Screen Manager for NiafamChat
3 * مدیریت صفحه خوشامدگویی و انتخاب نوع گفتگو
4 */
5
6/**
7 * NiafamChat Welcome Screen System
8 * ===============================
9 * 
10 * RECENT CHANGES (Project Restructure):
11 * - Moved from root to client/js/ directory for better organization
12 * - Updated all file paths and references for new structure
13 * - Maintained integration with FAQ and user-info systems
14 * 
15 * FEATURES:
16 * - Progressive user journey management
17 * - Interactive welcome options with statistics
18 * - Smart navigation based on user history
19 * - Integration with FAQ, user-info, and main chat
20 * - Persian RTL design with animations
21 * 
22 * Author: NiafamChat Development Team
23 * Last Updated: Project restructure for better organization
24 */
25class WelcomeScreen {
26    constructor() {
27        this.isVisible = false;
28        this.animationDuration = 300;
29        
30        this.init();
31    }
32
33    init() {
34        this.bindEvents();
35        console.log('🎉 Welcome Screen initialized');
36    }
37
38    /**
39     * نمایش صفحه خوشامدگویی
40     */
41    show() {
42        if (this.isVisible) return;
43
44        // ایجاد محتوای welcome screen
45        this.createWelcomeContent();
46        
47        // مخفی کردن بخش‌های چت
48        this.hideChatElements();
49        
50        // نمایش welcome screen
51        this.showWelcomeElements();
52        
53        this.isVisible = true;
54        
55        console.log('📱 Welcome screen shown');
56    }
57
58    /**
59     * مخفی کردن صفحه خوشامدگویی و نمایش چت
60     */
61    hide() {
62        if (!this.isVisible) return;
63
64        const welcomeContainer = document.getElementById('welcomeContainer');
65        if (welcomeContainer) {
66            welcomeContainer.style.opacity = '0';
67            welcomeContainer.style.transform = 'translateY(20px)';
68            
69            setTimeout(() => {
70                welcomeContainer.remove();
71                this.showChatElements();
72                this.isVisible = false;
73                console.log('💬 Switched to chat mode');
74            }, this.animationDuration);
75        }
76    }
77
78    /**
79     * ایجاد محتوای صفحه خوشامدگویی
80     */
81    createWelcomeContent() {
82        const chatContainer = document.getElementById('chatContainer');
83        
84        // Load configuration
85        const config = this.getWelcomeConfig();
86        
87        const welcomeHTML = `
88            <div id="welcomeContainer" class="welcome-screen">
89                <!-- Close Button - دکمه بستن -->
90                <button id="closeWelcome" class="welcome-close-btn" title="بستن">
91                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
92                        <line x1="18" y1="6" x2="6" y2="18"></line>
93                        <line x1="6" y1="6" x2="18" y2="18"></line>
94                    </svg>
95                </button>
96                
97                <!-- Welcome Header -->
98                <div class="welcome-header">
99                    <div class="welcome-logo">
100                        <i data-lucide="${config.header.icon}"></i>
101                    </div>
102                    <h1 class="welcome-title">${config.header.title}</h1>
103                    <p class="welcome-subtitle">${config.header.subtitle}</p>
104                </div>
105
106                <!-- Welcome Content -->
107                <div class="welcome-content">
108                    <div class="welcome-options">
109                        ${this.generateOptions(config.options)}
110                    </div>
111                </div>
112
113                <!-- Welcome Footer -->
114                <div class="welcome-footer">
115                    <div class="welcome-links">
116                        ${this.generateFooterLinks(config.footer.links)}
117                    </div>
118                </div>
119            </div>
120        `;
121
122        chatContainer.insertAdjacentHTML('afterbegin', welcomeHTML);
123        
124        // Initialize icons for the new content
125        if (window.initializeLucideIcons) {
126            window.initializeLucideIcons();
127        }
128        
129        // Bind close button event
130        const closeBtn = document.getElementById('closeWelcome');
131        if (closeBtn) {
132            closeBtn.addEventListener('click', () => {
133                this.closeChat();
134            });
135        }
136        
137        // Animate in
138        setTimeout(() => {
139            const welcomeContainer = document.getElementById('welcomeContainer');
140            if (welcomeContainer) {
141                welcomeContainer.style.opacity = '1';
142                welcomeContainer.style.transform = 'translateY(0)';
143            }
144        }, 50);
145    }
146    
147    /**
148     * بستن چت و برگشت به حالت اولیه
149     * پیش از مخفی کردن UI، هر سشنی که در بک‌اند برای کاربر باز است بسته می‌شود
150     * و state کلاینت (userData، messages، localStorage) کاملاً پاک می‌شود.
151     *
152     * اگر گفتگوی آنلاین فعال باشد، کارت تأیید درون پنل چت نمایش داده می‌شود
153     * (به جای popup مرورگر) و بستن واقعی پس از تأیید کاربر اتفاق می‌افتد.
154     */
155    closeChat() {
156        // modal تأیید را روی محفظه‌ی فعلی (welcome / user-info / chat) نمایش بده
157        try {
158            if (window.niafamChat &&
159                typeof window.niafamChat.hasActiveLiveSession === 'function' &&
160                window.niafamChat.hasActiveLiveSession() &&
161                typeof window.niafamChat.showCloseConfirmationInChat === 'function') {
162                window.niafamChat.showCloseConfirmationInChat(() => this._performCloseChat());
163                return;
164            }
165        } catch (e) {
166            // ignore — به مسیر معمولی برو
167        }
168
169        this._performCloseChat();
170    }
171
172    _performCloseChat() {
173        // بستن همه‌ی سشن‌های باز در بک‌اند + پاک‌سازی کامل state کلاینت
174        try {
175            if (window.niafamChat && typeof window.niafamChat.closeAllBackendSessions === 'function') {
176                window.niafamChat.closeAllBackendSessions();
177            }
178        } catch (e) {
179            // ignore
180        }
181
182        const chatContainer = document.getElementById('chatContainer');
183        const chatToggle = document.getElementById('chatToggle');
184        const speechBubble = document.getElementById('chatSpeechBubble');
185
186        // Remove active class from chat container
187        if (chatContainer) {
188            chatContainer.classList.remove('active');
189        }
190
191        // Show chat toggle button
192        if (chatToggle) {
193            chatToggle.style.display = 'flex';
194        }
195
196        // Show speech bubble
197        if (speechBubble) {
198            speechBubble.style.display = '';
199        }
200
201        // Restore body scroll for mobile
202        document.body.style.overflow = '';
203        document.body.style.position = '';
204        document.body.style.width = '';
205
206        console.log('🚪 Chat closed from welcome screen');
207    }
208
209    /**
210     * دریافت تنظیمات Welcome Screen از config
211     */
212    getWelcomeConfig() {
213        const defaultConfig = {
214            header: {
215                title: "نیافام چت",
216                subtitle: "دستیار هوشمند شما برای پاسخگویی سریع و دقیق",
217                icon: "bot"
218            },
219            options: {
220                smartChat: {
221                    enabled: true,
222                    title: "چت هوشمند",
223                    description: "گفتگو با دستیار هوش مصنوعی",
224                    icon: "bot"
225                },
226                faq: {
227                    enabled: true,
228                    title: "دانشنامه",
229                    description: "مشاهده پاسخ سریع به سوالات رایج و پرتکرار",
230                    icon: "help-circle"
231                }
232            },
233            footer: {
234                links: [
235                    { text: "حریم خصوصی", url: "#privacy" },
236                    { text: "شرایط استفاده", url: "#terms" },
237                    { text: "پشتیبانی", url: "#support" }
238                ]
239            },
240            chatGreeting: {
241                withName: "سلام {name} عزیز!  من دستیار هوشمند {botName} هستم. چطور می‌تونم کمکتون کنم؟",
242                withoutName: "سلام! من دستیار هوشمند {botName} هستم. چطور می‌تونم کمکتون کنم؟ 😊"
243            }
244        };
245
246        // Try to get from loaded config
247        if (window.LOADED_CONFIG && window.LOADED_CONFIG.welcomeScreen) {
248            return { ...defaultConfig, ...window.LOADED_CONFIG.welcomeScreen };
249        }
250
251        return defaultConfig;
252    }
253
254    /**
255     * تولید HTML گزینه‌ها
256     */
257    generateOptions(options) {
258        let html = '';
259
260        // گفتگوی آنلاین (Live Chat)
261        if (options.liveChat && options.liveChat.enabled) {
262            html += `
263                <div class="option-card primary" data-option="live-chat" data-chat-mode="${options.liveChat.chatMode || 'live'}">
264                    <div class="option-header">
265                        <div class="option-icon">
266                            <i data-lucide="${options.liveChat.icon}"></i>
267                        </div>
268                        <div class="option-info">
269                            <h3 class="option-title">${options.liveChat.title}</h3>
270                            <p class="option-description">${options.liveChat.description}</p>
271                        </div>
272                        <div class="option-arrow">←</div>
273                    </div>
274                </div>
275            `;
276        }
277
278        // گپ هوشمند (AI Assistant)
279        if (options.aiAssistant && options.aiAssistant.enabled) {
280            html += `
281                <div class="option-card" data-option="ai-assistant" data-chat-mode="${options.aiAssistant.chatMode || 'ai'}">
282                    <div class="option-header">
283                        <div class="option-icon">
284                            <i data-lucide="${options.aiAssistant.icon}"></i>
285                        </div>
286                        <div class="option-info">
287                            <h3 class="option-title">${options.aiAssistant.title}</h3>
288                            <p class="option-description">${options.aiAssistant.description}</p>
289                        </div>
290                        <div class="option-arrow">←</div>
291                    </div>
292                </div>
293            `;
294        }
295
296        // دانشنامه (FAQ)
297        if (options.faq && options.faq.enabled) {
298            html += `
299                <div class="option-card" data-option="faq">
300                    <div class="option-header">
301                        <div class="option-icon">
302                            <i data-lucide="${options.faq.icon}"></i>
303                        </div>
304                        <div class="option-info">
305                            <h3 class="option-title">${options.faq.title}</h3>
306                            <p class="option-description">${options.faq.description}</p>
307                        </div>
308                        <div class="option-arrow">←</div>
309                    </div>
310                </div>
311            `;
312        }
313
314        return html;
315    }
316
317    /**
318     * تولید HTML لینک‌های Footer
319     */
320    generateFooterLinks(links) {
321        if (!links || !Array.isArray(links)) return '';
322        
323        return links
324            .map(link => `<a href="${link.url}" class="welcome-link">${link.text}</a>`)
325            .join('\n');
326    }
327
328    /**
329     * مخفی کردن عناصر چت
330     */
331    hideChatElements() {
332        const elementsToHide = [
333            'searchContainer',
334            'savedMessagesPanel', 
335            'searchResultsPanel',
336            'chatMessages',
337            'typingIndicator',
338            'suggestedReplies',
339            'chat-input'
340        ];
341
342        elementsToHide.forEach(id => {
343            const element = document.getElementById(id) || document.querySelector(`.${id}`);
344            if (element) {
345                element.style.display = 'none';
346            }
347        });
348
349        // مخفی کردن header چت
350        const chatHeader = document.querySelector('.chat-header');
351        if (chatHeader) {
352            chatHeader.style.display = 'none';
353        }
354    }
355
356    /**
357     * نمایش عناصر چت
358     */
359    showChatElements() {
360        const elementsToShow = [
361            'chatMessages',
362            'typingIndicator', 
363            'suggestedReplies'
364        ];
365
366        elementsToShow.forEach(id => {
367            const element = document.getElementById(id) || document.querySelector(`.${id}`);
368            if (element) {
369                element.style.display = '';
370            }
371        });
372
373        // نمایش header چت
374        const chatHeader = document.querySelector('.chat-header');
375        if (chatHeader) {
376            chatHeader.style.display = '';
377        }
378
379        // نمایش input چت
380        const chatInput = document.querySelector('.chat-input');
381        if (chatInput) {
382            chatInput.style.display = '';
383        }
384    }
385
386    /**
387     * نمایش عناصر welcome
388     */
389    showWelcomeElements() {
390        const welcomeContainer = document.getElementById('welcomeContainer');
391        if (welcomeContainer) {
392            welcomeContainer.style.opacity = '0';
393            welcomeContainer.style.transform = 'translateY(20px)';
394            welcomeContainer.style.transition = `all ${this.animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`;
395        }
396    }
397
398    /**
399     * شروع چت (Live یا AI)
400     * @param {string} chatMode - 'live' or 'ai'
401     */
402    startChat(chatMode = 'live') {
403        console.log(`🚀 Starting chat with mode: ${chatMode}`);
404        
405        // تنظیم chatMode در chatInterface
406        if (window.niafamChat && window.niafamChat.switchChatMode) {
407            window.niafamChat.switchChatMode(chatMode);
408        }
409        
410        // بررسی تنظیمات احراز هویت
411        const config = window.LOADED_CONFIG || window.configLoader?.config || window.CHAT_BOX_CONFIG || {};
412        const clientAuth = config.clientAuthentication;
413        
414        // خواندن تنظیمات authentication و guest
415        const authenticationEnabled = clientAuth?.authentication?.enabled ?? clientAuth?.modes?.authenticationEnabled ?? false;
416        const guestEnabled = clientAuth?.guest?.enabled ?? clientAuth?.modes?.guestEnabled ?? false;
417        
418        console.log('🔐 Authentication settings:', { 
419            authenticationEnabled, 
420            guestEnabled,
421            clientAuth 
422        });
423        
424        // اگر هر دو غیرفعال باشند، مسیر ورودی وجود ندارد
425        if (authenticationEnabled === false && guestEnabled === false) {
426            console.log('⏭️ Both authentication and guest disabled - skipping user info form');
427            this.hide();
428            // ⚠️ پیام خوش‌آمدگویی در script.js نمایش داده می‌شود
429            return;
430        }
431
432        // تصمیم نمایش فرم را به userInfoForm.shouldShowForm() می‌سپاریم.
433        // این متد همهٔ شرایط را بررسی می‌کند: نیاز به انتخاب دپارتمان
434        // در Live Chat، فیلدهای قابل نمایش بر اساس کانفیگ، اطلاعات
435        // session کاربر authenticated و غیره.
436        //
437        // اگر فرم لازم باشد show() آن را نمایش می‌دهد؛ اگر نه، خودش
438        // proceedToChat() را صدا می‌زند و کاربر مستقیماً وارد چت می‌شود.
439        this.hide();
440        setTimeout(() => {
441            if (window.userInfoForm && typeof window.userInfoForm.show === 'function') {
442                window.userInfoForm.show();
443            }
444        }, this.animationDuration);
445    }
446    
447    /**
448     * شروع چت هوشمند (برای سازگاری با کد قدیمی)
449     * @deprecated استفاده از startChat() توصیه می‌شود
450     */
451    startSmartChat() {
452        this.startChat('ai');
453    }
454
455    /**
456     * دریافت پیام خوشامدگویی با جایگزینی placeholder ها
457     */
458    getWelcomeMessage() {
459        const config = this.getWelcomeConfig();
460        const userData = window.userInfoForm ? window.userInfoForm.getUserData() : {};
461        const firstName = userData.firstName;
462        
463        // Get bot name from company branding
464        const botName = window.LOADED_CONFIG?.companyBranding?.botName || 'نیافام';
465        
466        // Choose template based on whether we have user name
467        let template = firstName 
468            ? config.chatGreeting.withName 
469            : config.chatGreeting.withoutName;
470        
471        // Replace placeholders
472        template = template.replace('{name}', firstName || '');
473        template = template.replace('{botName}', botName);
474        
475        return template;
476    }
477
478    /**
479     * نمایش صفحه دانشنامه
480     */
481    showFAQ() {
482        if (window.faqManager) {
483            this.hide();
484            setTimeout(() => {
485                window.faqManager.show();
486            }, this.animationDuration);
487        } else {
488            console.warn('FAQ Manager not loaded');
489            alert('سیستم دانشنامه در حال بارگذاری است...');
490        }
491    }
492
493    /**
494     * اتصال رویدادها
495     */
496    bindEvents() {
497        // استفاده از event delegation برای کلیک روی گزینه‌ها
498        document.addEventListener('click', (e) => {
499            const optionCard = e.target.closest('.option-card');
500            if (optionCard) {
501                const option = optionCard.dataset.option;
502                const chatMode = optionCard.dataset.chatMode;
503                
504                // انیمیشن کلیک
505                optionCard.style.transform = 'translateY(-2px) scale(0.98)';
506                setTimeout(() => {
507                    optionCard.style.transform = '';
508                }, 150);
509                
510                // اجرای عمل مربوطه
511                switch (option) {
512                    case 'live-chat':
513                        this.startChat(chatMode || 'live');
514                        break;
515                    case 'ai-assistant':
516                        this.startChat(chatMode || 'ai');
517                        break;
518                    case 'faq':
519                        this.showFAQ();
520                        break;
521                }
522                
523                return;
524            }
525
526        });
527    }
528
529    /**
530     * بررسی اینکه آیا باید welcome screen نمایش داده شود
531     */
532    shouldShow() {
533        // اگر قبلاً چت استفاده شده، welcome screen نمایش داده نشود
534        const hasUsedChat = localStorage.getItem('niafam-chat-used');
535        return !hasUsedChat;
536    }
537
538    /**
539     * علامت‌گذاری اینکه چت استفاده شده
540     */
541    markChatAsUsed() {
542        localStorage.setItem('niafam-chat-used', 'true');
543    }
544}
545
546// ایجاد instance global
547window.welcomeScreen = new WelcomeScreen();
548
549// Export برای استفاده در سایر فایل‌ها
550if (typeof module !== 'undefined' && module.exports) {
551    module.exports = WelcomeScreen;
552}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.