diff --git a/README.md b/README.md
index 9ed4356..07d1427 100644
--- a/README.md
+++ b/README.md
@@ -147,6 +147,8 @@ source.onmessage = (e) => {
};
```
+La interfaz incluye una vista **Feed** accesible desde la barra lateral. Allí se muestran en tiempo real las tarjetas de cada módulo conforme llegan estos eventos.
+
#### Card Animation
The data cards implemented in `ui/src/components/ui/NucleoDataCard.vue` now feature a subtle growing animation when hovered over. This animation is implemented purely with CSS using keyframes and transitions defined within the component's `
diff --git a/ui/src/components/ui/NavBar.vue b/ui/src/components/ui/NavBar.vue
index 34f862b..06db6a1 100644
--- a/ui/src/components/ui/NavBar.vue
+++ b/ui/src/components/ui/NavBar.vue
@@ -12,6 +12,7 @@ const links = [
{ to: '/tareas', label: 'Tareas', icon: '📋' },
{ to: '/planillas', label: 'Planillas', icon: '📂' },
{ to: '/asistencias', label: 'Asistencias', icon: '⏰' },
+ { to: '/feed', label: 'Feed', icon: '📰' },
{ to: '/config', label: 'Config', icon: '⚙️' },
]
@@ -24,6 +25,7 @@ const accentColorForPath = (path) => {
if (path.startsWith('/tareas')) return ui.accentColorTareas
if (path.startsWith('/planillas')) return ui.accentColorPlanillas
if (path.startsWith('/asistencias')) return ui.accentColorAsistencias
+ if (path.startsWith('/feed')) return ui.primaryColor
if (path.startsWith('/config')) return ui.accentColorConfiguracion
return ui.accentColorChat
}
diff --git a/ui/src/router/index.js b/ui/src/router/index.js
index ea9a22c..d4a9628 100644
--- a/ui/src/router/index.js
+++ b/ui/src/router/index.js
@@ -25,6 +25,9 @@ const routes = [
{ path: '/asistencias/nuevo', name: 'asistencias-new', component: () => import('@/views/asistencias/AsistenciaForm.vue') },
{ path: '/asistencias/:id', name: 'asistencias-edit', component: () => import('@/views/asistencias/AsistenciaForm.vue'), props: true },
+ // ────── Feed en tiempo real ──────
+ { path: '/feed', name: 'feed', component: () => import('@/views/RealtimeFeedView.vue') },
+
// 404
{ path: '/:pathMatch(.*)*', name: 'not-found', component: () => import('@/views/NotFound.vue') }
]
diff --git a/ui/src/stores/useRealtime.js b/ui/src/stores/useRealtime.js
index a567cdf..a46edd1 100644
--- a/ui/src/stores/useRealtime.js
+++ b/ui/src/stores/useRealtime.js
@@ -7,6 +7,7 @@ import { useAsistenciasStore } from './useAsistencias'
export const useRealtimeStore = defineStore('realtime', {
state: () => ({
_sse: null,
+ events: [],
}),
actions: {
init() {
@@ -19,13 +20,16 @@ export const useRealtimeStore = defineStore('realtime', {
console.log('🟢 Conexión SSE establecida correctamente');
};
- this._sse.onmessage = (e) => {
- console.log('📩 SSE message raw:', e.data);
+ this._sse.onmessage = (e) => {
+ console.log('📩 SSE message raw:', e.data);
- try {
- const payload = JSON.parse(e.data);
- console.log('📦 Payload parseado:', payload);
- console.log('🧪 Tabla recibida:', payload.table);
+ try {
+ const payload = JSON.parse(e.data);
+ console.log('📦 Payload parseado:', payload);
+ console.log('🧪 Tabla recibida:', payload.table);
+
+ // store event for feed
+ this.events.unshift({ ...payload, receivedAt: new Date().toISOString() });
switch (payload.table) {
case 'Planilla':
diff --git a/ui/src/views/RealtimeFeedView.vue b/ui/src/views/RealtimeFeedView.vue
new file mode 100644
index 0000000..16e4fd0
--- /dev/null
+++ b/ui/src/views/RealtimeFeedView.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ No hay eventos aún.
+
+
+
+
+
+