Improve realtime feed
This commit is contained in:
@@ -3,7 +3,28 @@
|
||||
<p class="text-xs text-gray-500 mb-1">
|
||||
{{ event.operation }} · {{ event.table }} • {{ formatTimestamp(event.receivedAt) }}
|
||||
</p>
|
||||
<component v-if="component" :is="component" v-bind="componentProps" />
|
||||
<template v-if="event.operation === 'UPDATE'">
|
||||
<div class="flex items-center space-x-2">
|
||||
<component
|
||||
v-if="component"
|
||||
:is="component"
|
||||
v-bind="componentPropsOld"
|
||||
class="old-card opacity-70"
|
||||
/>
|
||||
<span class="text-2xl">→</span>
|
||||
<component
|
||||
v-if="component"
|
||||
:is="component"
|
||||
v-bind="componentPropsNew"
|
||||
class="new-card"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<component
|
||||
v-else-if="component"
|
||||
:is="component"
|
||||
v-bind="componentProps"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -31,22 +52,28 @@ const itemData = computed(() =>
|
||||
props.event.operation === 'DELETE' ? props.event.old : props.event.new
|
||||
)
|
||||
|
||||
const componentProps = computed(() => {
|
||||
const data = itemData.value || {}
|
||||
const buildProps = (data) => {
|
||||
switch (props.event.table) {
|
||||
case 'Planilla':
|
||||
return { planilla: data }
|
||||
return { planilla: data || {} }
|
||||
case 'Cliente':
|
||||
return { employee: data }
|
||||
return { employee: data || {} }
|
||||
case 'TareaRealizada':
|
||||
return { tarea: data }
|
||||
return { tarea: data || {} }
|
||||
case 'Asistencia':
|
||||
return { asistencia: data }
|
||||
return { asistencia: data || {} }
|
||||
default:
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
const componentProps = computed(() => {
|
||||
return buildProps(itemData.value)
|
||||
})
|
||||
|
||||
const componentPropsOld = computed(() => buildProps(props.event.old))
|
||||
const componentPropsNew = computed(() => buildProps(props.event.new))
|
||||
|
||||
const formatTimestamp = (ts) => {
|
||||
if (!ts) return ''
|
||||
return new Date(ts).toLocaleString('es-HN', { hour12: true })
|
||||
@@ -57,4 +84,9 @@ const formatTimestamp = (ts) => {
|
||||
.realtime-event {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.old-card,
|
||||
.new-card {
|
||||
flex: 1 1 0%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,16 +16,16 @@ onMounted(() => {
|
||||
<h1>Feed en Tiempo Real</h1>
|
||||
</header>
|
||||
|
||||
<div class="feed-list overflow-auto pr-2" style="max-height: calc(100vh - 160px);">
|
||||
<transition-group name="feed" tag="div" class="feed-list overflow-auto pr-2" style="max-height: calc(100vh - 160px);">
|
||||
<RealtimeEventCard
|
||||
v-for="(ev, idx) in realtime.events"
|
||||
:key="idx"
|
||||
:key="ev.receivedAt + idx"
|
||||
:event="ev"
|
||||
/>
|
||||
<div v-if="realtime.events.length === 0" class="text-center text-gray-500 mt-4">
|
||||
No hay eventos aún.
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -50,4 +50,17 @@ onMounted(() => {
|
||||
font-size: 2.2em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.feed-enter-active,
|
||||
.feed-leave-active {
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
.feed-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
.feed-enter-to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user