131 lines
4.6 KiB
Vue
131 lines
4.6 KiB
Vue
<script setup>
|
|
import { ref, nextTick, onMounted, watch, computed } from 'vue'
|
|
import { useChat } from '@/stores/useChat'
|
|
import { useUi } from '@/stores/useUi'
|
|
|
|
const chat = useChat()
|
|
const ui = useUi()
|
|
const msg = ref('')
|
|
const list = ref(null)
|
|
|
|
const chatStyleVariables = computed(() => ({
|
|
'--chat-agent-message-color': ui.chatAgentMessageColor,
|
|
'--chat-own-message-color': ui.chatOwnMessageColor,
|
|
'--chat-input-box-color': ui.chatInputBoxColor,
|
|
'--chat-accent-color': ui.chatAccentColor,
|
|
'--chat-background-color': ui.chatBackgroundColor,
|
|
'--chat-font-color': ui.chatFontColor,
|
|
'--chat-font-family': ui.chatFontFamily || 'inherit', // Fallback to inherit if empty
|
|
'--chat-font-size': ui.chatFontSize ? `${ui.chatFontSize}px` : 'inherit', // Fallback to inherit
|
|
}))
|
|
|
|
function scrollBottom () {
|
|
nextTick(() => list.value?.scrollTo({ top: list.value.scrollHeight, behavior: 'smooth' }))
|
|
}
|
|
|
|
function send () {
|
|
const t = msg.value.trim()
|
|
if (!t) return
|
|
|
|
if (t.startsWith('/')) chat.run(t.slice(1))
|
|
else chat.add({ type: 'text', owner: 'yo', text: t })
|
|
|
|
msg.value = ''
|
|
scrollBottom()
|
|
}
|
|
|
|
function handleKey (e) {
|
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
e.preventDefault()
|
|
send()
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!chat.items.length) {
|
|
chat.add({ type: 'text', owner: 'bot', text: '¡Hola! Probá /empleados, /tareas, etc.' })
|
|
}
|
|
scrollBottom()
|
|
})
|
|
|
|
watch(() => chat.items.length, scrollBottom)
|
|
</script>
|
|
|
|
<template>
|
|
<!-- se adapta al contenedor flex, sin superponer la sidebar -->
|
|
<div class="flex flex-col flex-1 min-h-0" :style="chatStyleVariables" style="background-color: var(--chat-background-color);">
|
|
<!-- historial -->
|
|
<div ref="list" class="flex-1 min-h-0 overflow-auto p-6 space-y-4 custom-scroll">
|
|
<template v-for="(m,i) in chat.items" :key="i">
|
|
<!-- mensaje de texto -->
|
|
<div :class="m.owner==='yo' ? 'flex justify-end' : 'flex justify-start'" v-if="m.type==='text'">
|
|
<div
|
|
class="max-w-lg rounded-lg px-4 py-2 shadow break-words"
|
|
:class="m.owner === 'yo' ? '' : ''"
|
|
:style="{
|
|
backgroundColor: m.owner === 'yo' ? 'var(--chat-own-message-color)' : 'var(--chat-agent-message-color)',
|
|
color: 'var(--chat-font-color)',
|
|
fontFamily: 'var(--chat-font-family)',
|
|
fontSize: 'var(--chat-font-size)'
|
|
}">
|
|
|
|
{{ m.text }}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- componente dinámico -->
|
|
<component v-else :is="m.is" v-bind="m.props" />
|
|
</template>
|
|
</div>
|
|
|
|
<!-- input -->
|
|
<form @submit.prevent="send" class="border-t p-4 flex gap-2" :style="{ backgroundColor: 'var(--chat-input-box-color)' }">
|
|
<textarea
|
|
v-model="msg"
|
|
@keydown="handleKey"
|
|
rows="1"
|
|
placeholder="Escribí un mensaje… (Enter para enviar, Shift+Enter salto)"
|
|
|
|
class="flex-1 resize-none rounded-lg border p-3 focus:outline-none focus:ring-2 custom-scroll"
|
|
:style="{
|
|
backgroundColor: 'var(--chat-input-box-color)',
|
|
borderColor: 'var(--chat-accent-color)',
|
|
'--tw-ring-color': 'var(--chat-accent-color)',
|
|
color: 'var(--chat-font-color)',
|
|
fontFamily: 'var(--chat-font-family)',
|
|
fontSize: 'var(--chat-font-size)'
|
|
}"
|
|
/>
|
|
<button type="submit" class="px-4 py-2 rounded-lg text-white transition" :style="{ backgroundColor: 'var(--chat-accent-color)' }">
|
|
➤
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.canvas-chat-root {
|
|
background-color: var(--background-color-chat, #F0F0F0); /* Fallback to store default */
|
|
}
|
|
|
|
/* Default accent color for chat if not provided by CSS variable */
|
|
:root {
|
|
--accent-color-chat-fallback: #0D9488; /* Teal-700 as a fallback */
|
|
--accent-color-chat-alpha-35-fallback: rgba(13, 148, 136, 0.35);
|
|
--accent-color-chat-alpha-70-fallback: rgba(13, 148, 136, 0.7);
|
|
--accent-color-chat-alpha-60-fallback: rgba(13, 148, 136, 0.6);
|
|
}
|
|
|
|
.custom-scroll::-webkit-scrollbar { width: 8px; }
|
|
.custom-scroll::-webkit-scrollbar-track { background: transparent; } /* Consider if track needs to adapt to --chat-background-color */
|
|
.custom-scroll::-webkit-scrollbar-thumb { background-color: var(--chat-accent-color); opacity: 0.35; border-radius: 4px; }
|
|
.custom-scroll:hover::-webkit-scrollbar-thumb { opacity: 0.7; }
|
|
/* For Firefox scrollbar, if needed, though limited styling capability compared to webkit */
|
|
.custom-scroll { scrollbar-width: thin; scrollbar-color: var(--chat-accent-color) transparent; }
|
|
|
|
/* Override Tailwind focus ring color if it doesn't pick up the CSS variable directly */
|
|
textarea:focus {
|
|
--tw-ring-color: var(--chat-accent-color);
|
|
}
|
|
</style>
|