Files
planilla/ui/src/components/chat/CanvasChat.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>