- Accompanying css - Views to serve the Chat Client - first test version of the TRACIE_SELECTION_SPECIALIST - ESS Implemented.
132 lines
3.9 KiB
JavaScript
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>
|
|
`
|
|
}; |