Files
eveAI/eveai_chat_client/static/js/components/ChatInput.js
Josako 5f1a5711f6 - Build of the Chat Client using Vue.js
- Accompanying css
- Views to serve the Chat Client
- first test version of the TRACIE_SELECTION_SPECIALIST
- ESS Implemented.
2025-06-12 18:21:51 +02:00

132 lines
3.9 KiB
JavaScript

// static/js/components/ChatInput.js
export const ChatInput = {
name: 'ChatInput',
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
},
},
emits: ['send-message', 'update-message'],
data() {
return {
localMessage: this.currentMessage,
};
},
computed: {
characterCount() {
return this.localMessage.length;
},
isOverLimit() {
return this.characterCount > this.maxLength;
},
canSend() {
return this.localMessage.trim() &&
!this.isLoading &&
!this.isOverLimit;
}
},
watch: {
currentMessage(newVal) {
this.localMessage = newVal;
},
localMessage(newVal) {
this.$emit('update-message', newVal);
this.autoResize();
}
},
mounted() {
this.autoResize();
},
methods: {
handleKeydown(event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
this.sendMessage();
} else if (event.key === 'Escape') {
this.localMessage = '';
}
},
sendMessage() {
if (this.canSend) {
this.$emit('send-message');
}
},
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();
}
},
template: `
<div class="chat-input-container">
<div class="chat-input">
<!-- Main input area -->
<div class="input-main">
<textarea
ref="messageInput"
v-model="localMessage"
@keydown="handleKeydown"
:placeholder="placeholder"
rows="1"
:disabled="isLoading"
:maxlength="maxLength"
class="message-input"
:class="{ 'over-limit': isOverLimit }"
></textarea>
<!-- Character counter -->
<div v-if="maxLength" class="character-counter" :class="{ 'over-limit': isOverLimit }">
{{ characterCount }}/{{ maxLength }}
</div>
</div>
<!-- Input actions -->
<div class="input-actions">
<!-- Send button -->
<button
@click="sendMessage"
class="send-btn"
:disabled="!canSend"
:title="isOverLimit ? 'Bericht te lang' : 'Bericht verzenden'"
>
<span v-if="isLoading" class="loading-spinner">⏳</span>
<svg v-else width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
</svg>
</button>
</div>
</div>
</div>
`
};