SearchResults.svelte
4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<script>
import { goto } from '$app/navigation';
import { clearSearch, filterType } from '$lib/stores/searchStore';
let { results = [], query = '', selectedIndex = -1 } = $props();
function handleSelect(item) {
if (item.tipo === 'entidad') {
goto(`/entidad/${item.codigo}`);
} else if (item.tipo === 'objeto_gasto') {
goto(`/objeto/${item.codigo}`);
} else if (item.tipo === 'rubro') {
goto(`/rubro/${item.codigo}`);
}
clearSearch();
}
// Agrupar resultados por tipo
let groupedResults = $derived(() => {
const entidades = results.filter(r => r.tipo === 'entidad');
const objetos = results.filter(r => r.tipo === 'objeto_gasto');
const rubros = results.filter(r => r.tipo === 'rubro');
return { entidades, objetos, rubros };
});
// Si hay un filtro específico, no mostrar headers de grupo
let showGroupHeaders = $derived($filterType === 'todos');
// Calcular índice global para navegación con teclado
function getGlobalIndex(tipo, localIndex) {
const g = groupedResults();
if (tipo === 'entidad') {
return localIndex;
} else if (tipo === 'objeto_gasto') {
return g.entidades.length + localIndex;
} else {
return g.entidades.length + g.objetos.length + localIndex;
}
}
</script>
{#if results.length > 0}
<div class="absolute top-full left-0 right-0 mt-1 bg-white border rounded shadow-lg max-h-80 overflow-y-auto z-50">
{#if groupedResults().entidades.length > 0}
{#if showGroupHeaders}
<div class="px-3 py-1.5 bg-slate-50 border-b">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wide">Entidades</span>
</div>
{/if}
{#each groupedResults().entidades as item, index}
{@const globalIdx = getGlobalIndex('entidad', index)}
<button
type="button"
class="w-full text-left px-3 py-2 text-sm hover:bg-gray-100 {globalIdx === selectedIndex ? 'bg-blue-50' : ''}"
onclick={() => handleSelect(item)}
>
<div class="flex items-center gap-2">
<span>{item.nombre}</span>
{#if item.sigla}
<span class="text-slate-400">({item.sigla})</span>
{/if}
</div>
<div class="text-xs text-gray-500">{item.contexto}</div>
</button>
{/each}
{/if}
{#if groupedResults().objetos.length > 0}
{#if showGroupHeaders}
<div class="px-3 py-1.5 bg-slate-50 border-b {groupedResults().entidades.length > 0 ? 'border-t' : ''}">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wide">Objetos del Gasto</span>
</div>
{/if}
{#each groupedResults().objetos as item, index}
{@const globalIdx = getGlobalIndex('objeto_gasto', index)}
<button
type="button"
class="w-full text-left px-3 py-2 text-sm hover:bg-gray-100 {globalIdx === selectedIndex ? 'bg-blue-50' : ''}"
onclick={() => handleSelect(item)}
>
<div class="flex items-center gap-2">
<span class="font-mono text-xs text-slate-400">{item.codigo}</span>
<span>{item.nombre}</span>
</div>
<div class="text-xs text-gray-500">{item.contexto}</div>
</button>
{/each}
{/if}
{#if groupedResults().rubros.length > 0}
{#if showGroupHeaders}
<div class="px-3 py-1.5 bg-slate-50 border-b {groupedResults().entidades.length > 0 || groupedResults().objetos.length > 0 ? 'border-t' : ''}">
<span class="text-xs font-medium text-slate-500 uppercase tracking-wide">Rubros</span>
</div>
{/if}
{#each groupedResults().rubros as item, index}
{@const globalIdx = getGlobalIndex('rubro', index)}
<button
type="button"
class="w-full text-left px-3 py-2 text-sm hover:bg-gray-100 {globalIdx === selectedIndex ? 'bg-blue-50' : ''}"
onclick={() => handleSelect(item)}
>
<div class="flex items-center gap-2">
<span class="font-mono text-xs text-slate-400">{item.codigo}</span>
<span>{item.nombre}</span>
</div>
<div class="text-xs text-gray-500">{item.contexto}</div>
</button>
{/each}
{/if}
</div>
{:else if query.length >= 2}
<div class="absolute top-full left-0 right-0 mt-1 bg-white border rounded p-3 text-sm text-gray-500">
Sin resultados para "{query}"
</div>
{/if}