- 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.
This commit is contained in:
132
eveai_chat_client/static/js/components/ChatInput.js
Normal file
132
eveai_chat_client/static/js/components/ChatInput.js
Normal file
@@ -0,0 +1,132 @@
|
||||
// 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>
|
||||
`
|
||||
};
|
||||
Reference in New Issue
Block a user