// Import all components via barrel export import { TypingIndicator, FormField, DynamicForm, ChatMessage, MessageHistory, ProgressTracker, LanguageSelector, ChatInput } from './components/index.js'; // 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 = `
`; // Nu we de DOM structuur hebben, gaan we de componenten initialiseren const messageHistoryContainer = document.getElementById('chat-message-history'); const chatInputContainer = document.getElementById('chat-input-container'); // Instantieer MessageHistory component met Vue if (messageHistoryContainer) { console.log('πŸ” [DEBUG] MessageHistory container gevonden, initialiseren...'); try { // Maak props voor de MessageHistory component const messageHistoryProps = { messages: this.allMessages, isTyping: this.isTyping, isSubmittingForm: this.isSubmittingForm, apiPrefix: this.apiPrefix, autoScroll: true }; // Maak een nieuwe Vue app en registreer alle componenten const messageHistoryApp = window.Vue.createApp(MessageHistory, messageHistoryProps); // Registreer benodigde componenten voor MessageHistory messageHistoryApp.component('chat-message', ChatMessage); messageHistoryApp.component('typing-indicator', TypingIndicator); messageHistoryApp.component('progress-tracker', ProgressTracker); messageHistoryApp.component('dynamic-form', DynamicForm); // Error handler messageHistoryApp.config.errorHandler = (err, vm, info) => { console.error('🚨 [Vue Error in MessageHistory]', err); console.error('Component:', vm); console.error('Error Info:', info); }; // Geef events door naar de ChatApp messageHistoryApp.config.globalProperties.$emit = (event, ...args) => { if (event === 'specialist-complete') { this.handleSpecialistComplete(args[0]); } else if (event === 'specialist-error') { this.handleSpecialistError(args[0]); } }; // Mount de component en bewaar de referentie - controleer of renderComponent bestaat let messageHistoryInstance = null; if (typeof MessageHistory.renderComponent === 'function') { messageHistoryInstance = MessageHistory.renderComponent( messageHistoryContainer, messageHistoryProps, messageHistoryApp ); } else { // Fallback: direct mounten messageHistoryInstance = messageHistoryApp.mount(messageHistoryContainer); console.log('πŸ” [DEBUG] MessageHistory direct gemount via app.mount()'); } // Bewaar de instantie voor toekomstige updates this.$refs.messageHistory = messageHistoryInstance; console.log('πŸ” [DEBUG] MessageHistory component succesvol geΓ―nitialiseerd'); } catch (error) { console.error('🚨 [ERROR] Fout bij initialiseren MessageHistory:', error); } } else { console.error('MessageHistory container niet gevonden in de DOM'); } // Instantieer ChatInput component met Vue if (chatInputContainer) { console.log('πŸ” [DEBUG] ChatInput container gevonden, initialiseren...'); try { // Maak props voor de ChatInput component const chatInputProps = { currentMessage: this.currentMessage, isLoading: this.isLoading, maxLength: this.settings.maxMessageLength, formData: this.currentInputFormData, allowFileUpload: this.settings.allowFileUpload, allowVoiceMessage: this.settings.allowVoiceMessage }; // Maak een nieuwe Vue app en registreer alle componenten const chatInputApp = window.Vue.createApp(ChatInput, chatInputProps); // Registreer benodigde componenten voor ChatInput chatInputApp.component('dynamic-form', DynamicForm); chatInputApp.component('form-field', FormField); // Error handler chatInputApp.config.errorHandler = (err, vm, info) => { console.error('🚨 [Vue Error in ChatInput]', err); console.error('Component:', vm); console.error('Error Info:', info); }; // Geef events door naar de ChatApp chatInputApp.config.globalProperties.$emit = (event, ...args) => { if (event === 'send-message') { this.sendMessage(); } else if (event === 'update-message') { this.updateCurrentMessage(args[0]); } else if (event === 'submit-form') { this.submitFormFromInput(args[0]); } else if (event === 'upload-file') { this.handleFileUpload(args[0]); } else if (event === 'record-voice') { this.handleVoiceRecord(args[0]); } }; // Mount de component en bewaar de referentie - controleer of renderComponent bestaat let chatInputInstance = null; if (typeof ChatInput.renderComponent === 'function') { console.log('πŸ” [DEBUG] ChatInput.renderComponent wordt aangeroepen met chatInputApp:', chatInputApp); console.log('πŸ” [DEBUG] chatInputApp.mount type:', typeof chatInputApp.mount); chatInputInstance = ChatInput.renderComponent( chatInputContainer, chatInputProps, chatInputApp ); } else { // Fallback: direct mounten console.log('πŸ” [DEBUG] ChatInput wordt direct gemount via app.mount()'); chatInputInstance = chatInputApp.mount(chatInputContainer); console.log('πŸ” [DEBUG] ChatInput direct gemount via app.mount()'); } // Bewaar de instantie voor toekomstige updates this.$refs.chatInput = chatInputInstance; console.log('πŸ” [DEBUG] ChatInput component succesvol geΓ―nitialiseerd'); } catch (error) { console.error('🚨 [ERROR] Fout bij initialiseren ChatInput:', error); } } else { console.error('ChatInput container niet gevonden in de DOM'); } console.log('πŸ” [DEBUG] ChatApp succesvol gerenderd met alle componenten'); }, }, // Voeg een minimale render functie toe (vergelijkbaar met LanguageSelector) render() { return document.createElement('div'); }, template: `
` };