Refactor: Migrar filtros de Informe Ingresos a UCheckboxGroup
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 49s

- Reemplazar checkboxes individuales por UCheckboxGroup en filtros de:
  * Ubicaciones (con scroll vertical para listas largas)
  * Tipos de Café (Uva, Mojado, Oreado, Verde)
  * Estados (Pagado, Pendiente)
  * Calidades (orientación horizontal)

- Simplificar modelo de datos:
  * Eliminar filterTipos y filterEstados (objetos con booleanos)
  * Usar directamente selectedTipos y selectedEstados (arrays)
  * Eliminar computed tiposArray y estadosArray (innecesarios)

- Beneficios:
  * Código más limpio y mantenible
  * Mejor consistencia con Nuxt UI
  * UI más compacta y profesional
  * Menos lógica de conversión de datos
This commit is contained in:
2025-10-30 13:21:18 -06:00
parent 3b0d21dd02
commit 6e4da65d63

View File

@@ -73,51 +73,58 @@
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Ubicaciones --> <!-- Ubicaciones -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Ubicaciones</label> <UCheckboxGroup
<div class="space-y-2 max-h-40 overflow-y-auto"> v-model="selectedUbicaciones"
<UCheckbox legend="Ubicaciones"
v-for="ubicacion in opcionesFiltros.ubicaciones" :items="opcionesFiltros.ubicaciones"
:key="ubicacion" color="primary"
v-model="selectedUbicaciones" variant="list"
:value="ubicacion" orientation="vertical"
:label="ubicacion" size="sm"
/> :ui="{
</div> fieldset: 'max-h-40 overflow-y-auto'
}"
/>
</div> </div>
<!-- Tipos de Café --> <!-- Tipos de Café -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Tipos de Café</label> <UCheckboxGroup
<div class="space-y-2"> v-model="selectedTipos"
<UCheckbox v-model="filterTipos.uva" label="Uva" /> legend="Tipos de Café"
<UCheckbox v-model="filterTipos.mojado" label="Mojado" /> :items="tiposItems"
<UCheckbox v-model="filterTipos.oreado" label="Oreado" /> color="primary"
<UCheckbox v-model="filterTipos.verde" label="Verde" /> variant="list"
</div> orientation="vertical"
size="sm"
/>
</div> </div>
<!-- Estados --> <!-- Estados -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Estados</label> <UCheckboxGroup
<div class="space-y-2"> v-model="selectedEstados"
<UCheckbox v-model="filterEstados.pagado" label="Pagado" /> legend="Estados"
<UCheckbox v-model="filterEstados.pendiente" label="Pendiente" /> :items="estadosItems"
</div> color="primary"
variant="list"
orientation="vertical"
size="sm"
/>
</div> </div>
</div> </div>
<!-- Calidades --> <!-- Calidades -->
<div v-if="opcionesFiltros.calidades.length > 0"> <div v-if="opcionesFiltros.calidades.length > 0">
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Calidades</label> <UCheckboxGroup
<div class="flex flex-wrap gap-2"> v-model="selectedCalidades"
<UCheckbox legend="Calidades"
v-for="calidad in opcionesFiltros.calidades" :items="opcionesFiltros.calidades"
:key="calidad" color="primary"
v-model="selectedCalidades" variant="list"
:value="calidad" orientation="horizontal"
:label="calidad" size="sm"
/> />
</div>
</div> </div>
</div> </div>
@@ -239,51 +246,58 @@
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Ubicaciones --> <!-- Ubicaciones -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Ubicaciones</label> <UCheckboxGroup
<div class="space-y-2 max-h-40 overflow-y-auto"> v-model="selectedUbicaciones"
<UCheckbox legend="Ubicaciones"
v-for="ubicacion in opcionesFiltros.ubicaciones" :items="opcionesFiltros.ubicaciones"
:key="ubicacion" color="primary"
v-model="selectedUbicaciones" variant="list"
:value="ubicacion" orientation="vertical"
:label="ubicacion" size="sm"
/> :ui="{
</div> fieldset: 'max-h-40 overflow-y-auto'
}"
/>
</div> </div>
<!-- Tipos de Café --> <!-- Tipos de Café -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Tipos de Café</label> <UCheckboxGroup
<div class="space-y-2"> v-model="selectedTipos"
<UCheckbox v-model="filterTipos.uva" label="Uva" /> legend="Tipos de Café"
<UCheckbox v-model="filterTipos.mojado" label="Mojado" /> :items="tiposItems"
<UCheckbox v-model="filterTipos.oreado" label="Oreado" /> color="primary"
<UCheckbox v-model="filterTipos.verde" label="Verde" /> variant="list"
</div> orientation="vertical"
size="sm"
/>
</div> </div>
<!-- Estados --> <!-- Estados -->
<div> <div>
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Estados</label> <UCheckboxGroup
<div class="space-y-2"> v-model="selectedEstados"
<UCheckbox v-model="filterEstados.pagado" label="Pagado" /> legend="Estados"
<UCheckbox v-model="filterEstados.pendiente" label="Pendiente" /> :items="estadosItems"
</div> color="primary"
variant="list"
orientation="vertical"
size="sm"
/>
</div> </div>
</div> </div>
<!-- Calidades --> <!-- Calidades -->
<div v-if="opcionesFiltros.calidades.length > 0"> <div v-if="opcionesFiltros.calidades.length > 0">
<label class="block text-sm font-medium mb-2 text-[var(--brand-text)]">Calidades</label> <UCheckboxGroup
<div class="flex flex-wrap gap-2"> v-model="selectedCalidades"
<UCheckbox legend="Calidades"
v-for="calidad in opcionesFiltros.calidades" :items="opcionesFiltros.calidades"
:key="calidad" color="primary"
v-model="selectedCalidades" variant="list"
:value="calidad" orientation="horizontal"
:label="calidad" size="sm"
/> />
</div>
</div> </div>
</div> </div>
@@ -423,23 +437,12 @@ const selectedPreset = ref<PresetValue>('cosecha-25-26')
const fechaDesde = ref<string | null>(null) const fechaDesde = ref<string | null>(null)
const fechaHasta = ref<string | null>(null) const fechaHasta = ref<string | null>(null)
// Filtros avanzados - clientes y ubicaciones // Filtros avanzados - todos usando arrays para CheckboxGroup
const selectedClienteIds = ref<number[]>([]) const selectedClienteIds = ref<number[]>([])
const selectedUbicaciones = ref<string[]>([]) const selectedUbicaciones = ref<string[]>([])
const selectedCalidades = ref<string[]>([]) const selectedCalidades = ref<string[]>([])
const selectedTipos = ref<string[]>([])
// Filtros avanzados - usando checkboxes separados const selectedEstados = ref<string[]>([])
const filterTipos = ref({
uva: false,
mojado: false,
oreado: false,
verde: false
})
const filterEstados = ref({
pagado: false,
pendiente: false
})
// Opciones de filtros disponibles (desde Metabase) // Opciones de filtros disponibles (desde Metabase)
const opcionesFiltros = ref({ const opcionesFiltros = ref({
@@ -449,22 +452,19 @@ const opcionesFiltros = ref({
estados: [] as string[] estados: [] as string[]
}) })
// Convertir checkboxes a arrays para el API // Items para CheckboxGroup de Tipos
const tiposArray = computed(() => { const tiposItems = computed(() => [
const tipos: string[] = [] { label: 'Uva', value: 'uva' },
if (filterTipos.value.uva) tipos.push('uva') { label: 'Mojado', value: 'mojado' },
if (filterTipos.value.mojado) tipos.push('mojado') { label: 'Oreado', value: 'oreado' },
if (filterTipos.value.oreado) tipos.push('oreado') { label: 'Verde', value: 'verde' }
if (filterTipos.value.verde) tipos.push('verde') ])
return tipos
})
const estadosArray = computed(() => { // Items para CheckboxGroup de Estados
const estados: string[] = [] const estadosItems = computed(() => [
if (filterEstados.value.pagado) estados.push('pagado') { label: 'Pagado', value: 'pagado' },
if (filterEstados.value.pendiente) estados.push('pendiente') { label: 'Pendiente', value: 'pendiente' }
return estados ])
})
// Filtros aplicados (los que se usaron en la última carga de datos) // Filtros aplicados (los que se usaron en la última carga de datos)
const appliedFilters = ref<{ const appliedFilters = ref<{
@@ -499,8 +499,8 @@ const hasPendingChanges = computed(() => {
JSON.stringify(selectedClienteIds.value) !== JSON.stringify(appliedFilters.value.clienteIds) || JSON.stringify(selectedClienteIds.value) !== JSON.stringify(appliedFilters.value.clienteIds) ||
JSON.stringify(selectedUbicaciones.value) !== JSON.stringify(appliedFilters.value.ubicaciones) || JSON.stringify(selectedUbicaciones.value) !== JSON.stringify(appliedFilters.value.ubicaciones) ||
JSON.stringify(selectedCalidades.value) !== JSON.stringify(appliedFilters.value.calidades) || JSON.stringify(selectedCalidades.value) !== JSON.stringify(appliedFilters.value.calidades) ||
JSON.stringify(tiposArray.value) !== JSON.stringify(appliedFilters.value.tipos) || JSON.stringify(selectedTipos.value) !== JSON.stringify(appliedFilters.value.tipos) ||
JSON.stringify(estadosArray.value) !== JSON.stringify(appliedFilters.value.estados) JSON.stringify(selectedEstados.value) !== JSON.stringify(appliedFilters.value.estados)
) )
}) })
@@ -521,8 +521,8 @@ async function loadData() {
fecha_hasta: fechaHasta.value, fecha_hasta: fechaHasta.value,
incluir_anulados: includeAnulados.value, incluir_anulados: includeAnulados.value,
cliente_ids: selectedClienteIds.value, cliente_ids: selectedClienteIds.value,
tipos: tiposArray.value, tipos: selectedTipos.value,
estados: estadosArray.value, estados: selectedEstados.value,
ubicaciones: selectedUbicaciones.value, ubicaciones: selectedUbicaciones.value,
calidades: selectedCalidades.value, calidades: selectedCalidades.value,
granularidad: 'dia' // Default granularity granularidad: 'dia' // Default granularity
@@ -551,8 +551,8 @@ async function loadData() {
clienteIds: [...selectedClienteIds.value], clienteIds: [...selectedClienteIds.value],
ubicaciones: [...selectedUbicaciones.value], ubicaciones: [...selectedUbicaciones.value],
calidades: [...selectedCalidades.value], calidades: [...selectedCalidades.value],
tipos: [...tiposArray.value], tipos: [...selectedTipos.value],
estados: [...estadosArray.value] estados: [...selectedEstados.value]
} }
console.log('[Informe] Datos cargados:', result) console.log('[Informe] Datos cargados:', result)