// static/js/components/ChatInput.js // Importeer de benodigde componenten import { DynamicForm } from './DynamicForm.js'; import { IconManagerMixin } from '../iconManager.js'; // CSS wordt nu geladen via de main bundle in chat-client.js // We hoeven hier niets dynamisch te laden export const ChatInput = { name: 'ChatInput', components: { 'dynamic-form': DynamicForm }, // Static method for direct rendering renderComponent(container, props, app) { console.log('๐Ÿ” [DEBUG] ChatInput.renderComponent() aangeroepen'); console.log('๐Ÿ” [DEBUG] ChatInput container:', container); console.log('๐Ÿ” [DEBUG] ChatInput props:', props); console.log('๐Ÿ” [DEBUG] ChatInput app:', app); if (!container) { console.error('Container element niet gevonden voor ChatInput'); return null; } // Controleer de globale dependencies console.log('๐Ÿ” [DEBUG] Global dependencies check:'); console.log('- window.Vue:', typeof window.Vue); if (window.Vue) { console.log('- window.Vue.createApp:', typeof window.Vue.createApp); console.log('- window.Vue.version:', window.Vue.version); } console.log('๐Ÿ” [DEBUG] ChatInput container gevonden, Vue app aan het initialiseren'); try { // We controleren het app object if (!app) { console.error('๐Ÿšจ [ERROR] Geen Vue app object ontvangen'); return null; } // Check of we een correcte Vue app hebben of we moeten er een maken if (typeof app.mount !== 'function') { console.log('๐Ÿ” [DEBUG] Ontvangen app heeft geen mount functie, dit is mogelijk een config object'); // Controleer of window.Vue beschikbaar is if (!window.Vue || typeof window.Vue.createApp !== 'function') { console.error('๐Ÿšจ [ERROR] window.Vue.createApp is niet beschikbaar'); return null; } // Maak een nieuwe Vue app met het ChatInput component en de props console.log('๐Ÿ” [DEBUG] Nieuwe Vue app aanmaken met ChatInput component'); try { app = window.Vue.createApp(ChatInput, props); console.log('๐Ÿ” [DEBUG] Nieuwe app aangemaakt:', app); } catch (createError) { console.error('๐Ÿšจ [ERROR] Fout bij aanmaken Vue app:', createError); // Probeer een alternatieve aanpak zonder importreferenties console.log('๐Ÿ” [DEBUG] Alternatieve aanpak proberen...'); const componentCopy = JSON.parse(JSON.stringify(ChatInput)); app = window.Vue.createApp(componentCopy, props); } } // Stel een fallback DOM in voor het geval mounten mislukt container.innerHTML = `
Chat input laden...
`; // Nu kunnen we de app mounten console.log('๐Ÿ” [DEBUG] App.mount aanroepen op container'); const instance = app.mount(container); console.log('๐Ÿ” [DEBUG] ChatInput component succesvol gemount, instance:', instance); return instance; } catch (error) { console.error('๐Ÿšจ [ERROR] Fout bij mounten ChatInput component:', error); console.error('Error stack:', error.stack); return null; } }, // Gebruik de IconManagerMixin om automatisch iconen te laden mixins: [IconManagerMixin], created() { // Als er een formData.icon is, wordt deze automatisch geladen via IconManagerMixin // Geen expliciete window.iconManager calls meer nodig // Maak een benoemde handler voor betere cleanup this.languageChangeHandler = (event) => { if (event.detail && event.detail.language) { this.handleLanguageChange(event); } }; // Luister naar taalwijzigingen document.addEventListener('language-changed', this.languageChangeHandler); }, beforeUnmount() { // Verwijder event listener bij unmount met de benoemde handler if (this.languageChangeHandler) { document.removeEventListener('language-changed', this.languageChangeHandler); } }, props: { currentMessage: { type: String, default: '' }, isLoading: { type: Boolean, default: false }, placeholder: { type: String, default: 'Typ je bericht hier... - Enter om te verzenden, Shift+Enter voor nieuwe regel' }, maxLength: { type: Number, default: 2000 }, formData: { type: Object, default: null }, }, emits: ['send-message', 'update-message', 'submit-form'], watch: { 'formData.icon': { handler(newIcon) { if (newIcon && window.iconManager) { window.iconManager.ensureIconsLoaded({}, [newIcon]); } }, immediate: true }, formData: { handler(newFormData, oldFormData) { console.log('ChatInput formData changed:', newFormData); if (!newFormData) { console.log('FormData is null of undefined'); this.formValues = {}; return; } // Controleer of velden aanwezig zijn if (!newFormData.fields) { console.error('FormData bevat geen velden!', newFormData); return; } console.log('Velden in formData:', newFormData.fields); console.log('Aantal velden:', Array.isArray(newFormData.fields) ? newFormData.fields.length : Object.keys(newFormData.fields).length); // Initialiseer formulierwaarden this.initFormValues(); // Log de geรฏnitialiseerde waarden console.log('Formulierwaarden geรฏnitialiseerd:', this.formValues); }, immediate: true, deep: true }, currentMessage(newVal) { this.localMessage = newVal; }, localMessage(newVal) { this.$emit('update-message', newVal); this.autoResize(); } }, data() { return { localMessage: this.currentMessage, formValues: {}, translatedPlaceholder: this.placeholder, isTranslating: false, languageChangeHandler: null }; }, computed: { characterCount() { return this.localMessage.length; }, isOverLimit() { return this.characterCount > this.maxLength; }, hasFormData() { return this.formData && this.formData.fields && ((Array.isArray(this.formData.fields) && this.formData.fields.length > 0) || (typeof this.formData.fields === 'object' && Object.keys(this.formData.fields).length > 0)); }, canSend() { const hasValidForm = this.formData && this.validateForm(); const hasValidMessage = this.localMessage.trim() && !this.isOverLimit; // We kunnen nu verzenden als er een geldig formulier OF een geldig bericht is // Bij een formulier is aanvullende tekst optioneel return (!this.isLoading) && (hasValidForm || hasValidMessage); }, hasFormDataToSend() { return this.formData && this.validateForm(); }, sendButtonText() { if (this.isLoading) { return 'Verzenden...'; } return this.formData ? 'Verstuur formulier' : 'Verstuur bericht'; } }, mounted() { this.autoResize(); // Debug informatie over formData bij initialisatie console.log('ChatInput mounted, formData:', this.formData); if (this.formData) { console.log('FormData bij mount:', JSON.stringify(this.formData)); } }, methods: { handleLanguageChange(event) { if (event.detail && event.detail.language) { this.translatePlaceholder(event.detail.language); } }, async translatePlaceholder(language) { // Voorkom dubbele vertaling if (this.isTranslating) { console.log('Placeholder vertaling al bezig, overslaan...'); return; } // Zet de vertaling vlag this.isTranslating = true; // Gebruik de originele placeholder als basis voor vertaling const originalText = this.placeholder; try { // Controleer of TranslationClient beschikbaar is if (!window.TranslationClient || typeof window.TranslationClient.translate !== 'function') { console.error('TranslationClient.translate is niet beschikbaar voor placeholder'); return; } // Gebruik TranslationClient zonder UI indicator const apiPrefix = window.chatConfig?.apiPrefix || ''; const response = await window.TranslationClient.translate( originalText, language, null, // source_lang (auto-detect) 'chat_input_placeholder', // context apiPrefix // API prefix voor tenant routing ); if (response.success) { // Update de placeholder this.translatedPlaceholder = response.translated_text; } else { console.error('Vertaling placeholder mislukt:', response.error); } } catch (error) { console.error('Fout bij vertalen placeholder:', error); } finally { // Reset de vertaling vlag this.isTranslating = false; } }, initFormValues() { if (this.formData && this.formData.fields) { console.log('Initializing form values for fields:', this.formData.fields); this.formValues = {}; // Verwerk array van velden if (Array.isArray(this.formData.fields)) { this.formData.fields.forEach(field => { const fieldId = field.id || field.name; if (fieldId) { this.formValues[fieldId] = field.default !== undefined ? field.default : ''; } }); } // Verwerk object van velden else if (typeof this.formData.fields === 'object') { Object.entries(this.formData.fields).forEach(([fieldId, field]) => { this.formValues[fieldId] = field.default !== undefined ? field.default : ''; }); } console.log('Initialized form values:', this.formValues); } }, handleKeydown(event) { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); this.sendMessage(); } else if (event.key === 'Escape') { this.localMessage = ''; } }, sendMessage() { if (!this.canSend) return; // Bij een formulier gaan we het formulier en optioneel bericht combineren if (this.formData) { // Valideer het formulier if (this.validateForm()) { // Verstuur het formulier, eventueel met aanvullende tekst this.$emit('submit-form', this.formValues); } } else if (this.localMessage.trim()) { // Verstuur normaal bericht zonder formulier this.$emit('send-message'); } }, getFormValuesForSending() { // Geeft de huidige formulierwaarden terug voor verzending return this.formValues; }, // Reset het formulier en de waarden resetForm() { this.formValues = {}; this.initFormValues(); }, // Annuleer het formulier (wordt momenteel niet gebruikt) cancelForm() { this.formValues = {}; // We sturen geen emit meer, maar het kan nuttig zijn om in de toekomst te hebben }, validateForm() { if (!this.formData || !this.formData.fields) return false; // Controleer of alle verplichte velden zijn ingevuld let missingFields = []; if (Array.isArray(this.formData.fields)) { missingFields = this.formData.fields.filter(field => { if (!field.required) return false; const fieldId = field.id || field.name; const value = this.formValues[fieldId]; return value === undefined || value === null || (typeof value === 'string' && !value.trim()); }); } else { // Voor object-gebaseerde velden Object.entries(this.formData.fields).forEach(([fieldId, field]) => { if (field.required) { const value = this.formValues[fieldId]; if (value === undefined || value === null || (typeof value === 'string' && !value.trim())) { missingFields.push(field); } } }); } return missingFields.length === 0; }, autoResize() { this.$nextTick(() => { const textarea = this.$refs.messageInput; if (textarea) { textarea.style.height = 'auto'; textarea.style.height = Math.min(textarea.scrollHeight, 120) + 'px'; } }); }, focusInput() { this.$refs.messageInput?.focus(); }, clearInput() { this.localMessage = ''; this.focusInput(); }, updateFormValues(newValues) { // Controleer of er daadwerkelijk iets is veranderd om recursieve updates te voorkomen if (JSON.stringify(newValues) !== JSON.stringify(this.formValues)) { this.formValues = JSON.parse(JSON.stringify(newValues)); } } }, template: `
Fout: Geen velden gevonden in formulier
{{ characterCount }}/{{ maxLength }}
` };