Fix: Corregir selección de usuarios y aplicar estilos de la app
Some checks failed
build-and-deploy / build-and-deploy (push) Has been cancelled

Correcciones de funcionalidad:
- Cambiar v-model por :model-value y @update:model-value para control manual
- Crear selectedClientesObjects computed para sincronizar con props
- Implementar onSelectionChange para extraer IDs correctamente
- Arreglar binding bidireccional con selectedIds

Correcciones de estilo:
- Agregar size="sm" para consistencia con otros inputs
- Usar variables CSS de la app (--brand-text, --brand-text-muted)
- Mantener coherencia visual con el resto de componentes
- Corregir contador para usar props.selectedIds directamente

Ahora el componente:
- Permite seleccionar y deseleccionar usuarios correctamente
- Muestra tags visuales de los seleccionados
- Mantiene el estilo consistente con la app
- Respeta el mínimo de 4 caracteres para búsqueda
This commit is contained in:
2025-10-30 13:20:37 -06:00
parent 466e3923d7
commit 3b0d21dd02

View File

@@ -2,8 +2,7 @@
<div class="space-y-3">
<!-- InputMenu for cliente search and selection -->
<UInputMenu
v-model="selectedClientes"
v-model:search-term="searchQuery"
:model-value="selectedClientesObjects"
:items="filteredItems"
:loading="loading"
multiple
@@ -11,12 +10,15 @@
value-key="id"
icon="i-lucide-search"
placeholder="Buscar clientes por nombre o cédula..."
size="sm"
ignore-filter
@update:model-value="onSelectionChange"
@update:search-term="searchQuery = $event"
>
<template #item-label="{ item }">
<div class="flex flex-col gap-0.5">
<span class="font-medium">{{ item.name }}</span>
<span v-if="item.cedula" class="text-xs text-muted">
<span class="font-medium text-[var(--brand-text)]">{{ item.name }}</span>
<span v-if="item.cedula" class="text-xs text-[var(--brand-text-muted)]">
{{ formatCedula(item.cedula) }}
</span>
</div>
@@ -24,10 +26,10 @@
<template #empty>
<div class="text-center py-2">
<span v-if="searchQuery.length < 4" class="text-muted text-sm">
<span v-if="searchQuery.length < 4" class="text-[var(--brand-text-muted)] text-sm">
Escribe al menos 4 caracteres para buscar
</span>
<span v-else class="text-muted text-sm">
<span v-else class="text-[var(--brand-text-muted)] text-sm">
No se encontraron clientes
</span>
</div>
@@ -35,9 +37,9 @@
</UInputMenu>
<!-- Selected count and clear all -->
<div v-if="selectedClientes.length > 0" class="flex items-center justify-between text-sm">
<span class="text-muted">
{{ selectedClientes.length }} cliente{{ selectedClientes.length !== 1 ? 's' : '' }} seleccionado{{ selectedClientes.length !== 1 ? 's' : '' }}
<div v-if="selectedIds.length > 0" class="flex items-center justify-between text-sm">
<span class="text-[var(--brand-text-muted)]">
{{ selectedIds.length }} cliente{{ selectedIds.length !== 1 ? 's' : '' }} seleccionado{{ selectedIds.length !== 1 ? 's' : '' }}
</span>
<UButton
size="xs"
@@ -74,14 +76,17 @@ const clientes = ref<Cliente[]>([])
const loading = ref(false)
const searchQuery = ref('')
// Computed - Sync with props
const selectedClientes = computed({
get: () => {
return clientes.value.filter(c => props.selectedIds.includes(c.id))
},
set: (value: Cliente[]) => {
emit('update:selectedIds', value.map(c => c.id))
}
// Computed - Get selected clientes as objects for InputMenu
const selectedClientesObjects = computed(() => {
return clientes.value
.filter(c => props.selectedIds.includes(c.id))
.map(c => ({
id: c.id,
name: c.name,
cedula: c.cedula,
label: c.name,
value: c.id
}))
})
// Computed - Filter items based on search (min 4 characters)
@@ -110,6 +115,12 @@ const filteredItems = computed((): InputMenuItem[] => {
})
// Methods
function onSelectionChange(value: any[]) {
// Extract IDs from selected items
const ids = value.map(item => item.id || item.value || item)
emit('update:selectedIds', ids)
}
function clearAll() {
emit('update:selectedIds', [])
}