From 5dae4a20d340cd251205220015d81842e2dca3cf Mon Sep 17 00:00:00 2001
From: josedario87 <71241187+josedario87@users.noreply.github.com>
Date: Mon, 9 Jun 2025 19:40:29 -0600
Subject: [PATCH 1/4] feat(ui): add realtime feed view
---
README.md | 2 +
ui/README.md | 4 ++
.../components/realtime/RealtimeEventCard.vue | 60 +++++++++++++++++++
ui/src/components/ui/NavBar.vue | 2 +
ui/src/router/index.js | 3 +
ui/src/stores/useRealtime.js | 16 +++--
ui/src/views/RealtimeFeedView.vue | 53 ++++++++++++++++
7 files changed, 134 insertions(+), 6 deletions(-)
create mode 100644 ui/src/components/realtime/RealtimeEventCard.vue
create mode 100644 ui/src/views/RealtimeFeedView.vue
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 @@
+
+
+
+ Feed en Tiempo Real
+
{{ event.operation }} · {{ event.table }} • {{ formatTimestamp(event.receivedAt) }}
@@ -78,11 +78,19 @@ const formatTimestamp = (ts) => { if (!ts) return '' return new Date(ts).toLocaleString('es-HN', { hour12: true }) } + +const eventBgClass = computed(() => { + if (props.event.operation === 'DELETE') return 'bg-red-100/40' + if (props.event.operation === 'INSERT') return 'bg-green-100/40' + return '' +}) From 6f5490ed4df27f35be95f181b8619361afe232c3 Mon Sep 17 00:00:00 2001 From: josedario87+
+ {{ event.operation }} · {{ event.table }} • {{ formatTimestamp(event.receivedAt) }}
@@ -10,6 +11,7 @@ :is="component" v-bind="componentPropsOld" class="old-card opacity-70" + style="max-width: 350px;" /> →