Files
analiticaNucleo/nuxt4-app/app/components/informe-ingresos/MetadatosPanel.vue
2025-10-01 03:11:10 -06:00

179 lines
5.1 KiB
Vue

<template>
<div class="flex flex-col gap-3">
<!-- Versión ultra compacta de MetadatosCard -->
<div v-if="ingresosMetadata" class="flex flex-col gap-3">
<!-- Header compacto -->
<div class="flex items-center justify-between pb-2 border-b border-[var(--brand-border)]">
<h3 class="text-sm font-bold text-[var(--brand-text)]">{{ ingresosMetadata.table }}</h3>
<span class="text-xs font-semibold text-[var(--brand-primary)]">
{{ formatNumber(recordCount) }}
</span>
</div>
<!-- Info grid compacto -->
<div class="grid grid-cols-2 gap-x-3 gap-y-2 text-xs">
<div>
<dt class="text-[var(--brand-text-muted)] uppercase text-[10px]">Tamaño</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ formatSize(ingresosMetadata.approxSizeBytes) }}</dd>
</div>
<div>
<dt class="text-[var(--brand-text-muted)] uppercase text-[10px]">Desde</dt>
<dd class="font-medium text-[var(--brand-text)]">{{ formatDate(ingresosMetadata.createdAtRange?.from) }}</dd>
</div>
<div class="col-span-2">
<dt class="text-[var(--brand-text-muted)] uppercase text-[10px]">Columnas ({{ ingresosMetadata.columns?.length || 0 }})</dt>
<dd class="font-medium text-[var(--brand-text)] truncate text-[10px]">
{{ (ingresosMetadata.columns || []).slice(0, 5).join(', ') }}{{ (ingresosMetadata.columns?.length || 0) > 5 ? '...' : '' }}
</dd>
</div>
</div>
<!-- Última actualización -->
<div class="text-[10px] text-[var(--brand-text-muted)] pt-2 border-t border-[var(--brand-border)]">
{{ tableStore ? tableStore.formattedLastUpdated : 'Sin datos' }}
</div>
<!-- Botones de acción compactos -->
<div class="flex gap-2">
<UButton
:loading="isLoadingLatest"
:disabled="isLoadingAll"
size="xs"
color="primary"
variant="soft"
@click="loadLatestData"
block
>
<template #leading>
<UIcon name="i-lucide-clock" class="w-3 h-3" />
</template>
Últimos
</UButton>
<UButton
:loading="isLoadingAll"
:disabled="isLoadingLatest"
size="xs"
color="primary"
variant="outline"
@click="loadAllData"
block
>
<template #leading>
<UIcon name="i-lucide-database" class="w-3 h-3" />
</template>
Todos
</UButton>
</div>
<!-- Progress bar compacto -->
<UProgress
v-if="isLoadingLatest || isLoadingAll"
:model-value="loadingProgress"
:max="100"
size="xs"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { useTableDataStore } from '~/stores/tableDataFactory'
interface Props {
ingresosMetadata: any
}
const props = defineProps<Props>()
const { $getTableStore } = useNuxtApp()
// Loading states
const isLoadingLatest = ref(false)
const isLoadingAll = ref(false)
const loadingProgress = ref(0)
// Get the table store
const tableStore = computed(() => {
if (typeof $getTableStore === 'function') {
return $getTableStore(props.ingresosMetadata.name)
}
return useTableDataStore(props.ingresosMetadata.name)
})
// Calculate record count
const recordCount = computed(() => {
return tableStore.value?.recordCount || 0
})
async function loadLatestData() {
isLoadingLatest.value = true
loadingProgress.value = 0
try {
const store = tableStore.value
if (!store) return
await store.loadLatestDataInBatches((progress) => {
loadingProgress.value = progress
})
loadingProgress.value = 100
} catch (error) {
console.error('Error loading latest data:', error)
} finally {
setTimeout(() => {
isLoadingLatest.value = false
loadingProgress.value = 0
}, 500)
}
}
async function loadAllData() {
isLoadingAll.value = true
loadingProgress.value = 0
try {
const store = tableStore.value
if (!store) return
await store.loadAllDataInBatches((progress) => {
loadingProgress.value = progress
})
loadingProgress.value = 100
} catch (error) {
console.error('Error loading all data:', error)
} finally {
setTimeout(() => {
isLoadingAll.value = false
loadingProgress.value = 0
}, 500)
}
}
function formatSize(bytes: number | null | undefined): string {
if (!bytes) return 'N/A'
if (bytes < 1024) return `${bytes} B`
const units = ['KB', 'MB', 'GB']
let size = bytes / 1024
let unitIndex = 0
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex++
}
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.toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: 'numeric' })
}
function formatNumber(value: number): string {
return new Intl.NumberFormat('es-ES').format(value)
}
</script>