From dae7c73749c9e2f943f3b72fa8a53863ab1006cf Mon Sep 17 00:00:00 2001 From: josedario87 Date: Thu, 30 Oct 2025 14:14:44 -0600 Subject: [PATCH] Fix: Normalizar array de ubicaciones y agregar soporte para loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problema identificado: - El array de ubicaciones viene como array de strings simples, no como objetos con {label, value} - Ejemplo: ["breñales, la union, lempira", "buenos aires, ..."] Solución implementada: 1. Normalización de datos: - Crear computed normalizedUbicaciones que transforma el array - Si el item es string: usa el string como label y value - Si el item es objeto: usa sus propiedades label y value - Filtrar null/undefined durante la transformación 2. Agregar prop loading: - Agregada prop opcional loading?: boolean - Pasar loading al UInputMenu para mostrar spinner 3. Simplificar lógica de filtrado: - Usar normalizedUbicaciones como base - Filtrar por query sin errores de toLowerCase 4. Mejorar selectedUbicacionesObjects: - Usar normalizedUbicaciones para encontrar seleccionados - Comparar con value normalizado Ahora el componente: - Muestra todas las ubicaciones correctamente - Funciona con array de strings o array de objetos - Muestra animación de loading cuando carga datos - Búsqueda funciona sin errores --- .../app/components/UbicacionMultiSelector.vue | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/nuxt4-app/app/components/UbicacionMultiSelector.vue b/nuxt4-app/app/components/UbicacionMultiSelector.vue index 071d7a3..1ad2c2e 100644 --- a/nuxt4-app/app/components/UbicacionMultiSelector.vue +++ b/nuxt4-app/app/components/UbicacionMultiSelector.vue @@ -4,6 +4,7 @@ () const emit = defineEmits<{ @@ -72,24 +74,43 @@ const emit = defineEmits<{ // State const searchQuery = ref('') +// Computed - Normalize ubicaciones to InputMenuItem format +const normalizedUbicaciones = computed((): InputMenuItem[] => { + if (!Array.isArray(props.ubicaciones)) return [] + + return props.ubicaciones + .filter(u => u) // Filter out null/undefined + .map(u => { + // If it's already an object with label and value, use it + if (typeof u === 'object' && u.label && u.value) { + return { label: u.label, value: u.value } + } + // If it's a string, use it as both label and value + if (typeof u === 'string') { + return { label: u, value: u } + } + return null + }) + .filter((u): u is InputMenuItem => u !== null) +}) + // Computed - Get selected ubicaciones as objects for InputMenu const selectedUbicacionesObjects = computed(() => { - return props.ubicaciones.filter(u => props.selectedUbicaciones.includes(u.value)) + return normalizedUbicaciones.value.filter(u => + props.selectedUbicaciones.includes(u.value as string) + ) }) // Computed - Filter items based on search const filteredItems = computed((): InputMenuItem[] => { const query = searchQuery.value.trim().toLowerCase() - // Filter out undefined/null items and ensure they have label and value - const validUbicaciones = props.ubicaciones.filter(u => u && u.label && u.value) - if (!query) { - return validUbicaciones + return normalizedUbicaciones.value } - return validUbicaciones.filter(u => - u.label.toLowerCase().includes(query) + return normalizedUbicaciones.value.filter(u => + u.label && typeof u.label === 'string' && u.label.toLowerCase().includes(query) ) })