230 lines
8.3 KiB
JavaScript
230 lines
8.3 KiB
JavaScript
// Import afhankelijke componenten
|
|
import { ChatMessage } from './ChatMessage.js';
|
|
import { TypingIndicator } from './TypingIndicator.js';
|
|
import { ProgressTracker } from './ProgressTracker.js';
|
|
|
|
export const MessageHistory = {
|
|
name: 'MessageHistory',
|
|
components: {
|
|
'chat-message': ChatMessage,
|
|
'typing-indicator': TypingIndicator,
|
|
'progress-tracker': ProgressTracker
|
|
},
|
|
props: {
|
|
messages: {
|
|
type: Array,
|
|
required: true,
|
|
default: () => []
|
|
},
|
|
isTyping: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
isSubmittingForm: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
apiPrefix: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
autoScroll: {
|
|
type: Boolean,
|
|
default: true
|
|
}
|
|
},
|
|
emits: ['submit-form', 'load-more', 'specialist-complete', 'specialist-error'],
|
|
data() {
|
|
return {
|
|
isAtBottom: true,
|
|
unreadCount: 0,
|
|
originalFirstMessage: null,
|
|
isTranslating: false, // Vlag om dubbele vertaling te voorkomen
|
|
languageChangeHandler: null // Referentie voor cleanup
|
|
};
|
|
},
|
|
mounted() {
|
|
this.scrollToBottom();
|
|
this.setupScrollListener();
|
|
this.listenForLanguageChanges();
|
|
|
|
// Sla de originele inhoud van het eerste bericht op als er maar één bericht is
|
|
if (this.messages.length === 1 && this.messages[0].sender === 'ai') {
|
|
this.originalFirstMessage = this.messages[0].content;
|
|
}
|
|
},
|
|
updated() {
|
|
if (this.autoScroll && this.isAtBottom) {
|
|
this.$nextTick(() => this.scrollToBottom());
|
|
}
|
|
},
|
|
methods: {
|
|
listenForLanguageChanges() {
|
|
// Maak een benoemde handler voor cleanup
|
|
this.languageChangeHandler = (event) => {
|
|
if (event.detail && event.detail.language) {
|
|
this.translateFirstMessageIfNeeded(event.detail.language);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('language-changed', this.languageChangeHandler);
|
|
},
|
|
|
|
async translateFirstMessageIfNeeded(language) {
|
|
// Voorkom dubbele vertaling
|
|
if (this.isTranslating) {
|
|
console.log('Vertaling al bezig, overslaan...');
|
|
return;
|
|
}
|
|
|
|
// Alleen vertalen als er precies één bericht is en het is van de AI
|
|
if (this.messages.length === 1 && this.messages[0].sender === 'ai') {
|
|
const firstMessage = this.messages[0];
|
|
|
|
// Controleer of we een origineel bericht hebben om te vertalen
|
|
const contentToTranslate = this.originalFirstMessage || firstMessage.content;
|
|
|
|
// Sla het originele bericht op als we dat nog niet hebben gedaan
|
|
if (!this.originalFirstMessage) {
|
|
this.originalFirstMessage = contentToTranslate;
|
|
}
|
|
|
|
// Zet de vertaling vlag
|
|
this.isTranslating = true;
|
|
|
|
try {
|
|
// Controleer of de vertaalclient beschikbaar is
|
|
if (!window.TranslationClient || typeof window.TranslationClient.translate !== 'function') {
|
|
console.error('TranslationClient.translate is niet beschikbaar');
|
|
return;
|
|
}
|
|
|
|
console.log(`Vertalen van eerste bericht naar ${language}`);
|
|
|
|
// Vertaal het bericht met de juiste context
|
|
const response = await window.TranslationClient.translate(
|
|
contentToTranslate,
|
|
language,
|
|
null, // source_lang (auto-detect)
|
|
'first_message', // context
|
|
this.apiPrefix // API prefix voor tenant routing
|
|
);
|
|
|
|
if (response.success) {
|
|
console.log('Vertaling van eerste bericht voltooid:', response.translated_text);
|
|
// Update het bericht zonder een indicator te tonen
|
|
firstMessage.content = response.translated_text;
|
|
} else {
|
|
console.error('Vertaling van eerste bericht mislukt:', response.error);
|
|
}
|
|
} catch (error) {
|
|
console.error('Fout bij het vertalen van eerste bericht:', error);
|
|
} finally {
|
|
// Reset de vertaling vlag
|
|
this.isTranslating = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
scrollToBottom() {
|
|
const container = this.$refs.messagesContainer;
|
|
if (container) {
|
|
container.scrollTop = container.scrollHeight;
|
|
this.isAtBottom = true;
|
|
this.showScrollButton = false;
|
|
this.unreadCount = 0;
|
|
}
|
|
},
|
|
|
|
setupScrollListener() {
|
|
const container = this.$refs.messagesContainer;
|
|
if (!container) return;
|
|
|
|
container.addEventListener('scroll', this.handleScroll);
|
|
},
|
|
|
|
handleScroll() {
|
|
const container = this.$refs.messagesContainer;
|
|
if (!container) return;
|
|
|
|
const threshold = 100; // pixels from bottom
|
|
const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
|
|
|
|
this.isAtBottom = isNearBottom;
|
|
|
|
// Load more messages when scrolled to top
|
|
if (container.scrollTop === 0) {
|
|
this.$emit('load-more');
|
|
}
|
|
},
|
|
|
|
|
|
handleImageLoaded() {
|
|
// Auto-scroll when images load to maintain position
|
|
if (this.isAtBottom) {
|
|
this.$nextTick(() => this.scrollToBottom());
|
|
}
|
|
},
|
|
|
|
searchMessages(query) {
|
|
// Simple message search
|
|
if (!query.trim()) return this.messages;
|
|
|
|
const searchTerm = query.toLowerCase();
|
|
return this.messages.filter(message =>
|
|
message.content &&
|
|
message.content.toLowerCase().includes(searchTerm)
|
|
);
|
|
},
|
|
|
|
},
|
|
beforeUnmount() {
|
|
// Cleanup scroll listener
|
|
const container = this.$refs.messagesContainer;
|
|
if (container) {
|
|
container.removeEventListener('scroll', this.handleScroll);
|
|
}
|
|
|
|
// Cleanup language change listener
|
|
if (this.languageChangeHandler) {
|
|
document.removeEventListener('language-changed', this.languageChangeHandler);
|
|
}
|
|
},
|
|
template: `
|
|
<div class="message-history-container">
|
|
<!-- Messages container -->
|
|
<div class="chat-messages" ref="messagesContainer">
|
|
<!-- Loading indicator for load more -->
|
|
<div v-if="$slots.loading" class="load-more-indicator">
|
|
<slot name="loading"></slot>
|
|
</div>
|
|
|
|
<!-- Empty state -->
|
|
<div v-if="messages.length === 0" class="empty-state">
|
|
<div class="empty-icon">💬</div>
|
|
<div class="empty-text">Nog geen berichten</div>
|
|
<div class="empty-subtext">Start een gesprek door een bericht te typen!</div>
|
|
</div>
|
|
|
|
<!-- Message list -->
|
|
<template v-else>
|
|
<!-- Messages -->
|
|
<template v-for="(message, index) in messages" :key="message.id">
|
|
<!-- The actual message -->
|
|
<chat-message
|
|
:message="message"
|
|
:is-submitting-form="isSubmittingForm"
|
|
:api-prefix="apiPrefix"
|
|
@image-loaded="handleImageLoaded"
|
|
@specialist-complete="$emit('specialist-complete', $event)"
|
|
@specialist-error="$emit('specialist-error', $event)"
|
|
></chat-message>
|
|
</template>
|
|
</template>
|
|
|
|
<!-- Typing indicator -->
|
|
<typing-indicator v-if="isTyping"></typing-indicator>
|
|
</div>
|
|
</div>
|
|
`
|
|
}; |