Showing
10 changed files
with
230 additions
and
41 deletions
| ... | @@ -45,7 +45,7 @@ | ... | @@ -45,7 +45,7 @@ |
| 45 | scaleBand() | 45 | scaleBand() |
| 46 | .domain(data.map(d => d.año)) | 46 | .domain(data.map(d => d.año)) |
| 47 | .range([0, 100]) // porcentaje | 47 | .range([0, 100]) // porcentaje |
| 48 | - .padding(0.2) | 48 | + .padding(0.6) |
| 49 | ); | 49 | ); |
| 50 | 50 | ||
| 51 | // Para CSS bottom positioning: 0 → 0%, max → 100% | 51 | // Para CSS bottom positioning: 0 → 0%, max → 100% |
| ... | @@ -112,15 +112,11 @@ | ... | @@ -112,15 +112,11 @@ |
| 112 | <!-- Eje X --> | 112 | <!-- Eje X --> |
| 113 | <div class="x-axis" style="height: {marginBottom}px; left: {marginLeft}px; right: {marginRight}px"> | 113 | <div class="x-axis" style="height: {marginBottom}px; left: {marginLeft}px; right: {marginRight}px"> |
| 114 | {#each data as d, i} | 114 | {#each data as d, i} |
| 115 | - {@const isFirst = i === 0} | ||
| 116 | - {@const isLast = i === data.length - 1} | ||
| 117 | - {@const isMid = i === midIndex && data.length > 5} | ||
| 118 | - {@const showLabel = isFirst || isLast || isMid || hoveredYear === d.año} | ||
| 119 | <span | 115 | <span |
| 120 | - class="x-label" | 116 | + class="x-label visible" |
| 121 | - class:visible={showLabel} | 117 | + class:hovered={hoveredYear === d.año} |
| 122 | > | 118 | > |
| 123 | - {d.año} | 119 | + {String(d.año).slice(-2)} |
| 124 | </span> | 120 | </span> |
| 125 | {/each} | 121 | {/each} |
| 126 | </div> | 122 | </div> |
| ... | @@ -170,7 +166,7 @@ | ... | @@ -170,7 +166,7 @@ |
| 170 | bottom: 0; | 166 | bottom: 0; |
| 171 | display: flex; | 167 | display: flex; |
| 172 | align-items: flex-end; | 168 | align-items: flex-end; |
| 173 | - gap: 2px; | 169 | + gap: 4px; |
| 174 | } | 170 | } |
| 175 | 171 | ||
| 176 | .bar-container { | 172 | .bar-container { |
| ... | @@ -178,11 +174,12 @@ | ... | @@ -178,11 +174,12 @@ |
| 178 | height: 100%; | 174 | height: 100%; |
| 179 | display: flex; | 175 | display: flex; |
| 180 | align-items: flex-end; | 176 | align-items: flex-end; |
| 177 | + justify-content: center; | ||
| 181 | cursor: default; | 178 | cursor: default; |
| 182 | } | 179 | } |
| 183 | 180 | ||
| 184 | .bar { | 181 | .bar { |
| 185 | - width: 100%; | 182 | + width: 80%; |
| 186 | background: #c4897d; | 183 | background: #c4897d; |
| 187 | border-radius: 4px 4px 0 0; | 184 | border-radius: 4px 4px 0 0; |
| 188 | transition: opacity 0.1s ease; | 185 | transition: opacity 0.1s ease; |
| ... | @@ -206,20 +203,27 @@ | ... | @@ -206,20 +203,27 @@ |
| 206 | bottom: 0; | 203 | bottom: 0; |
| 207 | display: flex; | 204 | display: flex; |
| 208 | align-items: center; | 205 | align-items: center; |
| 206 | + gap: 4px; | ||
| 209 | } | 207 | } |
| 210 | 208 | ||
| 211 | .x-label { | 209 | .x-label { |
| 212 | flex: 1; | 210 | flex: 1; |
| 213 | text-align: center; | 211 | text-align: center; |
| 214 | - font-family: 'Qanelas', var(--font-sans); | 212 | + font-family: 'DM Mono', monospace; |
| 215 | - font-size: 0.6875rem; | 213 | + font-size: 0.5625rem; |
| 216 | color: var(--theme-texto); | 214 | color: var(--theme-texto); |
| 217 | opacity: 0; | 215 | opacity: 0; |
| 218 | transition: opacity 0.2s ease; | 216 | transition: opacity 0.2s ease; |
| 219 | } | 217 | } |
| 220 | 218 | ||
| 221 | .x-label.visible { | 219 | .x-label.visible { |
| 220 | + opacity: 0.5; | ||
| 221 | + } | ||
| 222 | + | ||
| 223 | + .x-label.hovered { | ||
| 222 | opacity: 1; | 224 | opacity: 1; |
| 225 | + color: var(--theme-titulo); | ||
| 226 | + font-weight: 600; | ||
| 223 | } | 227 | } |
| 224 | 228 | ||
| 225 | .chart-empty { | 229 | .chart-empty { | ... | ... |
| ... | @@ -101,12 +101,14 @@ | ... | @@ -101,12 +101,14 @@ |
| 101 | padding: 0.125rem 0; | 101 | padding: 0.125rem 0; |
| 102 | background: transparent; | 102 | background: transparent; |
| 103 | border: none; | 103 | border: none; |
| 104 | - border-bottom: 1px dotted #333333; | 104 | + border-bottom: 1px dotted #666666; |
| 105 | color: var(--theme-titulo); | 105 | color: var(--theme-titulo); |
| 106 | font-size: 1rem; | 106 | font-size: 1rem; |
| 107 | font-weight: 500; | 107 | font-weight: 500; |
| 108 | cursor: pointer; | 108 | cursor: pointer; |
| 109 | transition: border-color 0.2s; | 109 | transition: border-color 0.2s; |
| 110 | + max-width: 100%; | ||
| 111 | + min-width: 0; | ||
| 110 | } | 112 | } |
| 111 | 113 | ||
| 112 | .entity-btn:hover { | 114 | .entity-btn:hover { |
| ... | @@ -115,6 +117,9 @@ | ... | @@ -115,6 +117,9 @@ |
| 115 | 117 | ||
| 116 | .entity-label { | 118 | .entity-label { |
| 117 | text-align: left; | 119 | text-align: left; |
| 120 | + overflow: hidden; | ||
| 121 | + text-overflow: ellipsis; | ||
| 122 | + white-space: nowrap; | ||
| 118 | } | 123 | } |
| 119 | 124 | ||
| 120 | .chevron { | 125 | .chevron { |
| ... | @@ -132,7 +137,8 @@ | ... | @@ -132,7 +137,8 @@ |
| 132 | position: absolute; | 137 | position: absolute; |
| 133 | top: calc(100% + 4px); | 138 | top: calc(100% + 4px); |
| 134 | left: 0; | 139 | left: 0; |
| 135 | - min-width: 280px; | 140 | + right: 0; |
| 141 | + min-width: min(280px, calc(100vw - 2rem)); | ||
| 136 | background: var(--theme-surface); | 142 | background: var(--theme-surface); |
| 137 | border: 1px solid var(--theme-borde); | 143 | border: 1px solid var(--theme-borde); |
| 138 | border-radius: 10px; | 144 | border-radius: 10px; | ... | ... |
| 1 | <script> | 1 | <script> |
| 2 | import { goto } from '$app/navigation'; | 2 | import { goto } from '$app/navigation'; |
| 3 | - import { indexLoaded } from '$lib/stores/searchStore'; | ||
| 4 | - import { search } from '$lib/services/search'; | ||
| 5 | 3 | ||
| 6 | let { | 4 | let { |
| 7 | preserveVista = false, | 5 | preserveVista = false, |
| ... | @@ -16,20 +14,46 @@ | ... | @@ -16,20 +14,46 @@ |
| 16 | let selectedIdx = $state(-1); | 14 | let selectedIdx = $state(-1); |
| 17 | let debounceTimer; | 15 | let debounceTimer; |
| 18 | 16 | ||
| 17 | + function parseMetadatos(meta) { | ||
| 18 | + if (!meta) return {}; | ||
| 19 | + if (typeof meta === 'object') return meta; | ||
| 20 | + try { return JSON.parse(meta); } catch { return {}; } | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + async function doSearch(query) { | ||
| 24 | + isSearching = true; | ||
| 25 | + try { | ||
| 26 | + const params = new URLSearchParams({ | ||
| 27 | + q: query, | ||
| 28 | + per_page: '20', | ||
| 29 | + is_class: 'true', | ||
| 30 | + class_: 'objeto' | ||
| 31 | + }); | ||
| 32 | + const res = await fetch(`/api/search?${params}`); | ||
| 33 | + if (!res.ok) throw new Error(); | ||
| 34 | + const data = await res.json(); | ||
| 35 | + localResults = (data.hits || []).map(hit => { | ||
| 36 | + const meta = parseMetadatos(hit.document.metadatos); | ||
| 37 | + const codigo = meta.objeto_subpartida || meta.objeto_partida || meta.objeto_subgrupo || meta.objeto_grupo || ''; | ||
| 38 | + const nombre = hit.document.texto; | ||
| 39 | + const highlight = hit.highlights?.[0]?.snippet || nombre; | ||
| 40 | + return { codigo, nombre, highlight }; | ||
| 41 | + }); | ||
| 42 | + selectedIdx = -1; | ||
| 43 | + } catch { | ||
| 44 | + localResults = []; | ||
| 45 | + } | ||
| 46 | + isSearching = false; | ||
| 47 | + } | ||
| 48 | + | ||
| 19 | function handleSearchInput(e) { | 49 | function handleSearchInput(e) { |
| 20 | - const val = e.target.value; | 50 | + searchVal = e.target.value; |
| 21 | clearTimeout(debounceTimer); | 51 | clearTimeout(debounceTimer); |
| 22 | - debounceTimer = setTimeout(() => { | 52 | + if (searchVal.length >= 2) { |
| 23 | - if (val.length >= 2) { | 53 | + debounceTimer = setTimeout(() => doSearch(searchVal), 200); |
| 24 | - isSearching = true; | 54 | + } else { |
| 25 | - // Buscar y filtrar solo objetos de gasto | 55 | + localResults = []; |
| 26 | - const allResults = search(val, 50); | 56 | + } |
| 27 | - localResults = allResults.filter(r => r.tipo === 'objeto_gasto').slice(0, 15); | ||
| 28 | - isSearching = false; | ||
| 29 | - } else { | ||
| 30 | - localResults = []; | ||
| 31 | - } | ||
| 32 | - }, 200); | ||
| 33 | } | 57 | } |
| 34 | 58 | ||
| 35 | function handleSearchKeydown(e) { | 59 | function handleSearchKeydown(e) { |
| ... | @@ -86,7 +110,6 @@ | ... | @@ -86,7 +110,6 @@ |
| 86 | onfocus={() => searchFocused = true} | 110 | onfocus={() => searchFocused = true} |
| 87 | onblur={handleSearchBlur} | 111 | onblur={handleSearchBlur} |
| 88 | placeholder="Buscar objeto..." | 112 | placeholder="Buscar objeto..." |
| 89 | - disabled={!$indexLoaded} | ||
| 90 | /> | 113 | /> |
| 91 | {#if searchVal} | 114 | {#if searchVal} |
| 92 | <button class="search-clear" onclick={handleClear}> | 115 | <button class="search-clear" onclick={handleClear}> |
| ... | @@ -110,7 +133,7 @@ | ... | @@ -110,7 +133,7 @@ |
| 110 | onmouseenter={() => selectedIdx = i} | 133 | onmouseenter={() => selectedIdx = i} |
| 111 | > | 134 | > |
| 112 | <span class="item-code">{result.codigo}</span> | 135 | <span class="item-code">{result.codigo}</span> |
| 113 | - <span class="item-name">{result.nombre}</span> | 136 | + <span class="item-name">{@html result.highlight}</span> |
| 114 | </button> | 137 | </button> |
| 115 | {/each} | 138 | {/each} |
| 116 | {/if} | 139 | {/if} |
| ... | @@ -229,4 +252,11 @@ | ... | @@ -229,4 +252,11 @@ |
| 229 | font-size: 0.8125rem; | 252 | font-size: 0.8125rem; |
| 230 | color: var(--theme-titulo); | 253 | color: var(--theme-titulo); |
| 231 | } | 254 | } |
| 255 | + | ||
| 256 | + :global(.item-name mark) { | ||
| 257 | + background: rgba(201, 167, 81, 0.3); | ||
| 258 | + color: inherit; | ||
| 259 | + border-radius: 2px; | ||
| 260 | + padding: 0 1px; | ||
| 261 | + } | ||
| 232 | </style> | 262 | </style> | ... | ... |
| ... | @@ -72,13 +72,13 @@ | ... | @@ -72,13 +72,13 @@ |
| 72 | 72 | ||
| 73 | // Detectar tipos de clasificadores presentes en los resultados | 73 | // Detectar tipos de clasificadores presentes en los resultados |
| 74 | // Mapeo inverso: API class_ → id interno del clasificador | 74 | // Mapeo inverso: API class_ → id interno del clasificador |
| 75 | - const CLASS_REVERSE_MAP = { ubigeo: 'geografico', acteco: 'sectores' }; | 75 | + const CLASS_REVERSE_MAP = { ubigeo: 'geografico', acteco: 'sectores', finalidad: 'finfun' }; |
| 76 | 76 | ||
| 77 | // Filtrar hits según clasificadores seleccionados (la API puede devolver tipos extra) | 77 | // Filtrar hits según clasificadores seleccionados (la API puede devolver tipos extra) |
| 78 | $: filteredHits = (() => { | 78 | $: filteredHits = (() => { |
| 79 | if (searchMode !== 'clasificadores' || selectedClassifiers.length === 0) return allHits; | 79 | if (searchMode !== 'clasificadores' || selectedClassifiers.length === 0) return allHits; |
| 80 | const allowedClasses = new Set(selectedClassifiers.map(c => { | 80 | const allowedClasses = new Set(selectedClassifiers.map(c => { |
| 81 | - const map = { geografico: 'ubigeo', sectores: 'acteco' }; | 81 | + const map = { geografico: 'ubigeo', sectores: 'acteco', finfun: 'finalidad' }; |
| 82 | return map[c] || c; | 82 | return map[c] || c; |
| 83 | })); | 83 | })); |
| 84 | return allHits.filter(h => allowedClasses.has(h.document.class_)); | 84 | return allHits.filter(h => allowedClasses.has(h.document.class_)); |
| ... | @@ -86,7 +86,12 @@ | ... | @@ -86,7 +86,12 @@ |
| 86 | 86 | ||
| 87 | $: activeClassTypes = (() => { | 87 | $: activeClassTypes = (() => { |
| 88 | const types = new Set(); | 88 | const types = new Set(); |
| 89 | - filteredHits.forEach(h => { if (h.document.class_) types.add(h.document.class_); }); | 89 | + filteredHits.forEach(h => { |
| 90 | + if (h.document.class_) { | ||
| 91 | + const normalized = CLASS_REVERSE_MAP[h.document.class_] || h.document.class_; | ||
| 92 | + types.add(normalized); | ||
| 93 | + } | ||
| 94 | + }); | ||
| 90 | return types; | 95 | return types; |
| 91 | })(); | 96 | })(); |
| 92 | $: isMixedClassSearch = activeClassTypes.size > 1; | 97 | $: isMixedClassSearch = activeClassTypes.size > 1; |
| ... | @@ -154,14 +159,14 @@ | ... | @@ -154,14 +159,14 @@ |
| 154 | if (isMixedClassSearch || searchMode === 'todo') { | 159 | if (isMixedClassSearch || searchMode === 'todo') { |
| 155 | // Filtrar duplicados de finfun | 160 | // Filtrar duplicados de finfun |
| 156 | const filtered = filteredHits.filter(hit => { | 161 | const filtered = filteredHits.filter(hit => { |
| 157 | - if (hit.document.class_ !== 'finfun') return true; | 162 | + if (hit.document.class_ !== 'finfun' && hit.document.class_ !== 'finalidad') return true; |
| 158 | const m = parseMetadatos(hit.document.metadatos); | 163 | const m = parseMetadatos(hit.document.metadatos); |
| 159 | return !(m.finfun_funcion === 0 && m.finfun_grpfuncion !== undefined); | 164 | return !(m.finfun_funcion === 0 && m.finfun_grpfuncion !== undefined); |
| 160 | }); | 165 | }); |
| 161 | 166 | ||
| 162 | const groups = {}; | 167 | const groups = {}; |
| 163 | filtered.forEach(hit => { | 168 | filtered.forEach(hit => { |
| 164 | - const type = hit.document.class_ || 'otros'; | 169 | + const type = CLASS_REVERSE_MAP[hit.document.class_] || hit.document.class_ || 'otros'; |
| 165 | const groupName = CLASS_LABELS[type] || type; | 170 | const groupName = CLASS_LABELS[type] || type; |
| 166 | if (!groups[groupName]) { | 171 | if (!groups[groupName]) { |
| 167 | groups[groupName] = { name: groupName, hits: [], totalMonto: 0, classType: type }; | 172 | groups[groupName] = { name: groupName, hits: [], totalMonto: 0, classType: type }; |
| ... | @@ -692,7 +697,7 @@ | ... | @@ -692,7 +697,7 @@ |
| 692 | const isClassResult = hit.document.is_class === true; | 697 | const isClassResult = hit.document.is_class === true; |
| 693 | 698 | ||
| 694 | let url; | 699 | let url; |
| 695 | - const isFinfunClass = hit.document.class_ === 'finfun'; | 700 | + const isFinfunClass = hit.document.class_ === 'finfun' || hit.document.class_ === 'finalidad'; |
| 696 | 701 | ||
| 697 | const isUbigeoClass = hit.document.class_ === 'ubigeo'; | 702 | const isUbigeoClass = hit.document.class_ === 'ubigeo'; |
| 698 | 703 | ||
| ... | @@ -1207,7 +1212,7 @@ | ... | @@ -1207,7 +1212,7 @@ |
| 1207 | {#each group.hits.slice(0, maxVisible) as hit, i (getHitKey(hit, gi * 1000 + i))} | 1212 | {#each group.hits.slice(0, maxVisible) as hit, i (getHitKey(hit, gi * 1000 + i))} |
| 1208 | {@const meta = parseMetadatos(hit.document.metadatos)} | 1213 | {@const meta = parseMetadatos(hit.document.metadatos)} |
| 1209 | {@const globalIdx = flatHitsForNav.indexOf(hit)} | 1214 | {@const globalIdx = flatHitsForNav.indexOf(hit)} |
| 1210 | - {@const hitClass = hit.document.class_} | 1215 | + {@const hitClass = CLASS_REVERSE_MAP[hit.document.class_] || hit.document.class_} |
| 1211 | {#if hitClass === 'entidad'} | 1216 | {#if hitClass === 'entidad'} |
| 1212 | {@const isDA = meta.da && meta.entidad_desc_entidad} | 1217 | {@const isDA = meta.da && meta.entidad_desc_entidad} |
| 1213 | {@const parentEntity = isDA ? extractAfterHyphen(meta.entidad_desc_entidad) : null} | 1218 | {@const parentEntity = isDA ? extractAfterHyphen(meta.entidad_desc_entidad) : null} |
| ... | @@ -1323,10 +1328,10 @@ | ... | @@ -1323,10 +1328,10 @@ |
| 1323 | {@const subarea = isEntidadClass ? extractAfterHyphen(meta.entidad_desc_subarea) : null} | 1328 | {@const subarea = isEntidadClass ? extractAfterHyphen(meta.entidad_desc_subarea) : null} |
| 1324 | {@const parentEntity = isDA ? extractAfterHyphen(meta.entidad_desc_entidad) : null} | 1329 | {@const parentEntity = isDA ? extractAfterHyphen(meta.entidad_desc_entidad) : null} |
| 1325 | {@const isObjetoClass = hit.document.class_ === 'objeto'} | 1330 | {@const isObjetoClass = hit.document.class_ === 'objeto'} |
| 1326 | - {@const isFinfunClass = hit.document.class_ === 'finfun'} | 1331 | + {@const isFinfunClass = hit.document.class_ === 'finfun' || hit.document.class_ === 'finalidad'} |
| 1327 | {@const isUbigeoClass = hit.document.class_ === 'ubigeo'} | 1332 | {@const isUbigeoClass = hit.document.class_ === 'ubigeo'} |
| 1328 | {@const isClassResult = hit.document.is_class === true} | 1333 | {@const isClassResult = hit.document.is_class === true} |
| 1329 | - {@const hitType = hit.document.class_} | 1334 | + {@const hitType = CLASS_REVERSE_MAP[hit.document.class_] || hit.document.class_} |
| 1330 | <a | 1335 | <a |
| 1331 | href={isEntidadClass | 1336 | href={isEntidadClass |
| 1332 | ? `/entidad/${meta.da ? `${meta.entidad}.${meta.da}` : meta.entidad}` | 1337 | ? `/entidad/${meta.da ? `${meta.entidad}.${meta.da}` : meta.entidad}` | ... | ... |
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
| ... | @@ -28,8 +28,8 @@ | ... | @@ -28,8 +28,8 @@ |
| 28 | let topEntidadesPorAño = $state({}); | 28 | let topEntidadesPorAño = $state({}); |
| 29 | 29 | ||
| 30 | const POBLACION = 12000000; | 30 | const POBLACION = 12000000; |
| 31 | - const objetoCodigo = '11700'; | 31 | + let objetoCodigo = $derived(objetoData.objeto); |
| 32 | - const objetoNivel = 'subpartida'; | 32 | + let objetoNivel = $derived(objetoData.nivel); |
| 33 | 33 | ||
| 34 | let gastoPerCapita = $derived( | 34 | let gastoPerCapita = $derived( |
| 35 | datosAnuales.map(d => ({ | 35 | datosAnuales.map(d => ({ | ... | ... |
| 1 | +import { supabase } from '$lib/supabase'; | ||
| 2 | +import { error } from '@sveltejs/kit'; | ||
| 3 | + | ||
| 4 | +// Funciones para derivar jerarquía del código objeto | ||
| 5 | +function getGrupoCode(objeto) { | ||
| 6 | + return objeto.charAt(0) + '0000'; | ||
| 7 | +} | ||
| 8 | + | ||
| 9 | +function getSubgrupoCode(objeto) { | ||
| 10 | + return objeto.substring(0, 2) + '000'; | ||
| 11 | +} | ||
| 12 | + | ||
| 13 | +function getPartidaCode(objeto) { | ||
| 14 | + return objeto.substring(0, 3) + '00'; | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +function getNivel(objeto) { | ||
| 18 | + if (objeto.endsWith('0000')) return 'grupo'; | ||
| 19 | + if (objeto.endsWith('000')) return 'subgrupo'; | ||
| 20 | + if (objeto.endsWith('00')) return 'partida'; | ||
| 21 | + return 'subpartida'; | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +export async function load({ params }) { | ||
| 25 | + console.time('[SERVER] Total load objeto'); | ||
| 26 | + const { codigo } = params; | ||
| 27 | + | ||
| 28 | + console.time('[SERVER] Query clas_objetos'); | ||
| 29 | + const { data, error: dbError } = await supabase | ||
| 30 | + .schema('ppto') | ||
| 31 | + .from('clas_objetos') | ||
| 32 | + .select('*') | ||
| 33 | + .eq('objeto', codigo); | ||
| 34 | + console.timeEnd('[SERVER] Query clas_objetos'); | ||
| 35 | + | ||
| 36 | + if (dbError || !data || data.length === 0) { | ||
| 37 | + throw error(404, 'Objeto no encontrado'); | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + // Tomar el primer resultado | ||
| 41 | + const objeto = data[0]; | ||
| 42 | + const nivel = objeto.nivel || getNivel(codigo); | ||
| 43 | + | ||
| 44 | + // Obtener jerarquía (padres e hijos) | ||
| 45 | + let padres = []; | ||
| 46 | + let hijos = []; | ||
| 47 | + | ||
| 48 | + console.time('[SERVER] Query padres'); | ||
| 49 | + | ||
| 50 | + // Buscar padres según nivel | ||
| 51 | + if (nivel === 'subpartida') { | ||
| 52 | + // Padres: grupo, subgrupo, partida | ||
| 53 | + const grupoCode = getGrupoCode(codigo); | ||
| 54 | + const subgrupoCode = getSubgrupoCode(codigo); | ||
| 55 | + const partidaCode = getPartidaCode(codigo); | ||
| 56 | + | ||
| 57 | + const { data: padresData } = await supabase | ||
| 58 | + .schema('ppto') | ||
| 59 | + .from('clas_objetos') | ||
| 60 | + .select('*') | ||
| 61 | + .in('objeto', [grupoCode, subgrupoCode, partidaCode]) | ||
| 62 | + .order('objeto'); | ||
| 63 | + | ||
| 64 | + if (padresData) padres = padresData; | ||
| 65 | + } else if (nivel === 'partida') { | ||
| 66 | + // Padres: grupo, subgrupo | ||
| 67 | + const grupoCode = getGrupoCode(codigo); | ||
| 68 | + const subgrupoCode = getSubgrupoCode(codigo); | ||
| 69 | + | ||
| 70 | + const { data: padresData } = await supabase | ||
| 71 | + .schema('ppto') | ||
| 72 | + .from('clas_objetos') | ||
| 73 | + .select('*') | ||
| 74 | + .in('objeto', [grupoCode, subgrupoCode]) | ||
| 75 | + .order('objeto'); | ||
| 76 | + | ||
| 77 | + if (padresData) padres = padresData; | ||
| 78 | + } else if (nivel === 'subgrupo') { | ||
| 79 | + // Padre: grupo | ||
| 80 | + const grupoCode = getGrupoCode(codigo); | ||
| 81 | + | ||
| 82 | + const { data: padresData } = await supabase | ||
| 83 | + .schema('ppto') | ||
| 84 | + .from('clas_objetos') | ||
| 85 | + .select('*') | ||
| 86 | + .eq('objeto', grupoCode); | ||
| 87 | + | ||
| 88 | + if (padresData) padres = padresData; | ||
| 89 | + } | ||
| 90 | + // grupo no tiene padres | ||
| 91 | + | ||
| 92 | + console.timeEnd('[SERVER] Query padres'); | ||
| 93 | + | ||
| 94 | + console.time('[SERVER] Query hijos'); | ||
| 95 | + | ||
| 96 | + // Buscar hijos según nivel | ||
| 97 | + if (nivel === 'grupo') { | ||
| 98 | + // Hijos: subgrupos que empiecen con el mismo dígito | ||
| 99 | + const prefix = codigo.charAt(0); | ||
| 100 | + const { data: hijosData } = await supabase | ||
| 101 | + .schema('ppto') | ||
| 102 | + .from('clas_objetos') | ||
| 103 | + .select('*') | ||
| 104 | + .eq('nivel', 'subgrupo') | ||
| 105 | + .like('objeto', `${prefix}%`) | ||
| 106 | + .order('objeto'); | ||
| 107 | + | ||
| 108 | + hijos = hijosData || []; | ||
| 109 | + } else if (nivel === 'subgrupo') { | ||
| 110 | + // Hijos: partidas que empiecen con los mismos 2 dígitos | ||
| 111 | + const prefix = codigo.substring(0, 2); | ||
| 112 | + const { data: hijosData } = await supabase | ||
| 113 | + .schema('ppto') | ||
| 114 | + .from('clas_objetos') | ||
| 115 | + .select('*') | ||
| 116 | + .eq('nivel', 'partida') | ||
| 117 | + .like('objeto', `${prefix}%`) | ||
| 118 | + .order('objeto'); | ||
| 119 | + | ||
| 120 | + hijos = hijosData || []; | ||
| 121 | + } else if (nivel === 'partida') { | ||
| 122 | + // Hijos: subpartidas que empiecen con los mismos 3 dígitos | ||
| 123 | + const prefix = codigo.substring(0, 3); | ||
| 124 | + const { data: hijosData } = await supabase | ||
| 125 | + .schema('ppto') | ||
| 126 | + .from('clas_objetos') | ||
| 127 | + .select('*') | ||
| 128 | + .eq('nivel', 'subpartida') | ||
| 129 | + .like('objeto', `${prefix}%`) | ||
| 130 | + .order('objeto'); | ||
| 131 | + | ||
| 132 | + hijos = hijosData || []; | ||
| 133 | + } | ||
| 134 | + // subpartida no tiene hijos | ||
| 135 | + | ||
| 136 | + console.timeEnd('[SERVER] Query hijos'); | ||
| 137 | + | ||
| 138 | + console.timeEnd('[SERVER] Total load objeto'); | ||
| 139 | + return { | ||
| 140 | + objeto, | ||
| 141 | + padres, | ||
| 142 | + hijos | ||
| 143 | + }; | ||
| 144 | +} |
src/routes/test/layout/[codigo]/+page.svelte
0 → 100644
This diff is collapsed. Click to expand it.
static/gap.png
0 → 100644
380 KB
-
Please register or login to post a comment