avances poderosos en ui
Some checks failed
build-and-deploy / filter (push) Successful in 4s
build-and-deploy / build (push) Failing after 19s
build-and-deploy / deploy (push) Has been skipped

This commit is contained in:
2025-05-25 08:21:57 -06:00
parent 55645d0cdd
commit 421ff236ae
40 changed files with 1669 additions and 425 deletions

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,83 @@
<script setup>
import { ref, nextTick, onMounted, watch } from 'vue'
import { useChat } from '@/stores/useChat'
const chat = useChat()
const msg = ref('')
const list = ref(null)
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 bg-gray-50">
<!-- 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' ? 'bg-teal-600 text-white' : 'bg-white text-gray-900'">
{{ 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 bg-white p-4 flex gap-2">
<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 focus:ring-teal-500 custom-scroll"
/>
<button type="submit" class="px-4 py-2 rounded-lg bg-teal-600 text-white hover:bg-teal-700 transition">
</button>
</form>
</div>
</template>
<style scoped>
.custom-scroll::-webkit-scrollbar { width: 8px; }
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
.custom-scroll::-webkit-scrollbar-thumb { background-color: rgba(13,148,136,.35); border-radius: 4px; }
.custom-scroll:hover::-webkit-scrollbar-thumb { background-color: rgba(13,148,136,.7); }
.custom-scroll { scrollbar-width: thin; scrollbar-color: rgba(13,148,136,.6) transparent; }
</style>

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,71 @@
<script setup>
import { ref, watch, computed } from 'vue'
import { useRoute } from 'vue-router'
import { useUi } from '@/stores/useUi'
const ui = useUi()
// enlaces de la app
const links = [
{ to: '/', label: 'Chat', icon: '💬' },
{ to: '/empleados', label: 'Empleados', icon: '👥' },
{ to: '/tareas', label: 'Tareas', icon: '📋' },
{ to: '/planillas', label: 'Planillas', icon: '📂' },
{ to: '/asistencias', label: 'Asistencias', icon: '⏰' },
{ to: '/config', label: 'Config', icon: '⚙️' },
]
const route = useRoute()
const activePath = ref(route.path)
watch(route, v => (activePath.value = v.path))
// clases dinámicas p/ mostrar / ocultar barra
const sidebarClasses = computed(() => ui.sidebarOpen ? 'translate-x-0' : '-translate-x-full')
</script>
<template>
<!-- backdrop en mobile -->
<div v-if="ui.sidebarOpen" class="fixed inset-0 bg-black/40 md:hidden" @click="ui.closeSidebar" />
<!-- barra lateral -->
<aside
:class="['fixed left-0 top-0 md:top-14 h-screen w-60 bg-white dark:bg-zinc-900 border-r border-gray-200 dark:border-zinc-800 flex flex-col select-none z-50 transform transition-transform duration-200 ease-in-out', sidebarClasses]">
<!-- encabezado dentro de sidebar -->
<div class="flex items-center justify-between px-4 py-4 md:px-5 md:py-4 border-b border-gray-200 dark:border-zinc-800 md:border-none">
<span class="text-lg font-semibold text-teal-600 dark:text-teal-400 md:hidden">Núcleo</span>
<button class="h-8 w-8 inline-flex items-center justify-center text-gray-500 hover:text-teal-600" @click="ui.toggleSidebar">
</button>
</div>
<!-- navegación -->
<nav class="flex-1 overflow-y-auto custom-scroll pr-1 pt-4 md:pt-0">
<ul class="space-y-1 px-2">
<li v-for="l in links" :key="l.to">
<RouterLink
:to="l.to"
class="flex items-center gap-3 w-full px-3 py-2 rounded-md font-medium transition group"
:class="activePath.startsWith(l.to)
? 'bg-teal-600 text-white shadow'
: 'text-gray-700 dark:text-gray-100 hover:bg-teal-100 hover:text-teal-900 dark:hover:bg-zinc-800'"
@click="ui.closeSidebar()"
>
<span class="text-lg" aria-hidden="true">{{ l.icon }}</span>
<span class="truncate">{{ l.label }}</span>
</RouterLink>
</li>
</ul>
</nav>
</aside>
</template>
<style scoped>
ul { list-style: none; padding-left: 0; }
.custom-scroll::-webkit-scrollbar { width: 8px; }
.custom-scroll::-webkit-scrollbar-track { background: transparent; }
.custom-scroll::-webkit-scrollbar-thumb { background-color: rgba(13,148,136,.4); border-radius: 4px; }
.custom-scroll:hover::-webkit-scrollbar-thumb { background-color: rgba(13,148,136,.7); }
.custom-scroll { scrollbar-width: thin; scrollbar-color: rgba(13,148,136,.6) transparent; }
</style>

View File

View File

@@ -0,0 +1,23 @@
<script setup>
import { useUi } from '@/stores/useUi'
const ui = useUi()
</script>
<template>
<!-- barra superior fija -->
<header class="fixed top-0 left-0 right-0 h-14 bg-white dark:bg-zinc-900 border-b border-gray-200 dark:border-zinc-800 flex items-center justify-between px-4 md:px-6 z-50 shadow-sm">
<!-- título -->
<h1 class="text-lg font-semibold tracking-wide text-teal-600 dark:text-teal-400 select-none">Núcleo</h1>
<!-- botón hamburguesa (visible solo en mobile) -->
<button
@click="ui.toggleSidebar"
class="inline-flex items-center justify-center h-9 w-9 rounded-md bg-teal-600 text-white hover:bg-teal-700 transition ">
&#9776;
</button>
</header>
</template>
<style scoped>
/* sin estilos extra */
</style>