Replace chat page with floating widget
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
import { watchEffect, computed } from 'vue' // Added computed
|
import { watchEffect, computed } from 'vue' // Added computed
|
||||||
import TopBar from '@/components/ui/TopBar.vue'
|
import TopBar from '@/components/ui/TopBar.vue'
|
||||||
import NavBar from '@/components/ui/NavBar.vue'
|
import NavBar from '@/components/ui/NavBar.vue'
|
||||||
|
import FloatingChat from '@/components/chat/FloatingChat.vue'
|
||||||
import { useUi } from '@/stores/useUi'
|
import { useUi } from '@/stores/useUi'
|
||||||
|
|
||||||
const ui = useUi()
|
const ui = useUi()
|
||||||
@@ -71,6 +72,7 @@ const transitionDurationStyle = computed(() => {
|
|||||||
]" :style="transitionDurationStyle">
|
]" :style="transitionDurationStyle">
|
||||||
<!-- NavBar fija -->
|
<!-- NavBar fija -->
|
||||||
<NavBar />
|
<NavBar />
|
||||||
|
<FloatingChat />
|
||||||
|
|
||||||
<!-- contenido principal -->
|
<!-- contenido principal -->
|
||||||
<main class="min-h-[calc(100vh-56px)] flex flex-col overflow-hidden">
|
<main class="min-h-[calc(100vh-56px)] flex flex-col overflow-hidden">
|
||||||
|
|||||||
69
ui/src/components/chat/FloatingChat.vue
Normal file
69
ui/src/components/chat/FloatingChat.vue
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import CanvasChat from './CanvasChat.vue'
|
||||||
|
|
||||||
|
const open = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<button v-if="!open" @click="open = true" class="chat-fab" aria-label="Abrir chat">
|
||||||
|
💬
|
||||||
|
</button>
|
||||||
|
<transition name="fade">
|
||||||
|
<div v-if="open" class="chat-window">
|
||||||
|
<div class="chat-header">
|
||||||
|
<button @click="open = false" class="close-btn" aria-label="Cerrar chat">✖</button>
|
||||||
|
</div>
|
||||||
|
<CanvasChat class="flex-1 min-h-0" />
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.chat-fab {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
color: white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
|
||||||
|
z-index: 60;
|
||||||
|
}
|
||||||
|
.chat-window {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
width: 24rem; /* 384px */
|
||||||
|
height: 32rem; /* 512px */
|
||||||
|
background-color: var(--background-color);
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
z-index: 60;
|
||||||
|
}
|
||||||
|
.chat-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 0.25rem;
|
||||||
|
}
|
||||||
|
.close-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
.fade-enter-active, .fade-leave-active {
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
.fade-enter-from, .fade-leave-to { opacity: 0; }
|
||||||
|
</style>
|
||||||
@@ -9,7 +9,6 @@ const realtime = useRealtimeStore()
|
|||||||
|
|
||||||
// enlaces de la app
|
// enlaces de la app
|
||||||
const links = [
|
const links = [
|
||||||
{ to: '/', label: 'Chat', icon: '💬' },
|
|
||||||
{ to: '/empleados', label: 'Empleados', icon: '👥' },
|
{ to: '/empleados', label: 'Empleados', icon: '👥' },
|
||||||
{ to: '/tareas', label: 'Tareas', icon: '📋' },
|
{ to: '/tareas', label: 'Tareas', icon: '📋' },
|
||||||
{ to: '/planillas', label: 'Planillas', icon: '📂' },
|
{ to: '/planillas', label: 'Planillas', icon: '📂' },
|
||||||
@@ -38,7 +37,7 @@ const accentColorForPath = (path) => {
|
|||||||
if (path.startsWith('/asistencias')) return ui.accentColorAsistencias
|
if (path.startsWith('/asistencias')) return ui.accentColorAsistencias
|
||||||
if (path.startsWith('/feed')) return ui.primaryColor
|
if (path.startsWith('/feed')) return ui.primaryColor
|
||||||
if (path.startsWith('/config')) return ui.accentColorConfiguracion
|
if (path.startsWith('/config')) return ui.accentColorConfiguracion
|
||||||
return ui.accentColorChat
|
return ui.primaryColor
|
||||||
}
|
}
|
||||||
|
|
||||||
const tableForPath = (path) => {
|
const tableForPath = (path) => {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { createRouter, createMemoryHistory , createWebHashHistory} from 'vue-router'
|
import { createRouter, createMemoryHistory , createWebHashHistory} from 'vue-router'
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
// Chat principal y config
|
// Configuración
|
||||||
{ path: '/', name: 'chat', component: () => import('@/views/ChatView.vue') },
|
{ path: '/', redirect: '/empleados' },
|
||||||
{ path: '/config', name: 'settings', component: () => import('@/views/SettingsView.vue') },
|
{ path: '/config', name: 'settings', component: () => import('@/views/SettingsView.vue') },
|
||||||
|
|
||||||
// ────── Empleados ──────
|
// ────── Empleados ──────
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
/* Vista raíz “/” → muestra el chat estilo ChatGPT */
|
|
||||||
import CanvasChat from '@/components/chat/CanvasChat.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="chat-view-container flex flex-col h-full">
|
|
||||||
<header class="page-header">
|
|
||||||
<h1>Chat</h1>
|
|
||||||
</header>
|
|
||||||
<CanvasChat class="flex-1 min-h-0" /> <!-- Added min-h-0 -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.chat-view-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--background-color-chat, #F0F0F0); /* Fallback to store default */
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between; /* Consistent with other headers, even if no button on right */
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 25px; /* Consistent with PlanillasIndex */
|
|
||||||
padding: 10px 20px; /* Provides padding for the header itself */
|
|
||||||
border-bottom: 1px solid #eee; /* Consistent with PlanillasIndex */
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-header h1 {
|
|
||||||
color: var(--accent-color-chat, #0D9488); /* Fallback to store default */
|
|
||||||
font-size: 2.2em; /* Consistent with PlanillasIndex */
|
|
||||||
font-weight: 600; /* Consistent with PlanillasIndex */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CanvasChat is expected to manage its own internal padding and scrolling */
|
|
||||||
</style>
|
|
||||||
Reference in New Issue
Block a user