count basado en datos en memoria, ya no cuenta de manera automatica. metadatosCard puede cargar los datos de la tabla

This commit is contained in:
2025-09-29 22:37:25 -06:00
parent c531a745fe
commit ab920c355a
20 changed files with 300 additions and 106 deletions

View File

@@ -0,0 +1,162 @@
<template>
<UCard class="brand-card border border-transparent">
<template #header>
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold brand-section-title">Tabla {{ metadata.table }}</h2>
<span class="brand-badge inline-flex items-center gap-1 rounded-full px-3 py-1 text-xs font-semibold tracking-wide">
{{ formatNumber(recordCount) }} registros en memoria
</span>
</div>
<p v-if="metadata.description" class="text-sm text-[var(--brand-text-muted)]">
{{ metadata.description }}
</p>
</div>
</template>
<dl class="grid grid-cols-2 gap-3 text-sm text-[var(--brand-text-muted)]">
<div>
<dt class="uppercase tracking-wide text-xs">Clave primaria</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ metadata.primaryKey || '—' }}</dd>
</div>
<div>
<dt class="uppercase tracking-wide text-xs">Tamaño aprox.</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ formatSize(metadata.approxSizeBytes) }}</dd>
</div>
<div>
<dt class="uppercase tracking-wide text-xs">Creación desde</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ formatDate(metadata.createdAtRange?.from) }}</dd>
</div>
<div>
<dt class="uppercase tracking-wide text-xs">Creación hasta</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ formatDate(metadata.createdAtRange?.to) }}</dd>
</div>
</dl>
<template #footer>
<div class="flex flex-col gap-3">
<div class="brand-divider pt-3 text-xs text-[var(--brand-text-muted)]">
Columnas detectadas ({{ metadata.columns?.length || 0 }}): {{ (metadata.columns || []).join(', ') || 'Ninguna' }}
</div>
<div class="flex items-center justify-between gap-3">
<div class="flex flex-col gap-1">
<span class="text-xs text-[var(--brand-text-muted)]">
{{ tableStore ? 'Última carga: ' + tableStore.formattedLastUpdated : 'No hay datos cargados' }}
</span>
<span v-if="tableStore?.isStale" class="text-xs text-yellow-400">
Los datos pueden estar desactualizados
</span>
</div>
<UButton
:loading="tableStore?.isLoading"
:ui="{ base: 'bg-[#c08040] text-[#1b1209] border border-[#d99a56] hover:bg-[#d99a56] hover:border-[#f0c07c]' }"
size="sm"
@click="loadData"
>
<template #leading>
<UIcon name="i-lucide-refresh-cw" :class="{ 'animate-spin': tableStore?.isLoading }" />
</template>
Cargar datos
</UButton>
</div>
</div>
</template>
</UCard>
</template>
<script setup lang="ts">
import { useTableDataStore } from '~/stores/tableDataFactory'
interface MetadataProps {
metadata: {
name: string
table: string
primaryKey?: string
rowCount?: number
approxSizeBytes?: number | null
columns?: string[]
createdAtRange?: {
from: string | null
to: string | null
}
sampleRow?: any
lastRefreshed?: string
description?: string
}
}
const props = defineProps<MetadataProps>()
const { $getTableStore } = useNuxtApp()
// Get the table store for this specific datasource (using name, not table)
const tableStore = computed(() => {
if (typeof $getTableStore === 'function') {
return $getTableStore(props.metadata.name)
}
return useTableDataStore(props.metadata.name)
})
// Calculate record count from in-memory data
const recordCount = computed(() => {
return tableStore.value?.recordCount || 0
})
async function loadData() {
const store = tableStore.value
if (store) {
if (!store.hasData) {
// If no data, initialize (which loads from cache or fetches)
await store.initialize()
} else {
// If already has data, refresh it
await store.refreshData()
}
}
}
function formatSize(bytes: number | null | undefined): string {
if (!bytes) {
return 'No disponible'
}
if (bytes < 1024) {
return `${bytes} B`
}
const units = ['KB', 'MB', 'GB', 'TB']
let size = bytes / 1024
let unitIndex = 0
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex += 1
}
return `${size.toFixed(1)} ${units[unitIndex]}`
}
function formatDate(value: string | null | undefined): string {
if (!value) {
return '—'
}
const date = new Date(value)
if (Number.isNaN(date.getTime())) {
return value
}
return date.toLocaleString('es-ES', {
year: 'numeric',
month: 'short',
day: 'numeric'
})
}
function formatNumber(value: number): string {
return new Intl.NumberFormat('es-ES').format(value)
}
</script>