cambio heavys
This commit is contained in:
178
nuxt4-app/app/components/informe-ingresos/MetadatosPanel.vue
Normal file
178
nuxt4-app/app/components/informe-ingresos/MetadatosPanel.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user