diff --git a/eveai_chat_client/__init__.py b/eveai_chat_client/__init__.py index 8a818e0..3eab354 100644 --- a/eveai_chat_client/__init__.py +++ b/eveai_chat_client/__init__.py @@ -76,11 +76,13 @@ def create_app(config_file=None): app.logger.info(f"EveAI Chat Client Started Successfully (PID: {os.getpid()})") app.logger.info("-------------------------------------------------------------------------------------------------") - # @app.before_request - # def app_before_request(): - # app.logger.debug(f'App before request: {request.path} ===== Method: {request.method} =====') - # app.logger.debug(f'Full URL: {request.url}') - # app.logger.debug(f'Endpoint: {request.endpoint}') + @app.before_request + def app_before_request(): + if request.path.startswith('/healthz'): + pass + app.logger.debug(f'App before request: {request.path} ===== Method: {request.method} =====') + app.logger.debug(f'Full URL: {request.url}') + app.logger.debug(f'Endpoint: {request.endpoint}') return app diff --git a/eveai_chat_client/static/assets/js/ChatApp.js b/eveai_chat_client/static/assets/js/ChatApp.js deleted file mode 100644 index 42912af..0000000 --- a/eveai_chat_client/static/assets/js/ChatApp.js +++ /dev/null @@ -1,1113 +0,0 @@ -// Import all components as Vue SFCs -import TypingIndicator from '../vue-components/TypingIndicator.vue'; -import FormField from '../vue-components/FormField.vue'; -import DynamicForm from '../vue-components/DynamicForm.vue'; -import ChatMessage from '../vue-components/ChatMessage.vue'; -import MessageHistory from '../vue-components/MessageHistory.vue'; -import ProgressTracker from '../vue-components/ProgressTracker.vue'; -import LanguageSelector from '../vue-components/LanguageSelector.vue'; -import ChatInput from '../vue-components/ChatInput.vue'; - -// Main Chat Application -// Main Chat Application - geëxporteerd als module -export const ChatApp = { - name: 'ChatApp', - components: { - TypingIndicator, - FormField, - DynamicForm, - ChatMessage, - MessageHistory, - ProgressTracker, - ChatInput - }, - - data() { - // Maak een lokale kopie van de chatConfig om undefined errors te voorkomen - const chatConfig = window.chatConfig || {}; - const settings = chatConfig.settings || {}; - const initialLanguage = chatConfig.language || 'nl'; - const originalExplanation = chatConfig.explanation || ''; - const tenantMake = chatConfig.tenantMake || {}; - - return { - // Tenant info - tenantName: tenantMake.name || 'EveAI', - tenantLogoUrl: tenantMake.logo_url || '', - - // Taal gerelateerde data - currentLanguage: initialLanguage, - supportedLanguageDetails: chatConfig.supportedLanguageDetails || {}, - allowedLanguages: chatConfig.allowedLanguages || ['nl', 'en', 'fr', 'de'], - supportedLanguages: chatConfig.supportedLanguages || [], - originalExplanation: originalExplanation, - explanation: chatConfig.explanation || '', - - // Chat-specific data - currentMessage: '', - allMessages: [], - isTyping: false, - isLoading: false, - isSubmittingForm: false, - messageIdCounter: 1, - formValues: {}, - currentInputFormData: null, - - // API prefix voor endpoints - apiPrefix: chatConfig.apiPrefix || '', - - // Configuration from Flask/server - conversationId: chatConfig.conversationId || 'default', - userId: chatConfig.userId || null, - userName: chatConfig.userName || '', - - // Settings met standaard waarden en overschreven door server config - settings: { - maxMessageLength: settings.maxMessageLength || 2000, - allowFileUpload: settings.allowFileUpload === true, - allowVoiceMessage: settings.allowVoiceMessage === true, - autoScroll: settings.autoScroll === true - }, - - // UI state - isMobile: window.innerWidth <= 768, - showSidebar: window.innerWidth > 768, - - // Advanced features - messageSearch: '', - filteredMessages: [], - isSearching: false - }; - }, - - computed: { - // Keep existing computed from base.html - compiledExplanation() { - if (typeof marked === 'function') { - return marked(this.explanation); - } else if (marked && typeof marked.parse === 'function') { - return marked.parse(this.explanation.replace(/\[\[(.*?)\]\]/g, '$1')); - } else { - console.error('Marked library not properly loaded'); - return this.explanation; - } - }, - - displayMessages() { - return this.isSearching ? this.filteredMessages : this.allMessages; - }, - - hasMessages() { - return this.allMessages.length > 0; - }, - - displayLanguages() { - // Filter de ondersteunde talen op basis van de toegestane talen - if (!this.supportedLanguages || !this.allowedLanguages) { - return []; - } - - return this.supportedLanguages.filter(lang => - this.allowedLanguages.includes(lang.code) - ); - } - }, - - mounted() { - console.log('🔍 [DEBUG] ChatApp mounted'); - console.log('🔍 [DEBUG] ChatApp data:', { - tenantName: this.tenantName, - currentLanguage: this.currentLanguage, - allowedLanguages: this.allowedLanguages, - conversationId: this.conversationId, - userId: this.userId - }); - - // Log beschikbare componenten - console.log('🔍 [DEBUG] Geregistreerde componenten:', { - messageHistory: !!this.$options.components.MessageHistory, - chatInput: !!this.$options.components.ChatInput - }); - - // Render de component - this.renderComponent(); - - console.log('🔍 [DEBUG] ChatApp mounted'); - console.log('🔍 [DEBUG] Props en data:', { - currentLanguage: this.currentLanguage, - allowedLanguages: this.allowedLanguages, - tenantName: this.tenantName - }); - - this.initializeChat(); - this.setupEventListeners(); - - // Render de component - this.renderComponent(); - }, - - beforeUnmount() { - this.cleanup(); - }, - - // Nieuwe methode om de component direct te renderen - renderComponent() { - console.log('🔍 [DEBUG] ChatApp.renderComponent() aangeroepen'); - // Hier kunnen we directe DOM-manipulatie toevoegen indien nodig - // Vergelijkbaar met LanguageSelector.renderComponent() - }, - - methods: { - // Initialization - initializeChat() { - console.log('Initializing chat application...'); - - // Load historical messages from server - this.loadHistoricalMessages(); - - console.log('Nr of messages:', this.allMessages.length); - - // Add welcome message if no history - if (this.allMessages.length === 0) { - this.addWelcomeMessage(); - } - - // Focus input after initialization - this.$nextTick(() => { - this.focusChatInput(); - }); - }, - - loadHistoricalMessages() { - // Veilige toegang tot messages met fallback - const chatConfig = window.chatConfig || {}; - const historicalMessages = chatConfig.messages || []; - - if (historicalMessages.length > 0) { - this.allMessages = historicalMessages - .filter(msg => msg !== null && msg !== undefined) // Filter null/undefined berichten uit - .map(msg => { - // Zorg voor een correct geformatteerde bericht-object - return { - id: this.messageIdCounter++, - content: typeof msg === 'string' ? msg : (msg.content || ''), - sender: msg.sender || 'ai', - type: msg.type || 'text', - timestamp: msg.timestamp || new Date().toISOString(), - formData: msg.formData || null, - status: msg.status || 'delivered' - }; - }); - - console.log(`Loaded ${this.allMessages.length} historical messages`); - } - }, - - async addWelcomeMessage() { - console.log('Sending initialize message to backend'); - - // Toon typing indicator - this.isTyping = true; - this.isLoading = true; - - try { - // Verzamel gegevens voor de API call - const apiData = { - message: 'Initialize', - conversation_id: this.conversationId, - user_id: this.userId, - language: this.currentLanguage - }; - - const response = await this.callAPI('/api/send_message', apiData); - - // Verberg typing indicator - this.isTyping = false; - - // Voeg AI response toe met task_id voor tracking - const aiMessage = this.addMessage( - '', - 'ai', - 'text' - ); - - // Voeg task_id toe als beschikbaar - if (response.task_id) { - console.log('Monitoring Initialize Task ID: ', response.task_id); - aiMessage.taskId = response.task_id; - } - } catch (error) { - console.error('Error sending initialize message:', error); - this.isTyping = false; - - // Voeg standaard welkomstbericht toe als fallback - this.addMessage( - 'Hallo! Ik ben je AI assistant. Vraag gerust om een formulier zoals "contactformulier" of "bestelformulier"!', - 'ai', - 'text' - ); - } finally { - this.isLoading = false; - } - }, - - setupEventListeners() { - // Window resize listener - window.addEventListener('resize', this.handleResize); - - // Keyboard shortcuts - document.addEventListener('keydown', this.handleGlobalKeydown); - - // Luister naar taalwijzigingen via custom events - document.addEventListener('language-changed', (event) => { - if (event.detail && event.detail.language) { - console.log('ChatApp received language-changed event:', event.detail.language); - this.handleLanguageChange(event.detail.language); - } - }); - }, - - cleanup() { - window.removeEventListener('resize', this.handleResize); - document.removeEventListener('keydown', this.handleGlobalKeydown); - }, - - // Taal gerelateerde functionaliteit - handleLanguageChange(newLanguage) { - if (this.currentLanguage !== newLanguage) { - console.log(`ChatApp: Taal gewijzigd van ${this.currentLanguage} naar ${newLanguage}`); - this.currentLanguage = newLanguage; - - // Vertaal de sidebar - this.translateSidebar(newLanguage); - - // Sla de taalvoorkeur op voor toekomstige API calls - this.storeLanguagePreference(newLanguage); - - // Stuur language-changed event voor andere componenten (zoals ChatInput) - // Dit wordt gedaan via het event systeem, waardoor we geen directe referentie nodig hebben - const event = new CustomEvent('language-changed', { - detail: { language: newLanguage } - }); - document.dispatchEvent(event); - } - }, - - // Maak de handleLanguageChange methode toegankelijk van buitenaf - // Deze functie wordt opgeroepen door het externe LanguageSelector component - __handleExternalLanguageChange(newLanguage) { - this.handleLanguageChange(newLanguage); - }, - - storeLanguagePreference(language) { - // Sla op in localStorage voor persistentie - localStorage.setItem('preferredLanguage', language); - - // Update chatConfig voor toekomstige API calls - if (window.chatConfig) { - window.chatConfig.language = language; - } - - console.log(`Taalvoorkeur opgeslagen: ${language}`); - }, - - async translateSidebar(language) { - console.log(`Sidebar wordt vertaald naar: ${language}`); - - // Haal de originele tekst op - const originalText = this.originalExplanation || this.explanation; - - try { - // Controleer of TranslationClient beschikbaar is - if (!window.TranslationClient || typeof window.TranslationClient.translate !== 'function') { - console.error('TranslationClient.translate is niet beschikbaar'); - this.showTranslationIndicator(language, 'Vertaling niet beschikbaar', false); - return; - } - - // Toon loading indicator - this.showTranslationIndicator(language, 'Bezig met vertalen...'); - console.log('API prefix voor vertaling:', this.apiPrefix); - - // Gebruik TranslationClient met de juiste parameters - const response = await window.TranslationClient.translate( - originalText, - language, - null, // source_lang (auto-detect) - 'sidebar_explanation', // context - this.apiPrefix // API prefix voor tenant routing - ); - - if (response.success) { - // Update de explanation variabele - console.log('Translated text: ' + response.translated_text); - this.explanation = response.translated_text; - - // 1. Update de Vue instance - if (window.__vueApp && window.__vueApp._instance) { - window.__vueApp._instance.proxy.explanation = response.translated_text; - } - - // 2. Update direct het DOM-element via marked voor onmiddellijke weergave - const sidebarElement = document.querySelector('.sidebar-explanation'); - if (sidebarElement) { - console.log('DOM-element gevonden, directe update toepassen'); - // Gebruik de marked library om de markdown naar HTML te converteren - let htmlContent; - if (typeof marked === 'function') { - htmlContent = marked(response.translated_text); - } else if (marked && typeof marked.parse === 'function') { - htmlContent = marked.parse(response.translated_text); - } else { - htmlContent = response.translated_text; - } - - // Update de inhoud direct - sidebarElement.innerHTML = htmlContent; - } else { - console.error('Sidebar explanation element niet gevonden in DOM'); - } - - this.showTranslationIndicator(language, 'Vertaling voltooid!', true); - } else { - console.error('Vertaling mislukt:', response.error); - this.showTranslationIndicator(language, 'Vertaling mislukt', false); - } - } catch (error) { - console.error('Fout bij vertalen sidebar:', error); - this.showTranslationIndicator(language, 'Vertaling mislukt', false); - } - }, - - // Message management - addMessage(content, sender, type = 'text', formData = null, formValues = null) { - const message = { - id: this.messageIdCounter++, - content, - sender, - type, - formData, - formValues, - timestamp: new Date().toISOString(), - status: sender === 'user' ? 'sent' : 'delivered' - }; - - this.allMessages.push(message); - - // Initialize form values if it's a form and no values were provided - if (type === 'form' && formData && !formValues) { - // Vue 3 compatibele manier om reactieve objecten bij te werken - this.formValues[message.id] = {}; - formData.fields.forEach(field => { - const fieldName = field.name || field.id; - if (fieldName) { - this.formValues[message.id][fieldName] = field.defaultValue || ''; - } - }); - } - - // Update search results if searching - if (this.isSearching) { - this.performSearch(); - } - - return message; - }, - - showTranslationIndicator(language, message, success = null) { - const explanationElement = document.querySelector('.sidebar-explanation'); - if (explanationElement) { - // Verwijder eventuele bestaande indicators - const existingIndicator = explanationElement.querySelector('.language-change-indicator'); - if (existingIndicator) { - existingIndicator.remove(); - } - - // Voeg nieuwe indicator toe - const indicator = document.createElement('div'); - indicator.className = 'language-change-indicator'; - if (success === true) indicator.classList.add('success'); - if (success === false) indicator.classList.add('error'); - - indicator.innerHTML = `${message}`; - explanationElement.prepend(indicator); - - // Verwijder na 3 seconden, behalve bij loading - if (success !== null) { - setTimeout(() => { - if (explanationElement.contains(indicator)) { - indicator.remove(); - } - }, 3000); - } - } - }, - - - // Helper functie om formulierdata toe te voegen aan bestaande berichten - attachFormDataToMessage(messageId, formData, formValues) { - const message = this.allMessages.find(m => m.id === messageId); - if (message) { - message.formData = formData; - message.formValues = formValues; - } - }, - - updateCurrentMessage(value) { - this.currentMessage = value; - }, - - // Message sending (alleen voor gewone tekstberichten, geen formulieren) - async sendMessage() { - const text = this.currentMessage.trim(); - - // Controleer of we kunnen verzenden - if (!text || this.isLoading) return; - - console.log('Sending text message:', text); - - // Add user message - const userMessage = this.addMessage(text, 'user', 'text'); - - // Wis input - this.currentMessage = ''; - - // Show typing and loading state - this.isTyping = true; - this.isLoading = true; - - try { - // Verzamel gegevens voor de API call - const apiData = { - message: text, - conversation_id: this.conversationId, - user_id: this.userId, - language: this.currentLanguage - }; - - const response = await this.callAPI('/api/send_message', apiData); - - // Hide typing indicator - this.isTyping = false; - - // Mark user message as delivered - userMessage.status = 'delivered'; - - // Add AI response - if (response.type === 'form') { - this.addMessage('', 'ai', 'form', response.formData); - } else { - // Voeg het bericht toe met task_id voor tracking - initieel leeg - const aiMessage = this.addMessage( - '', - 'ai', - 'text' - ); - - // Voeg task_id toe als beschikbaar - if (response.task_id) { - console.log('Monitoring Task ID: ', response.task_id); - aiMessage.taskId = response.task_id; - } - } - - } catch (error) { - console.error('Error sending message:', error); - this.isTyping = false; - - // Mark user message as failed - userMessage.status = 'failed'; - - this.addMessage( - 'Sorry, er ging iets mis bij het verzenden van je bericht. Probeer het opnieuw.', - 'ai', - 'error' - ); - } finally { - this.isLoading = false; - } - }, - - async submitFormFromInput(formValues) { - this.isSubmittingForm = true; - - if (!this.currentInputFormData) { - console.error('No form data available'); - return; - } - - console.log('Form values received:', formValues); - console.log('Current input form data:', this.currentInputFormData); - - try { - // Maak een user message met formuliergegevens én eventuele tekst - const userMessage = this.addMessage( - this.currentMessage.trim(), // Voeg tekst toe als die er is - 'user', - 'text' - ); - - // Voeg formuliergegevens toe aan het bericht - userMessage.formData = this.currentInputFormData; - userMessage.formValues = formValues; - - // Reset het tekstbericht - this.currentMessage = ''; - this.$emit('update-message', ''); - - // Toon laad-indicator - this.isTyping = true; - this.isLoading = true; - - // Verzamel gegevens voor de API call - const apiData = { - message: userMessage.content, - conversation_id: this.conversationId, - user_id: this.userId, - form_values: formValues // Voeg formuliergegevens toe aan API call - }; - - // Verstuur bericht naar de API - const response = await this.callAPI('/api/send_message', apiData); - - // Verberg de typing indicator - this.isTyping = false; - - // Markeer het gebruikersbericht als afgeleverd - userMessage.status = 'delivered'; - - // Voeg AI response toe met task_id voor tracking - const aiMessage = this.addMessage( - '', - 'ai', - 'text' - ); - - if (response.task_id) { - console.log('Monitoring Task ID: ', response.task_id); - aiMessage.taskId = response.task_id; - } - - // Reset formulier na succesvolle verzending - this.currentInputFormData = null; - - } catch (error) { - console.error('Error submitting form:', error); - this.addMessage( - 'Sorry, er ging iets mis bij het verzenden van het formulier. Probeer het opnieuw.', - 'ai', - 'text' - ); - // Wis ook hier het formulier na een fout - this.currentInputFormData = null; - } finally { - this.isSubmittingForm = false; - this.isLoading = false; - } - }, - - // Message actions - - retryMessage(messageId) { - const message = this.allMessages.find(m => m.id === messageId); - if (message && message.status === 'failed') { - // Retry sending the message - this.currentMessage = message.content; - this.removeMessage(messageId); - this.sendMessage(); - } - }, - - submitForm(formValues) { - console.log('🔍 [DEBUG] Formulier verzenden:', formValues); - if (!formValues || this.isLoading) return; - - // Markeer formulier als bezig met verzenden - this.isSubmittingForm = true; - - // Voeg gebruikersformulier toe aan chat - this.addFormMessage(formValues, 'user'); - - // Verstuur naar backend - this.sendFormToBackend(formValues); - - // Reset input form - this.currentInputFormData = null; - }, - - sendFormToBackend(formValues) { - console.log('🔍 [DEBUG] Formulier naar backend versturen', formValues); - // Implementatie voor het versturen van formulier data - this.isSubmittingForm = false; - }, - - sendMessageToBackend(message) { - console.log('🔍 [DEBUG] Bericht naar backend versturen', message); - // Implementatie voor het versturen van berichten - }, - - addFormMessage(formValues, sender) { - console.log('🔍 [DEBUG] Formulier bericht toevoegen:', formValues); - // Implementatie voor het toevoegen van een formulier bericht - }, - - focusChatInput() { - // Focus op de chat input als deze beschikbaar is - this.$nextTick(() => { - // Controleer of $el beschikbaar is - if (!this.$el) { - console.warn('$el is niet beschikbaar in focusChatInput'); - return; - } - - // Probeer de input te vinden en focus - try { - const chatInputComponent = this.$el.querySelector('.chat-input-container'); - if (chatInputComponent) { - console.log('🔍 [DEBUG] Focus op chat input'); - // Probeer een input element te vinden om focus op te zetten - const inputElement = chatInputComponent.querySelector('input, textarea'); - if (inputElement) { - inputElement.focus(); - } - } - } catch (error) { - console.error('Fout bij focussen op chat input:', error); - } - }); - }, - - removeMessage(messageId) { - const index = this.allMessages.findIndex(m => m.id === messageId); - if (index !== -1) { - this.allMessages.splice(index, 1); - // Verwijder ook eventuele formuliergegevens - if (this.formValues[messageId]) { - delete this.formValues[messageId]; - } - } - }, - - // File handling - async handleFileUpload(file) { - console.log('Uploading file:', file.name); - - // Add file message - const fileMessage = this.addMessage('', 'user', 'file', { - fileName: file.name, - fileSize: this.formatFileSize(file.size), - fileType: file.type - }); - - try { - // TODO: Implement actual file upload - // const response = await this.uploadFile(file); - // fileMessage.fileUrl = response.url; - - // Simulate file upload - setTimeout(() => { - fileMessage.fileUrl = URL.createObjectURL(file); - fileMessage.status = 'delivered'; - }, 1000); - - } catch (error) { - console.error('Error uploading file:', error); - fileMessage.status = 'failed'; - } - }, - - async handleVoiceRecord(audioBlob) { - console.log('Processing voice recording'); - - // Add voice message - const voiceMessage = this.addMessage('', 'user', 'voice', { - audioBlob, - duration: '00:05' // TODO: Calculate actual duration - }); - - // TODO: Send to speech-to-text service - // const transcription = await this.transcribeAudio(audioBlob); - // this.currentMessage = transcription; - // this.sendMessage(); - }, - - // Search functionality - performSearch() { - if (!this.messageSearch.trim()) { - this.isSearching = false; - this.filteredMessages = []; - return; - } - - this.isSearching = true; - const query = this.messageSearch.toLowerCase(); - - this.filteredMessages = this.allMessages.filter(message => - message.content && - message.content.toLowerCase().includes(query) - ); - }, - - clearSearch() { - this.messageSearch = ''; - this.isSearching = false; - this.filteredMessages = []; - }, - - // Event handlers voor specialist events - handleSpecialistComplete(eventData) { - console.log('ChatApp received specialist-complete:', eventData); - - // Als er een form_request is, toon deze in de ChatInput component - if (eventData.form_request) { - console.log('Setting form request in ChatInput:', eventData.form_request); - - try { - // Converteer de form_request naar het verwachte formaat - const formData = this.convertFormRequest(eventData.form_request); - - // Stel het formulier in als currentInputFormData in plaats van als bericht toe te voegen - if (formData && formData.title && formData.fields) { - this.currentInputFormData = formData; - } else { - console.error('Invalid form data after conversion:', formData); - } - } catch (err) { - console.error('Error processing form request:', err); - } - } - }, - - handleSpecialistError(eventData) { - console.log('ChatApp received specialist-error:', eventData); - - // Voeg foutbericht toe - this.addMessage( - eventData.message || 'Er is een fout opgetreden bij het verwerken van uw verzoek.', - 'ai', - 'error' - ); - }, - - // Helper methode om form_request te converteren naar het verwachte formaat - convertFormRequest(formRequest) { - console.log('Converting form request:', formRequest); - - if (!formRequest) { - console.error('Geen geldig formRequest ontvangen'); - return null; - } - - // Controleer of fields een object is voordat we converteren - let fieldsArray; - if (formRequest.fields && typeof formRequest.fields === 'object' && !Array.isArray(formRequest.fields)) { - // Converteer de fields van object naar array formaat - fieldsArray = Object.entries(formRequest.fields).map(([fieldId, fieldDef]) => ({ - id: fieldId, - name: fieldDef.name || fieldId, // Gebruik fieldId als fallback - type: fieldDef.type || 'text', // Standaard naar text - description: fieldDef.description || '', - required: fieldDef.required || false, - default: fieldDef.default || '', - allowedValues: fieldDef.allowed_values || null, - context: fieldDef.context || null - })); - } else if (Array.isArray(formRequest.fields)) { - // Als het al een array is, zorg dat alle velden correct zijn - fieldsArray = formRequest.fields.map(field => ({ - id: field.id || field.name, - name: field.name || field.id, - type: field.type || 'text', - description: field.description || '', - required: field.required || false, - default: field.default || field.defaultValue || '', - allowedValues: field.allowed_values || field.allowedValues || null, - context: field.context || null - })); - } else { - // Fallback naar lege array als er geen velden zijn - console.warn('Formulier heeft geen geldige velden'); - fieldsArray = []; - } - - return { - title: formRequest.name || formRequest.title || 'Formulier', - description: formRequest.description || '', - icon: formRequest.icon || 'form', - version: formRequest.version || '1.0', - fields: fieldsArray - }; - }, - - // Event handlers - handleResize() { - this.isMobile = window.innerWidth <= 768; - this.showSidebar = window.innerWidth > 768; - }, - - handleGlobalKeydown(event) { - // Ctrl/Cmd + K for search - if ((event.ctrlKey || event.metaKey) && event.key === 'k') { - event.preventDefault(); - this.focusSearch(); - } - - // Escape to clear search - if (event.key === 'Escape' && this.isSearching) { - this.clearSearch(); - } - }, - - - // Utility methods - async callAPI(endpoint, data) { - // Gebruik de API prefix uit de lokale variabele - const fullEndpoint = this.apiPrefix + '/chat' + endpoint; - - console.log('Calling API with prefix:', { - prefix: this.apiPrefix, - endpoint: endpoint, - fullEndpoint: fullEndpoint - }); - - const response = await fetch(fullEndpoint, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data) - }); - - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - - return response.json(); - }, - - - formatFileSize(bytes) { - if (bytes === 0) return '0 Bytes'; - const k = 1024; - const sizes = ['Bytes', 'KB', 'MB', 'GB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; - }, - - focusSearch() { - this.$refs.searchInput?.focus(); - }, - - renderComponent() { - console.log('🔍 [DEBUG] ChatApp.renderComponent() aangeroepen'); - console.log('🔍 [DEBUG] window.Vue beschikbaar:', !!window.Vue); - if (window.Vue) { - console.log('🔍 [DEBUG] window.Vue.createApp beschikbaar:', !!window.Vue.createApp); - console.log('🔍 [DEBUG] window.Vue.version:', window.Vue.version); - } - - // We gaan direct de container manipuleren - const container = document.querySelector('.chat-container'); - if (!container) { - console.error('Container niet gevonden voor ChatApp (.chat-container)'); - return; - } - - console.log('🔍 [DEBUG] ChatApp container gevonden, inhoud wordt gerenderd'); - console.log('🔍 [DEBUG] Beschikbare components:', { - MessageHistory: !!window.Components?.MessageHistory, - ChatInput: !!window.Components?.ChatInput - }); - - // Basis layout voor de chat app - container.innerHTML = ` -
$1')
- .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1')
- .replace(/\n/g, '$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g,'$1').replace(/\n/g,"$1").replace(/\[([^\]]+)\]\(([^)]+)\)/g,'$1').replace(/\n/g,"${el(e,!0)}`}br(e){return"An error occurred:
"+el(n.message+"",!0)+"";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}},ex=new ev;function eb(e,t){return ex.parse(e,t)}eb.options=eb.setOptions=function(e){return ex.setOptions(e),eb.defaults=ex.defaults,c=eb.defaults,eb},eb.getDefaults=a,eb.defaults=c,eb.use=function(...e){return ex.use(...e),eb.defaults=ex.defaults,c=eb.defaults,eb},eb.walkTokens=function(e,t){return ex.walkTokens(e,t)},eb.parseInline=ex.parseInline,eb.Parser=em,eb.parser=em.parse,eb.Renderer=ef,eb.TextRenderer=eg,eb.Lexer=eh,eb.lexer=eh.lex,eb.Tokenizer=ep,eb.Hooks=ey,eb.parse=eb;var ek=eb.options,eS=eb.setOptions,e_=eb.use,ew=eb.walkTokens,eD=eb.parseInline,eE=eb,eC=em.parse,eT=eh.lex;return e.exports}(),c("gQG4c"),window.TranslationClient={translate:async function(e,t,n=null,r=null,i=""){try{let s={text:e,target_lang:t};n&&(s.source_lang=n),r&&(s.context=r);let o=`${i}/chat/api/translate`;console.log(`Vertaling aanvragen op endpoint: ${o}`);let l=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!l.ok){let e=await l.json();throw Error(e.error||"Onbekende fout bij vertalen")}return await l.json()}catch(e){throw console.error("Vertaalfout:",e),e}}},console.log("TranslationClient geladen en klaar voor gebruik");var f={};s(f,"LanguageSelector",function(){return g}),s(f,"ChatInput",function(){return m}),s(f,"MessageHistory",function(){return y}),s(f,"ChatMessage",function(){return c("lVdl4").default}),s(f,"TypingIndicator",function(){return c("aNcdg").default}),s(f,"ProgressTracker",function(){return c("3b050").default}),s(f,"DynamicForm",function(){return c("9J6tU").default}),s(f,"FormField",function(){return c("70gdv").default}),s(f,"FormMessage",function(){return w}),(e=c("lfk1t")).__esModule&&(e=e.default),e.render=c("esoaL").render,e.__cssModules={},c("6VrmS").default(e),e.__scopeId="data-v-9a7b49",e.__file="LanguageSelector.vue";var g=e;(t=c("13ZGu")).__esModule&&(t=t.default),t.render=c("dv6Fl").render,t.__cssModules={},c("dOnmI").default(t),t.__scopeId="data-v-df2e88",t.__file="ChatInput.vue";var m=t;(n=c("dwb6L")).__esModule&&(n=n.default),n.render=c("3LFpJ").render,n.__cssModules={},c("6hDPH").default(n),n.__scopeId="data-v-efbfed",n.__file="MessageHistory.vue";var y=n,x=c("lVdl4"),b=c("aNcdg"),k=c("3b050"),S=c("9J6tU"),_=c("70gdv");(r=c("eu21N")).__esModule&&(r=r.default),r.render=c("8lvfw").render,r.__cssModules={},c("4boaj").default(r),r.__scopeId="data-v-199543",r.__file="FormMessage.vue";var w=r;console.log("Vue components loaded successfully from barrel export");var b=c("aNcdg"),_=c("70gdv"),S=c("9J6tU"),x=c("lVdl4"),k=c("3b050");let D={name:"ChatApp",components:{TypingIndicator:b.default,FormField:_.default,DynamicForm:S.default,ChatMessage:x.default,MessageHistory:y,ProgressTracker:k.default,ChatInput:m},data(){let e=window.chatConfig||{},t=e.settings||{},n=e.language||"nl",r=e.explanation||"",i=e.tenantMake||{};return{tenantName:i.name||"EveAI",tenantLogoUrl:i.logo_url||"",currentLanguage:n,supportedLanguageDetails:e.supportedLanguageDetails||{},allowedLanguages:e.allowedLanguages||["nl","en","fr","de"],supportedLanguages:e.supportedLanguages||[],originalExplanation:r,explanation:e.explanation||"",currentMessage:"",allMessages:[],isTyping:!1,isLoading:!1,isSubmittingForm:!1,messageIdCounter:1,formValues:{},currentInputFormData:null,apiPrefix:e.apiPrefix||"",conversationId:e.conversationId||"default",userId:e.userId||null,userName:e.userName||"",settings:{maxMessageLength:t.maxMessageLength||2e3,allowFileUpload:!0===t.allowFileUpload,allowVoiceMessage:!0===t.allowVoiceMessage,autoScroll:!0===t.autoScroll},isMobile:window.innerWidth<=768,showSidebar:window.innerWidth>768,messageSearch:"",filteredMessages:[],isSearching:!1}},computed:{compiledExplanation(){return"function"==typeof marked?marked(this.explanation):marked&&"function"==typeof marked.parse?marked.parse(this.explanation.replace(/\[\[(.*?)\]\]/g,"$1")):(console.error("Marked library not properly loaded"),this.explanation)},displayMessages(){return this.isSearching?this.filteredMessages:this.allMessages},hasMessages(){return this.allMessages.length>0},displayLanguages(){return this.supportedLanguages&&this.allowedLanguages?this.supportedLanguages.filter(e=>this.allowedLanguages.includes(e.code)):[]}},mounted(){console.log("\uD83D\uDD0D [DEBUG] ChatApp mounted"),console.log("\uD83D\uDD0D [DEBUG] ChatApp data:",{tenantName:this.tenantName,currentLanguage:this.currentLanguage,allowedLanguages:this.allowedLanguages,conversationId:this.conversationId,userId:this.userId}),console.log("\uD83D\uDD0D [DEBUG] Geregistreerde componenten:",{messageHistory:!!this.$options.components.MessageHistory,chatInput:!!this.$options.components.ChatInput}),this.renderComponent(),console.log("\uD83D\uDD0D [DEBUG] ChatApp mounted"),console.log("\uD83D\uDD0D [DEBUG] Props en data:",{currentLanguage:this.currentLanguage,allowedLanguages:this.allowedLanguages,tenantName:this.tenantName}),this.initializeChat(),this.setupEventListeners(),this.renderComponent()},beforeUnmount(){this.cleanup()},renderComponent(){console.log("\uD83D\uDD0D [DEBUG] ChatApp.renderComponent() aangeroepen")},methods:{initializeChat(){console.log("Initializing chat application..."),this.loadHistoricalMessages(),console.log("Nr of messages:",this.allMessages.length),0===this.allMessages.length&&this.addWelcomeMessage(),this.$nextTick(()=>{this.focusChatInput()})},loadHistoricalMessages(){let e=(window.chatConfig||{}).messages||[];e.length>0&&(this.allMessages=e.filter(e=>null!=e).map(e=>({id:this.messageIdCounter++,content:"string"==typeof e?e:e.content||"",sender:e.sender||"ai",type:e.type||"text",timestamp:e.timestamp||new Date().toISOString(),formData:e.formData||null,status:e.status||"delivered"})),console.log(`Loaded ${this.allMessages.length} historical messages`))},async addWelcomeMessage(){console.log("Sending initialize message to backend"),this.isTyping=!0,this.isLoading=!0;try{let e={message:"Initialize",conversation_id:this.conversationId,user_id:this.userId,language:this.currentLanguage},t=await this.callAPI("/api/send_message",e);this.isTyping=!1;let n=this.addMessage("","ai","text");t.task_id&&(console.log("Monitoring Initialize Task ID: ",t.task_id),n.taskId=t.task_id)}catch(e){console.error("Error sending initialize message:",e),this.isTyping=!1,this.addMessage('Hallo! Ik ben je AI assistant. Vraag gerust om een formulier zoals "contactformulier" of "bestelformulier"!',"ai","text")}finally{this.isLoading=!1}},setupEventListeners(){window.addEventListener("resize",this.handleResize),document.addEventListener("keydown",this.handleGlobalKeydown),document.addEventListener("language-changed",e=>{e.detail&&e.detail.language&&(console.log("ChatApp received language-changed event:",e.detail.language),this.handleLanguageChange(e.detail.language))})},cleanup(){window.removeEventListener("resize",this.handleResize),document.removeEventListener("keydown",this.handleGlobalKeydown)},handleLanguageChange(e){if(this.currentLanguage!==e){console.log(`ChatApp: Taal gewijzigd van ${this.currentLanguage} naar ${e}`),this.currentLanguage=e,this.translateSidebar(e),this.storeLanguagePreference(e);let t=new CustomEvent("language-changed",{detail:{language:e}});document.dispatchEvent(t)}},__handleExternalLanguageChange(e){this.handleLanguageChange(e)},storeLanguagePreference(e){localStorage.setItem("preferredLanguage",e),window.chatConfig&&(window.chatConfig.language=e),console.log(`Taalvoorkeur opgeslagen: ${e}`)},async translateSidebar(e){console.log(`Sidebar wordt vertaald naar: ${e}`);let t=this.originalExplanation||this.explanation;try{if(!window.TranslationClient||"function"!=typeof window.TranslationClient.translate){console.error("TranslationClient.translate is niet beschikbaar"),this.showTranslationIndicator(e,"Vertaling niet beschikbaar",!1);return}this.showTranslationIndicator(e,"Bezig met vertalen..."),console.log("API prefix voor vertaling:",this.apiPrefix);let n=await window.TranslationClient.translate(t,e,null,"sidebar_explanation",this.apiPrefix);if(n.success){console.log("Translated text: "+n.translated_text),this.explanation=n.translated_text,window.__vueApp&&window.__vueApp._instance&&(window.__vueApp._instance.proxy.explanation=n.translated_text);let t=document.querySelector(".sidebar-explanation");if(t)console.log("DOM-element gevonden, directe update toepassen"),t.innerHTML="function"==typeof marked?marked(n.translated_text):marked&&"function"==typeof marked.parse?marked.parse(n.translated_text):n.translated_text;else console.error("Sidebar explanation element niet gevonden in DOM");this.showTranslationIndicator(e,"Vertaling voltooid!",!0)}else console.error("Vertaling mislukt:",n.error),this.showTranslationIndicator(e,"Vertaling mislukt",!1)}catch(t){console.error("Fout bij vertalen sidebar:",t),this.showTranslationIndicator(e,"Vertaling mislukt",!1)}},addMessage(e,t,n="text",r=null,i=null){let s={id:this.messageIdCounter++,content:e,sender:t,type:n,formData:r,formValues:i,timestamp:new Date().toISOString(),status:"user"===t?"sent":"delivered"};return this.allMessages.push(s),"form"===n&&r&&!i&&(this.formValues[s.id]={},r.fields.forEach(e=>{let t=e.name||e.id;t&&(this.formValues[s.id][t]=e.defaultValue||"")})),this.isSearching&&this.performSearch(),s},showTranslationIndicator(e,t,n=null){let r=document.querySelector(".sidebar-explanation");if(r){let e=r.querySelector(".language-change-indicator");e&&e.remove();let i=document.createElement("div");i.className="language-change-indicator",!0===n&&i.classList.add("success"),!1===n&&i.classList.add("error"),i.innerHTML=`${t}`,r.prepend(i),null!==n&&setTimeout(()=>{r.contains(i)&&i.remove()},3e3)}},attachFormDataToMessage(e,t,n){let r=this.allMessages.find(t=>t.id===e);r&&(r.formData=t,r.formValues=n)},updateCurrentMessage(e){this.currentMessage=e},async sendMessage(){let e=this.currentMessage.trim();if(!e||this.isLoading)return;console.log("Sending text message:",e);let t=this.addMessage(e,"user","text");this.currentMessage="",this.isTyping=!0,this.isLoading=!0;try{let n={message:e,conversation_id:this.conversationId,user_id:this.userId,language:this.currentLanguage},r=await this.callAPI("/api/send_message",n);if(this.isTyping=!1,t.status="delivered","form"===r.type)this.addMessage("","ai","form",r.formData);else{let e=this.addMessage("","ai","text");r.task_id&&(console.log("Monitoring Task ID: ",r.task_id),e.taskId=r.task_id)}}catch(e){console.error("Error sending message:",e),this.isTyping=!1,t.status="failed",this.addMessage("Sorry, er ging iets mis bij het verzenden van je bericht. Probeer het opnieuw.","ai","error")}finally{this.isLoading=!1}},async submitFormFromInput(e){if(this.isSubmittingForm=!0,!this.currentInputFormData)return void console.error("No form data available");console.log("Form values received:",e),console.log("Current input form data:",this.currentInputFormData);try{let t=this.addMessage(this.currentMessage.trim(),"user","text");t.formData=this.currentInputFormData,t.formValues=e,this.currentMessage="",this.$emit("update-message",""),this.isTyping=!0,this.isLoading=!0;let n={message:t.content,conversation_id:this.conversationId,user_id:this.userId,form_values:e},r=await this.callAPI("/api/send_message",n);this.isTyping=!1,t.status="delivered";let i=this.addMessage("","ai","text");r.task_id&&(console.log("Monitoring Task ID: ",r.task_id),i.taskId=r.task_id),this.currentInputFormData=null}catch(e){console.error("Error submitting form:",e),this.addMessage("Sorry, er ging iets mis bij het verzenden van het formulier. Probeer het opnieuw.","ai","text"),this.currentInputFormData=null}finally{this.isSubmittingForm=!1,this.isLoading=!1}},retryMessage(e){let t=this.allMessages.find(t=>t.id===e);t&&"failed"===t.status&&(this.currentMessage=t.content,this.removeMessage(e),this.sendMessage())},submitForm(e){console.log("\uD83D\uDD0D [DEBUG] Formulier verzenden:",e),e&&!this.isLoading&&(this.isSubmittingForm=!0,this.addFormMessage(e,"user"),this.sendFormToBackend(e),this.currentInputFormData=null)},sendFormToBackend(e){console.log("\uD83D\uDD0D [DEBUG] Formulier naar backend versturen",e),this.isSubmittingForm=!1},sendMessageToBackend(e){console.log("\uD83D\uDD0D [DEBUG] Bericht naar backend versturen",e)},addFormMessage(e,t){console.log("\uD83D\uDD0D [DEBUG] Formulier bericht toevoegen:",e)},focusChatInput(){this.$nextTick(()=>{if(!this.$el)return void console.warn("$el is niet beschikbaar in focusChatInput");try{let e=this.$el.querySelector(".chat-input-container");if(e){console.log("\uD83D\uDD0D [DEBUG] Focus op chat input");let t=e.querySelector("input, textarea");t&&t.focus()}}catch(e){console.error("Fout bij focussen op chat input:",e)}})},removeMessage(e){let t=this.allMessages.findIndex(t=>t.id===e);-1!==t&&(this.allMessages.splice(t,1),this.formValues[e]&&delete this.formValues[e])},async handleFileUpload(e){console.log("Uploading file:",e.name);let t=this.addMessage("","user","file",{fileName:e.name,fileSize:this.formatFileSize(e.size),fileType:e.type});try{setTimeout(()=>{t.fileUrl=URL.createObjectURL(e),t.status="delivered"},1e3)}catch(e){console.error("Error uploading file:",e),t.status="failed"}},async handleVoiceRecord(e){console.log("Processing voice recording"),this.addMessage("","user","voice",{audioBlob:e,duration:"00:05"})},performSearch(){if(!this.messageSearch.trim()){this.isSearching=!1,this.filteredMessages=[];return}this.isSearching=!0;let e=this.messageSearch.toLowerCase();this.filteredMessages=this.allMessages.filter(t=>t.content&&t.content.toLowerCase().includes(e))},clearSearch(){this.messageSearch="",this.isSearching=!1,this.filteredMessages=[]},handleSpecialistComplete(e){if(console.log("ChatApp received specialist-complete:",e),e.form_request){console.log("Setting form request in ChatInput:",e.form_request);try{let t=this.convertFormRequest(e.form_request);t&&t.title&&t.fields?this.currentInputFormData=t:console.error("Invalid form data after conversion:",t)}catch(e){console.error("Error processing form request:",e)}}},handleSpecialistError(e){console.log("ChatApp received specialist-error:",e),this.addMessage(e.message||"Er is een fout opgetreden bij het verwerken van uw verzoek.","ai","error")},convertFormRequest(e){let t;return(console.log("Converting form request:",e),e)?(e.fields&&"object"==typeof e.fields&&!Array.isArray(e.fields)?t=Object.entries(e.fields).map(([e,t])=>({id:e,name:t.name||e,type:t.type||"text",description:t.description||"",required:t.required||!1,default:t.default||"",allowedValues:t.allowed_values||null,context:t.context||null})):Array.isArray(e.fields)?t=e.fields.map(e=>({id:e.id||e.name,name:e.name||e.id,type:e.type||"text",description:e.description||"",required:e.required||!1,default:e.default||e.defaultValue||"",allowedValues:e.allowed_values||e.allowedValues||null,context:e.context||null})):(console.warn("Formulier heeft geen geldige velden"),t=[]),{title:e.name||e.title||"Formulier",description:e.description||"",icon:e.icon||"form",version:e.version||"1.0",fields:t}):(console.error("Geen geldig formRequest ontvangen"),null)},handleResize(){this.isMobile=window.innerWidth<=768,this.showSidebar=window.innerWidth>768},handleGlobalKeydown(e){(e.ctrlKey||e.metaKey)&&"k"===e.key&&(e.preventDefault(),this.focusSearch()),"Escape"===e.key&&this.isSearching&&this.clearSearch()},async callAPI(e,t){let n=this.apiPrefix+"/chat"+e;console.log("Calling API with prefix:",{prefix:this.apiPrefix,endpoint:e,fullEndpoint:n});let r=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!r.ok)throw Error(`HTTP error! status: ${r.status}`);return r.json()},formatFileSize(e){if(0===e)return"0 Bytes";let t=Math.floor(Math.log(e)/Math.log(1024));return parseFloat((e/Math.pow(1024,t)).toFixed(2))+" "+["Bytes","KB","MB","GB"][t]},focusSearch(){this.$refs.searchInput?.focus()},renderComponent(){console.log("\uD83D\uDD0D [DEBUG] ChatApp.renderComponent() aangeroepen"),console.log("\uD83D\uDD0D [DEBUG] window.Vue beschikbaar:",!!window.Vue),window.Vue&&(console.log("\uD83D\uDD0D [DEBUG] window.Vue.createApp beschikbaar:",!!window.Vue.createApp),console.log("\uD83D\uDD0D [DEBUG] window.Vue.version:",window.Vue.version));let e=document.querySelector(".chat-container");if(!e)return void console.error("Container niet gevonden voor ChatApp (.chat-container)");console.log("\uD83D\uDD0D [DEBUG] ChatApp container gevonden, inhoud wordt gerenderd"),console.log("\uD83D\uDD0D [DEBUG] Beschikbare components:",{MessageHistory:!!window.Components?.MessageHistory,ChatInput:!!window.Components?.ChatInput}),e.innerHTML=` -
An error occurred:
"+el(n.message+"",!0)+"";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}},ev=new ex;function eb(e,t){return ev.parse(e,t)}eb.options=eb.setOptions=function(e){return ev.setOptions(e),eb.defaults=ev.defaults,c=eb.defaults,eb},eb.getDefaults=a,eb.defaults=c,eb.use=function(...e){return ev.use(...e),eb.defaults=ev.defaults,c=eb.defaults,eb},eb.walkTokens=function(e,t){return ev.walkTokens(e,t)},eb.parseInline=ev.parseInline,eb.Parser=em,eb.parser=em.parse,eb.Renderer=ef,eb.TextRenderer=eg,eb.Lexer=eh,eb.lexer=eh.lex,eb.Tokenizer=ep,eb.Hooks=ey,eb.parse=eb;var ek=eb.options,eS=eb.setOptions,e_=eb.use,ew=eb.walkTokens,eE=eb.parseInline,eT=eb,eC=em.parse,eA=eh.lex;return e.exports}(),l("gQG4c"),window.TranslationClient={translate:async function(e,t,n=null,r=null,i=""){try{let s={text:e,target_lang:t};n&&(s.source_lang=n),r&&(s.context=r);let o=`${i}/api/translate`;console.log(`Vertaling aanvragen op endpoint: ${o}`);let l=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});if(!l.ok){let e=await l.json();throw Error(e.error||"Onbekende fout bij vertalen")}return await l.json()}catch(e){throw console.error("Vertaalfout:",e),e}}},console.log("TranslationClient geladen en klaar voor gebruik");var p={};r(p,"LanguageSelector",function(){return l("2Fvhx").default}),r(p,"ChatInput",function(){return l("2TN9T").default}),r(p,"MessageHistory",function(){return l("1MYs0").default}),r(p,"ChatMessage",function(){return l("lVdl4").default}),r(p,"TypingIndicator",function(){return l("aNcdg").default}),r(p,"ProgressTracker",function(){return l("3b050").default}),r(p,"DynamicForm",function(){return l("9J6tU").default}),r(p,"FormField",function(){return l("70gdv").default}),r(p,"FormMessage",function(){return f});var h=l("2Fvhx");l("2TN9T"),l("1MYs0"),l("lVdl4"),l("aNcdg"),l("3b050"),l("9J6tU"),l("70gdv"),(e=l("eu21N")).__esModule&&(e=e.default),e.render=l("8lvfw").render,e.__cssModules={},l("4boaj").default(e),e.__scopeId="data-v-199543",e.__file="FormMessage.vue";var f=e;console.log("Vue components loaded successfully from barrel export");var h=l("2Fvhx");(t=l("6jOml")).__esModule&&(t=t.default),t.render=l("1JmDG").render,t.__cssModules={},l("cH9BU").default(t),t.__scopeId="data-v-bfe173",t.__file="ChatApp.vue";var g=t;window.Vue={createApp:c.createApp,version:u.version},window.marked=d.marked,window.Components=p,console.log("Components loaded:",Object.keys(p)),window.addEventListener("error",function(e){console.error("\uD83D\uDEA8 [Global Error]",e.error)}),document.addEventListener("DOMContentLoaded",function(){window.chatConfig||(console.error("chatConfig is niet beschikbaar"),window.chatConfig={}),function(){let e=document.getElementById("sidebar-explanation");e&&window.chatConfig.explanation&&("function"==typeof window.marked?e.innerHTML=window.marked(window.chatConfig.explanation):window.marked&&"function"==typeof window.marked.parse?e.innerHTML=window.marked.parse(window.chatConfig.explanation.replace(/\[\[(.*?)\]\]/g,"$1")):e.innerHTML=window.chatConfig.explanation)}(),function(){let e=document.getElementById("language-selector-container");if(!e)return console.error("#language-selector-container niet gevonden");try{let t={initialLanguage:window.chatConfig.language||"nl",supportedLanguageDetails:window.chatConfig.supportedLanguageDetails||{},allowedLanguages:window.chatConfig.allowedLanguages||["nl","en","fr","de"]},n=window.Vue&&"function"==typeof window.Vue.createApp?window.Vue.createApp(h.default,t):(0,c.createApp)(h.default,t);n.config.errorHandler=(e,t,n)=>{console.error("\uD83D\uDEA8 [Vue Error]",e),console.error("Component:",t),console.error("Error Info:",n)},n.mount(e),document.addEventListener("vue:language-changed",function(e){let t=e.detail.language;console.log(`Taal gewijzigd naar ${t}`),window.chatConfig&&(window.chatConfig.language=t);let n=new CustomEvent("language-changed",{detail:{language:t}});document.dispatchEvent(n),localStorage.setItem("preferredLanguage",t)})}catch(e){console.error("\uD83D\uDEA8 [CRITICAL ERROR] Bij initialiseren language selector:",e),console.error("Stack trace:",e.stack)}}(),function(){let e=document.querySelector(".chat-container");if(!e)return console.error("\uD83D\uDEA8 [CRITICAL ERROR] .chat-container niet gevonden");try{if(!g)throw Error("\uD83D\uDEA8 [CRITICAL ERROR] ChatApp component niet gevonden");p.MessageHistory&&p.ChatInput&&p.TypingIndicator&&p.ChatMessage||console.warn("⚠️ [WARN] Niet alle benodigde sub-componenten zijn geladen!");let t={apiPrefix:window.chatConfig.apiPrefix||"",conversationId:window.chatConfig.conversationId||"default",userId:window.chatConfig.userId||null,userName:window.chatConfig.userName||"",initialLanguage:window.chatConfig.language||"nl",supportedLanguageDetails:window.chatConfig.supportedLanguageDetails||{},allowedLanguages:window.chatConfig.allowedLanguages||["nl","en","fr","de"]},n=(0,c.createApp)(g,t);n.provide("sseConfig",{maxRetries:3,retryDelay:2e3,handleSseError:function(e,t){return console.warn(`SSE verbinding voor task ${t} mislukt:`,e),this.fallbackToPolling(t)},fallbackToPolling:function(e){console.log(`Fallback naar polling voor task ${e}`);let n=setInterval(()=>{let r=`${t.apiPrefix}/api/task_status/${e}`;fetch(r).then(e=>{if(!e.ok)throw Error(`Task status endpoint error: ${e.status}`);return e.json()}).then(t=>{let r=new CustomEvent("message",{detail:{data:JSON.stringify(t)}});document.dispatchEvent(new CustomEvent(`sse:${e}:message`,{detail:r})),("completed"===t.status||"failed"===t.status||"cancelled"===t.status)&&clearInterval(n)}).catch(e=>console.error("Polling error:",e))},3e3);return n}}),Object.entries(p).forEach(([e,t])=>{n.component(e,t)}),n.config.errorHandler=(e,t,n)=>{console.error("\uD83D\uDEA8 [Vue Error in ChatApp]",e),console.error("Component:",t),console.error("Error Info:",n)};let r=n.mount(e);window.__chatApp=r,window.__vueApp=n}catch(t){console.error("\uD83D\uDEA8 [CRITICAL ERROR] Bij initialiseren chat app:",t),console.error("Stack trace:",t.stack),e.innerHTML="