preparando el deploy
Some checks failed
deploy-analiticaNucleo / deploy (push) Failing after 2s

This commit is contained in:
2025-10-05 12:13:32 -06:00
parent 053501a16d
commit 2b252d798b
15 changed files with 170 additions and 34 deletions

View File

@@ -26,11 +26,11 @@
<div class="grid grid-cols-2 gap-4 flex-1">
<div>
<label class="text-xs text-[var(--brand-text-muted)]">Fecha desde</label>
<UInput :model-value="fechaDesde" type="date" @input="(e) => onManualDateChange('desde', e)" />
<UInput :model-value="fechaDesde" type="date" @input="(e: Event) => onManualDateChange('desde', e)" />
</div>
<div>
<label class="text-xs text-[var(--brand-text-muted)]">Fecha hasta</label>
<UInput :model-value="fechaHasta" type="date" @input="(e) => onManualDateChange('hasta', e)" />
<UInput :model-value="fechaHasta" type="date" @input="(e: Event) => onManualDateChange('hasta', e)" />
</div>
</div>
@@ -138,7 +138,7 @@ function setToday() {
// Watch para aplicar el preset cuando cambia (incluyendo el valor inicial)
watch(() => props.selectedPreset, (newPreset) => {
if (newPreset && newPreset !== 'custom' && newPreset !== '') {
if (newPreset !== '' && newPreset !== 'custom') {
selectPreset(newPreset)
}
}, { immediate: true })

View File

@@ -6,7 +6,7 @@
compact && tableStore?.isStale ? 'bg-yellow-500/10 border-l-4 !border-l-yellow-500' : ''
]"
@click="toggleCompact"
:ui="compact ? { body: { padding: '0' }, header: { padding: 'px-3 py-2' }, footer: { padding: '0' } } : {}"
:ui="compact ? { body: 'p-0', header: 'px-3 py-2', footer: 'p-0' } : {}"
>
<template v-if="compact" #header>
<div class="flex items-center justify-between gap-3">
@@ -38,7 +38,7 @@
:loading="isLoadingLatest"
:disabled="isLoadingAll"
:ui="{ base: tableStore?.isStale ? 'bg-yellow-500 text-black border-0 hover:bg-yellow-400 font-bold' : 'bg-[#c08040] text-[#1b1209] border-0 hover:bg-[#d99a56]' }"
size="2xs"
size="xs"
icon="i-lucide-clock"
@click.stop="loadLatestData"
:class="{ 'animate-spin': isLoadingLatest, 'animate-bounce': tableStore?.isStale && !isLoadingLatest }"
@@ -48,7 +48,7 @@
:loading="isLoadingAll"
:disabled="isLoadingLatest"
:ui="{ base: tableStore?.isStale ? 'bg-yellow-500 text-black border-0 hover:bg-yellow-400 font-bold' : 'bg-[#c08040] text-[#1b1209] border-0 hover:bg-[#d99a56]' }"
size="2xs"
size="xs"
icon="i-lucide-database"
@click.stop="loadAllData"
:class="{ 'animate-spin': isLoadingAll }"
@@ -58,7 +58,7 @@
icon="i-lucide-chevron-down"
color="neutral"
variant="ghost"
size="2xs"
size="xs"
@click.stop="toggleCompact"
/>
</div>

View File

@@ -105,10 +105,10 @@ defineEmits<{
// Compute initials from name
const clienteInitials = computed(() => {
const names = props.cliente.name.trim().split(' ')
if (names.length >= 2) {
if (names.length >= 2 && names[0] && names[1]) {
return (names[0][0] + names[1][0]).toUpperCase()
}
return names[0].substring(0, 2).toUpperCase()
return names[0]?.substring(0, 2).toUpperCase() || 'XX'
})
// Format date helper

View File

@@ -228,7 +228,7 @@
class="text-[10px] text-blue-400 font-medium"
title="Acumulado hasta la fecha actual"
>
{{ formatTotal(cosecha.totalALaFecha) }}
{{ formatTotal(cosecha.totalALaFecha || 0) }}
</div>
<div
v-else
@@ -344,14 +344,14 @@
class="text-[10px] text-blue-400 font-medium"
title="Acumulado hasta la fecha actual"
>
{{ formatTotal(cosecha.totalALaFecha) }}
{{ formatTotal(cosecha.totalALaFecha || 0) }}
</div>
<div
v-else
class="text-[10px] text-gray-500 italic"
title="Sin datos hasta la fecha actual"
>
{{ formatTotal(cosecha.totalALaFecha) }}
{{ formatTotal(cosecha.totalALaFecha || 0) }}
</div>
</div>
</div>
@@ -853,7 +853,7 @@ function getDiaDelAnio(mes: number, dia: number, esBisiesto: boolean): number {
let diaDelAnio = 0
for (let i = 0; i < mes - 1; i++) {
diaDelAnio += diasPorMes[i]
diaDelAnio += diasPorMes[i] || 0
}
diaDelAnio += dia - 1 // -1 porque empezamos en día 0
@@ -1093,7 +1093,7 @@ async function toggleFullscreen() {
try {
if (!document.fullscreenElement) {
// Entrar a pantalla completa
await cardContainer.value.$el.requestFullscreen()
await cardContainer.value.requestFullscreen()
isFullscreen.value = true
} else {
// Salir de pantalla completa
@@ -1130,7 +1130,7 @@ onMounted(() => {
document.addEventListener('fullscreenchange', handleFullscreenChange)
// Agregar listener para zoom con rueda del mouse
const container = cardContainer.value?.$el
const container = cardContainer.value
if (container) {
container.addEventListener('wheel', handleWheel, { passive: false })
}
@@ -1140,7 +1140,7 @@ onUnmounted(() => {
document.removeEventListener('fullscreenchange', handleFullscreenChange)
// Remover listener de zoom
const container = cardContainer.value?.$el
const container = cardContainer.value
if (container) {
container.removeEventListener('wheel', handleWheel)
}

View File

@@ -243,8 +243,9 @@ const maxPesoPorTipo = computed(() => {
let max = 0
datosCosechas.value.forEach(cosecha => {
tipos.forEach(tipo => {
if (cosecha.pesosPorTipo[tipo] > max) {
max = cosecha.pesosPorTipo[tipo]
const valor = cosecha.pesosPorTipo[tipo]
if (valor !== undefined && valor > max) {
max = valor
}
})
})
@@ -255,8 +256,9 @@ const maxCantidadPorTipo = computed(() => {
let max = 0
datosCosechas.value.forEach(cosecha => {
tipos.forEach(tipo => {
if (cosecha.cantidadPorTipo[tipo] > max) {
max = cosecha.cantidadPorTipo[tipo]
const valor = cosecha.cantidadPorTipo[tipo]
if (valor !== undefined && valor > max) {
max = valor
}
})
})
@@ -312,8 +314,8 @@ function getCosechaColor(cosechaIdOrIndex: string | number): string {
return colores[index % colores.length]
}
// Si es un número, buscar el ID de la cosecha en datosPorTipo
const cosecha = datosPorTipo.value[cosechaIdOrIndex]
// Si es un número, buscar el ID de la cosecha en datosCosechas
const cosecha = datosCosechas.value[cosechaIdOrIndex]
if (cosecha?.id) {
const index = cosechaColorMap[cosecha.id] ?? cosechaIdOrIndex
return colores[index % colores.length]

View File

@@ -183,12 +183,23 @@
</template>
<script setup lang="ts">
import type { Cliente } from '~/composables/useClienteSelector'
interface Cliente {
id: number
name: string
cedula?: number
ubicacion?: string
telefono?: string
}
type PresetValue =
| '' | 'custom' | 'hoy' | 'semana' | 'mes' | 'ytd'
| 'cosecha-20-21' | 'cosecha-21-22' | 'cosecha-22-23'
| 'cosecha-23-24' | 'cosecha-24-25' | 'cosecha-25-26'
interface Props {
clientes: Cliente[]
selectedClienteIds: number[]
selectedPreset: string
selectedPreset: PresetValue
fechaDesde: string | null
fechaHasta: string | null
selectedTipos: string[]
@@ -207,7 +218,7 @@ const props = defineProps<Props>()
const emit = defineEmits<{
'update:selectedClienteIds': [value: number[]]
'update:selectedPreset': [value: string]
'update:selectedPreset': [value: PresetValue]
'update:fechaDesde': [value: string | null]
'update:fechaHasta': [value: string | null]
'update:selectedTipos': [value: string[]]

View File

@@ -260,8 +260,9 @@ function getPresetLabel(): string {
'cosecha-25-26': 'Cosecha 25-26'
}
if (props.selectedPreset && props.selectedPreset !== 'custom' && presetLabels[props.selectedPreset]) {
return presetLabels[props.selectedPreset]
const label = props.selectedPreset && props.selectedPreset !== 'custom' ? presetLabels[props.selectedPreset] : undefined
if (label) {
return label
}
// Si es personalizado, mostrar las fechas

View File

@@ -15,7 +15,7 @@
v-for="tipo in tipos"
:key="tipo.value"
:model-value="tiposSeleccionados.includes(tipo.value)"
@update:model-value="(checked) => toggleTipo(tipo.value, checked)"
@update:model-value="(checked: boolean) => toggleTipo(tipo.value, checked)"
:label="getTipoLabel(tipo)"
:disabled="isTipoDisabled(tipo.value)"
size="xs"

View File

@@ -159,10 +159,10 @@ export function createTableDataStore<T = Record<string, unknown>>(
})
if (response && typeof response === 'object' && 'records' in response) {
const dataset = response as { records?: T[] }
const dataset = response as { records?: any[] }
this.data = Array.isArray(dataset.records) ? dataset.records : []
} else if (Array.isArray(response)) {
this.data = response as T[]
this.data = response
} else {
this.data = []
}
@@ -322,7 +322,7 @@ export function createTableDataStore<T = Record<string, unknown>>(
if (response.records && response.records.length > 0) {
console.log(`[${tableName}] loadAllDataInBatches: Got ${response.records.length} records`)
this.data.push(...(response.records as T[]))
this.data.push(...response.records)
totalFetched += response.records.length
console.log(`[${tableName}] loadAllDataInBatches: Total fetched so far: ${totalFetched}, data.length: ${this.data.length}`)
@@ -442,7 +442,7 @@ export function createTableDataStore<T = Record<string, unknown>>(
console.log(`[${tableName}] loadLatestDataInBatches: ${newRecords.length} new records after filtering`)
if (newRecords.length > 0) {
this.data.unshift(...(newRecords as T[]))
this.data.unshift(...newRecords)
newRecordsCount += newRecords.length
console.log(`[${tableName}] loadLatestDataInBatches: Total new records: ${newRecordsCount}, data.length: ${this.data.length}`)
}