Showing
21 changed files
with
739 additions
and
381 deletions
| ... | @@ -228,3 +228,145 @@ body { | ... | @@ -228,3 +228,145 @@ body { |
| 228 | .font-display { | 228 | .font-display { |
| 229 | font-family: var(--font-display); | 229 | font-family: var(--font-display); |
| 230 | } | 230 | } |
| 231 | + | ||
| 232 | +/* ============================================ | ||
| 233 | + FALLBACK LAYOUT UTILITIES | ||
| 234 | + Respaldo para asegurar que flex siempre funcione | ||
| 235 | + ============================================ */ | ||
| 236 | + | ||
| 237 | +/* Forzar flex en contenedores principales */ | ||
| 238 | +.flex { | ||
| 239 | + display: flex !important; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +.flex-1 { | ||
| 243 | + flex: 1 1 0% !important; | ||
| 244 | +} | ||
| 245 | + | ||
| 246 | +.flex-col { | ||
| 247 | + flex-direction: column !important; | ||
| 248 | +} | ||
| 249 | + | ||
| 250 | +.flex-row { | ||
| 251 | + flex-direction: row !important; | ||
| 252 | +} | ||
| 253 | + | ||
| 254 | +.flex-wrap { | ||
| 255 | + flex-wrap: wrap !important; | ||
| 256 | +} | ||
| 257 | + | ||
| 258 | +.flex-shrink-0 { | ||
| 259 | + flex-shrink: 0 !important; | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +.items-center { | ||
| 263 | + align-items: center !important; | ||
| 264 | +} | ||
| 265 | + | ||
| 266 | +.items-start { | ||
| 267 | + align-items: flex-start !important; | ||
| 268 | +} | ||
| 269 | + | ||
| 270 | +.justify-center { | ||
| 271 | + justify-content: center !important; | ||
| 272 | +} | ||
| 273 | + | ||
| 274 | +.justify-between { | ||
| 275 | + justify-content: space-between !important; | ||
| 276 | +} | ||
| 277 | + | ||
| 278 | +.gap-1 { gap: 0.25rem !important; } | ||
| 279 | +.gap-2 { gap: 0.5rem !important; } | ||
| 280 | +.gap-3 { gap: 0.75rem !important; } | ||
| 281 | +.gap-4 { gap: 1rem !important; } | ||
| 282 | +.gap-6 { gap: 1.5rem !important; } | ||
| 283 | + | ||
| 284 | +/* Grid fallbacks */ | ||
| 285 | +.grid { | ||
| 286 | + display: grid !important; | ||
| 287 | +} | ||
| 288 | + | ||
| 289 | +/* Hidden utilities */ | ||
| 290 | +.hidden { | ||
| 291 | + display: none !important; | ||
| 292 | +} | ||
| 293 | + | ||
| 294 | +/* Responsive: mostrar en lg+ */ | ||
| 295 | +@media (min-width: 1024px) { | ||
| 296 | + .lg\:flex { | ||
| 297 | + display: flex !important; | ||
| 298 | + } | ||
| 299 | + .lg\:block { | ||
| 300 | + display: block !important; | ||
| 301 | + } | ||
| 302 | + .lg\:hidden { | ||
| 303 | + display: none !important; | ||
| 304 | + } | ||
| 305 | + .lg\:relative { | ||
| 306 | + position: relative !important; | ||
| 307 | + } | ||
| 308 | + .lg\:translate-x-0 { | ||
| 309 | + transform: translateX(0) !important; | ||
| 310 | + } | ||
| 311 | +} | ||
| 312 | + | ||
| 313 | +@media (min-width: 1280px) { | ||
| 314 | + .xl\:block { | ||
| 315 | + display: block !important; | ||
| 316 | + } | ||
| 317 | + .xl\:hidden { | ||
| 318 | + display: none !important; | ||
| 319 | + } | ||
| 320 | +} | ||
| 321 | + | ||
| 322 | +/* ============================================ | ||
| 323 | + CLASIFICADORES LAYOUT - ESTILOS GLOBALES | ||
| 324 | + Forzar layout correcto en todas las páginas | ||
| 325 | + ============================================ */ | ||
| 326 | + | ||
| 327 | +.clasificador-layout { | ||
| 328 | + display: flex !important; | ||
| 329 | + flex-direction: row !important; | ||
| 330 | +} | ||
| 331 | + | ||
| 332 | +.clasificador-layout > .sidebar-left { | ||
| 333 | + position: relative !important; | ||
| 334 | + transform: translateX(0) !important; | ||
| 335 | + flex-shrink: 0 !important; | ||
| 336 | + width: 18rem !important; | ||
| 337 | + z-index: auto !important; | ||
| 338 | + box-shadow: none !important; | ||
| 339 | +} | ||
| 340 | + | ||
| 341 | +.clasificador-layout > main { | ||
| 342 | + flex: 1 1 0% !important; | ||
| 343 | + min-width: 0 !important; | ||
| 344 | +} | ||
| 345 | + | ||
| 346 | +/* Forzar estilos correctos después del mount (para navegación cliente) */ | ||
| 347 | +@media (min-width: 1024px) { | ||
| 348 | + .sidebar-mounted.sidebar-left { | ||
| 349 | + position: relative !important; | ||
| 350 | + transform: translateX(0) !important; | ||
| 351 | + flex-shrink: 0 !important; | ||
| 352 | + z-index: auto !important; | ||
| 353 | + box-shadow: none !important; | ||
| 354 | + } | ||
| 355 | +} | ||
| 356 | + | ||
| 357 | +@media (max-width: 1023px) { | ||
| 358 | + .clasificador-layout { | ||
| 359 | + display: block !important; | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + .clasificador-layout > .sidebar-left { | ||
| 363 | + position: fixed !important; | ||
| 364 | + transform: translateX(-100%) !important; | ||
| 365 | + width: 20rem !important; | ||
| 366 | + z-index: 50 !important; | ||
| 367 | + } | ||
| 368 | + | ||
| 369 | + .clasificador-layout > .sidebar-left.translate-x-0 { | ||
| 370 | + transform: translateX(0) !important; | ||
| 371 | + } | ||
| 372 | +} | ... | ... |
| ... | @@ -17,7 +17,7 @@ | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | ||
| 18 | %sveltekit.head% | 18 | %sveltekit.head% |
| 19 | </head> | 19 | </head> |
| 20 | - <body data-sveltekit-preload-data="hover"> | 20 | + <body data-sveltekit-preload-data="off"> |
| 21 | <div style="display: contents">%sveltekit.body%</div> | 21 | <div style="display: contents">%sveltekit.body%</div> |
| 22 | </body> | 22 | </body> |
| 23 | </html> | 23 | </html> | ... | ... |
| ... | @@ -33,7 +33,12 @@ | ... | @@ -33,7 +33,12 @@ |
| 33 | 33 | ||
| 34 | // Dimensiones del área del gráfico | 34 | // Dimensiones del área del gráfico |
| 35 | let effectiveHeight = $derived(fill ? measuredHeight : height); | 35 | let effectiveHeight = $derived(fill ? measuredHeight : height); |
| 36 | - let chartHeight = $derived(effectiveHeight - marginTop - marginBottom); | 36 | + let chartHeight = $derived(Math.max(effectiveHeight - marginTop - marginBottom, 50)); |
| 37 | + | ||
| 38 | + // Máximo del eje Y (con guard para data vacía o valores undefined) | ||
| 39 | + let maxPerCapita = $derived( | ||
| 40 | + data.length > 0 ? Math.max(...data.map(d => d.perCapita || 0), 1) : 1 | ||
| 41 | + ); | ||
| 37 | 42 | ||
| 38 | // Escalas D3 | 43 | // Escalas D3 |
| 39 | let xScale = $derived( | 44 | let xScale = $derived( |
| ... | @@ -46,7 +51,7 @@ | ... | @@ -46,7 +51,7 @@ |
| 46 | // Para CSS bottom positioning: 0 → 0%, max → 100% | 51 | // Para CSS bottom positioning: 0 → 0%, max → 100% |
| 47 | let yScale = $derived( | 52 | let yScale = $derived( |
| 48 | scaleLinear() | 53 | scaleLinear() |
| 49 | - .domain([0, Math.max(...data.map(d => d.perCapita))]) | 54 | + .domain([0, maxPerCapita]) |
| 50 | .range([0, chartHeight]) | 55 | .range([0, chartHeight]) |
| 51 | .nice() | 56 | .nice() |
| 52 | ); | 57 | ); |
| ... | @@ -65,7 +70,8 @@ | ... | @@ -65,7 +70,8 @@ |
| 65 | } | 70 | } |
| 66 | </script> | 71 | </script> |
| 67 | 72 | ||
| 68 | -<div class="chart-wrapper" bind:this={wrapperEl} style="height: {fill ? '100%' : height + 'px'}"> | 73 | +<div class="chart-wrapper" bind:this={wrapperEl} style="height: {fill ? '100%' : height + 'px'}; min-height: {height}px"> |
| 74 | + {#if data.length > 0 && chartHeight > 0} | ||
| 69 | <!-- Contenedor principal con márgenes --> | 75 | <!-- Contenedor principal con márgenes --> |
| 70 | <div class="chart-inner" style="top: {marginTop}px; bottom: {marginBottom}px; left: {marginLeft}px; right: {marginRight}px"> | 76 | <div class="chart-inner" style="top: {marginTop}px; bottom: {marginBottom}px; left: {marginLeft}px; right: {marginRight}px"> |
| 71 | 77 | ||
| ... | @@ -118,6 +124,11 @@ | ... | @@ -118,6 +124,11 @@ |
| 118 | </span> | 124 | </span> |
| 119 | {/each} | 125 | {/each} |
| 120 | </div> | 126 | </div> |
| 127 | + {:else} | ||
| 128 | + <div class="chart-empty"> | ||
| 129 | + <span>Sin datos</span> | ||
| 130 | + </div> | ||
| 131 | + {/if} | ||
| 121 | </div> | 132 | </div> |
| 122 | 133 | ||
| 123 | <style> | 134 | <style> |
| ... | @@ -210,4 +221,15 @@ | ... | @@ -210,4 +221,15 @@ |
| 210 | .x-label.visible { | 221 | .x-label.visible { |
| 211 | opacity: 1; | 222 | opacity: 1; |
| 212 | } | 223 | } |
| 224 | + | ||
| 225 | + .chart-empty { | ||
| 226 | + position: absolute; | ||
| 227 | + inset: 0; | ||
| 228 | + display: flex; | ||
| 229 | + align-items: center; | ||
| 230 | + justify-content: center; | ||
| 231 | + color: var(--theme-texto); | ||
| 232 | + opacity: 0.5; | ||
| 233 | + font-size: 0.875rem; | ||
| 234 | + } | ||
| 213 | </style> | 235 | </style> | ... | ... |
| 1 | <script> | 1 | <script> |
| 2 | import { goto } from '$app/navigation'; | 2 | import { goto } from '$app/navigation'; |
| 3 | - import { | 3 | + import { indexLoaded } from '$lib/stores/searchStore'; |
| 4 | - query, | 4 | + import { search } from '$lib/services/search'; |
| 5 | - results, | ||
| 6 | - isLoading as searchLoading, | ||
| 7 | - indexLoaded, | ||
| 8 | - selectedIndex, | ||
| 9 | - performSearch, | ||
| 10 | - clearSearch, | ||
| 11 | - navigateResults | ||
| 12 | - } from '$lib/stores/searchStore'; | ||
| 13 | 5 | ||
| 14 | let { | 6 | let { |
| 15 | preserveVista = false, | 7 | preserveVista = false, |
| ... | @@ -19,19 +11,23 @@ | ... | @@ -19,19 +11,23 @@ |
| 19 | let searchInputRef = $state(null); | 11 | let searchInputRef = $state(null); |
| 20 | let searchVal = $state(''); | 12 | let searchVal = $state(''); |
| 21 | let searchFocused = $state(false); | 13 | let searchFocused = $state(false); |
| 14 | + let isSearching = $state(false); | ||
| 15 | + let localResults = $state([]); | ||
| 16 | + let selectedIdx = $state(-1); | ||
| 22 | let debounceTimer; | 17 | let debounceTimer; |
| 23 | 18 | ||
| 24 | - // Filtrar solo objeto_gasto | ||
| 25 | - let filteredSearchResults = $derived($results.filter(r => r.tipo === 'objeto_gasto')); | ||
| 26 | - | ||
| 27 | function handleSearchInput(e) { | 19 | function handleSearchInput(e) { |
| 28 | const val = e.target.value; | 20 | const val = e.target.value; |
| 29 | clearTimeout(debounceTimer); | 21 | clearTimeout(debounceTimer); |
| 30 | debounceTimer = setTimeout(() => { | 22 | debounceTimer = setTimeout(() => { |
| 31 | if (val.length >= 2) { | 23 | if (val.length >= 2) { |
| 32 | - performSearch(val); | 24 | + isSearching = true; |
| 25 | + // Buscar y filtrar solo objetos de gasto | ||
| 26 | + const allResults = search(val, 50); | ||
| 27 | + localResults = allResults.filter(r => r.tipo === 'objeto_gasto').slice(0, 15); | ||
| 28 | + isSearching = false; | ||
| 33 | } else { | 29 | } else { |
| 34 | - clearSearch(); | 30 | + localResults = []; |
| 35 | } | 31 | } |
| 36 | }, 200); | 32 | }, 200); |
| 37 | } | 33 | } |
| ... | @@ -39,14 +35,18 @@ | ... | @@ -39,14 +35,18 @@ |
| 39 | function handleSearchKeydown(e) { | 35 | function handleSearchKeydown(e) { |
| 40 | if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { | 36 | if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { |
| 41 | e.preventDefault(); | 37 | e.preventDefault(); |
| 42 | - navigateResults(e.key === 'ArrowDown' ? 1 : -1, filteredSearchResults.length); | 38 | + if (e.key === 'ArrowDown') { |
| 43 | - } else if (e.key === 'Enter' && filteredSearchResults.length > 0) { | 39 | + selectedIdx = selectedIdx < localResults.length - 1 ? selectedIdx + 1 : 0; |
| 40 | + } else { | ||
| 41 | + selectedIdx = selectedIdx > 0 ? selectedIdx - 1 : localResults.length - 1; | ||
| 42 | + } | ||
| 43 | + } else if (e.key === 'Enter' && localResults.length > 0) { | ||
| 44 | e.preventDefault(); | 44 | e.preventDefault(); |
| 45 | - const selected = filteredSearchResults[$selectedIndex]; | 45 | + const selected = localResults[selectedIdx >= 0 ? selectedIdx : 0]; |
| 46 | if (selected) handleSearchSelect(selected); | 46 | if (selected) handleSearchSelect(selected); |
| 47 | } else if (e.key === 'Escape') { | 47 | } else if (e.key === 'Escape') { |
| 48 | searchVal = ''; | 48 | searchVal = ''; |
| 49 | - clearSearch(); | 49 | + localResults = []; |
| 50 | searchInputRef?.blur(); | 50 | searchInputRef?.blur(); |
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| ... | @@ -57,7 +57,7 @@ | ... | @@ -57,7 +57,7 @@ |
| 57 | : `/objeto/${result.codigo}`; | 57 | : `/objeto/${result.codigo}`; |
| 58 | goto(url); | 58 | goto(url); |
| 59 | searchVal = ''; | 59 | searchVal = ''; |
| 60 | - clearSearch(); | 60 | + localResults = []; |
| 61 | searchFocused = false; | 61 | searchFocused = false; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| ... | @@ -68,7 +68,7 @@ | ... | @@ -68,7 +68,7 @@ |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | function handleClear() { | 70 | function handleClear() { |
| 71 | - clearSearch(); | 71 | + localResults = []; |
| 72 | searchVal = ''; | 72 | searchVal = ''; |
| 73 | } | 73 | } |
| 74 | </script> | 74 | </script> |
| ... | @@ -97,17 +97,17 @@ | ... | @@ -97,17 +97,17 @@ |
| 97 | {/if} | 97 | {/if} |
| 98 | {#if searchFocused && searchVal.length >= 2} | 98 | {#if searchFocused && searchVal.length >= 2} |
| 99 | <div class="search-dropdown"> | 99 | <div class="search-dropdown"> |
| 100 | - {#if $searchLoading} | 100 | + {#if isSearching} |
| 101 | <div class="search-msg">Buscando...</div> | 101 | <div class="search-msg">Buscando...</div> |
| 102 | - {:else if filteredSearchResults.length === 0} | 102 | + {:else if localResults.length === 0} |
| 103 | <div class="search-msg">Sin resultados</div> | 103 | <div class="search-msg">Sin resultados</div> |
| 104 | {:else} | 104 | {:else} |
| 105 | - {#each filteredSearchResults as result, i} | 105 | + {#each localResults as result, i} |
| 106 | <button | 106 | <button |
| 107 | class="search-item" | 107 | class="search-item" |
| 108 | - class:selected={$selectedIndex === i} | 108 | + class:selected={selectedIdx === i} |
| 109 | onclick={() => handleSearchSelect(result)} | 109 | onclick={() => handleSearchSelect(result)} |
| 110 | - onmouseenter={() => selectedIndex.set(i)} | 110 | + onmouseenter={() => selectedIdx = i} |
| 111 | > | 111 | > |
| 112 | <span class="item-code">{result.codigo}</span> | 112 | <span class="item-code">{result.codigo}</span> |
| 113 | <span class="item-name">{result.nombre}</span> | 113 | <span class="item-name">{result.nombre}</span> | ... | ... |
This diff is collapsed. Click to expand it.
src/lib/components/ui/SearchModal.svelte
0 → 100644
This diff is collapsed. Click to expand it.
| ... | @@ -54,7 +54,7 @@ export async function initSearchIndex() { | ... | @@ -54,7 +54,7 @@ export async function initSearchIndex() { |
| 54 | const { data: rubros, error: errorRubros } = await supabase | 54 | const { data: rubros, error: errorRubros } = await supabase |
| 55 | .schema('ppto') | 55 | .schema('ppto') |
| 56 | .from('clas_rubros') | 56 | .from('clas_rubros') |
| 57 | - .select('rubro, desc_rubros, nivel'); | 57 | + .select('rubro, desc_rubro, nivel'); |
| 58 | 58 | ||
| 59 | if (errorRubros) { | 59 | if (errorRubros) { |
| 60 | console.error('Error cargando rubros:', errorRubros); | 60 | console.error('Error cargando rubros:', errorRubros); |
| ... | @@ -93,11 +93,11 @@ export async function initSearchIndex() { | ... | @@ -93,11 +93,11 @@ export async function initSearchIndex() { |
| 93 | const rubrosIndex = rubros.map(item => ({ | 93 | const rubrosIndex = rubros.map(item => ({ |
| 94 | tipo: 'rubro', | 94 | tipo: 'rubro', |
| 95 | codigo: item.rubro, | 95 | codigo: item.rubro, |
| 96 | - nombre: item.desc_rubros, | 96 | + nombre: item.desc_rubro, |
| 97 | sigla: null, | 97 | sigla: null, |
| 98 | contexto: `Rubro · ${nivelLabelsRubros[item.nivel] || item.nivel}`, | 98 | contexto: `Rubro · ${nivelLabelsRubros[item.nivel] || item.nivel}`, |
| 99 | nivel: item.nivel, | 99 | nivel: item.nivel, |
| 100 | - nombre_normalizado: normalizeText(item.desc_rubros), | 100 | + nombre_normalizado: normalizeText(item.desc_rubro), |
| 101 | sigla_normalizada: '', | 101 | sigla_normalizada: '', |
| 102 | codigo_normalizado: item.rubro?.toString() || '' | 102 | codigo_normalizado: item.rubro?.toString() || '' |
| 103 | })); | 103 | })); | ... | ... |
| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | import favicon from '$lib/assets/favicon.svg'; | 4 | import favicon from '$lib/assets/favicon.svg'; |
| 5 | import Navbar from '$lib/components/ui/Navbar.svelte'; | 5 | import Navbar from '$lib/components/ui/Navbar.svelte'; |
| 6 | import NavigationDrawer from '$lib/components/layout/NavigationDrawer.svelte'; | 6 | import NavigationDrawer from '$lib/components/layout/NavigationDrawer.svelte'; |
| 7 | + import SearchModal from '$lib/components/ui/SearchModal.svelte'; | ||
| 7 | import { openDrawer } from '$lib/stores/drawer.js'; | 8 | import { openDrawer } from '$lib/stores/drawer.js'; |
| 8 | import Spinner from '$lib/components/ui/Spinner.svelte'; | 9 | import Spinner from '$lib/components/ui/Spinner.svelte'; |
| 9 | 10 | ||
| ... | @@ -12,6 +13,21 @@ | ... | @@ -12,6 +13,21 @@ |
| 12 | // Don't show navbar on landing page | 13 | // Don't show navbar on landing page |
| 13 | let isLanding = $derived($page.url.pathname === '/'); | 14 | let isLanding = $derived($page.url.pathname === '/'); |
| 14 | 15 | ||
| 16 | + // Global search modal state | ||
| 17 | + let searchModalOpen = $state(false); | ||
| 18 | + | ||
| 19 | + function openSearchModal() { | ||
| 20 | + searchModalOpen = true; | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + function handleGlobalKeydown(e) { | ||
| 24 | + // Cmd+K or Ctrl+K to open search | ||
| 25 | + if ((e.metaKey || e.ctrlKey) && e.key === 'k') { | ||
| 26 | + e.preventDefault(); | ||
| 27 | + searchModalOpen = true; | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | + | ||
| 15 | // Navigation loading state | 31 | // Navigation loading state |
| 16 | let showLoader = $state(false); | 32 | let showLoader = $state(false); |
| 17 | let loaderTimeout = null; | 33 | let loaderTimeout = null; |
| ... | @@ -42,12 +58,17 @@ | ... | @@ -42,12 +58,17 @@ |
| 42 | <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600&display=swap" rel="stylesheet" /> | 58 | <link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600&display=swap" rel="stylesheet" /> |
| 43 | </svelte:head> | 59 | </svelte:head> |
| 44 | 60 | ||
| 61 | +<svelte:window onkeydown={handleGlobalKeydown} /> | ||
| 62 | + | ||
| 45 | <!-- Navigation Drawer (siempre presente) --> | 63 | <!-- Navigation Drawer (siempre presente) --> |
| 46 | <NavigationDrawer /> | 64 | <NavigationDrawer /> |
| 47 | 65 | ||
| 66 | +<!-- Global Search Modal --> | ||
| 67 | +<SearchModal bind:open={searchModalOpen} /> | ||
| 68 | + | ||
| 48 | <!-- Floating controls bar (fixed position - no afecta el flujo) --> | 69 | <!-- Floating controls bar (fixed position - no afecta el flujo) --> |
| 49 | {#if !isLanding} | 70 | {#if !isLanding} |
| 50 | - <Navbar onOpenDrawer={openDrawer} /> | 71 | + <Navbar onOpenDrawer={openDrawer} onOpenSearch={openSearchModal} /> |
| 51 | {/if} | 72 | {/if} |
| 52 | 73 | ||
| 53 | <!-- Navigation loading overlay --> | 74 | <!-- Navigation loading overlay --> | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -28,6 +28,11 @@ | ... | @@ -28,6 +28,11 @@ |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | onMount(async () => { | 30 | onMount(async () => { |
| 31 | + // Forzar recálculo de layout para navegación cliente | ||
| 32 | + requestAnimationFrame(() => { | ||
| 33 | + document.body.offsetHeight; // Force reflow | ||
| 34 | + }); | ||
| 35 | + | ||
| 31 | const { data, error } = await supabase | 36 | const { data, error } = await supabase |
| 32 | .schema('ppto') | 37 | .schema('ppto') |
| 33 | .from('clas_institucional') | 38 | .from('clas_institucional') |
| ... | @@ -307,7 +312,7 @@ | ... | @@ -307,7 +312,7 @@ |
| 307 | </button> | 312 | </button> |
| 308 | </div> | 313 | </div> |
| 309 | 314 | ||
| 310 | - <div class="max-w-screen-xl mx-auto flex px-4"> | 315 | + <div class="clasificador-layout max-w-screen-xl mx-auto flex px-4" style="display: flex !important; flex-direction: row;"> |
| 311 | <!-- Sidebar izquierda: Áreas --> | 316 | <!-- Sidebar izquierda: Áreas --> |
| 312 | <!-- En móvil: overlay, en desktop: sidebar fijo --> | 317 | <!-- En móvil: overlay, en desktop: sidebar fijo --> |
| 313 | {#if sidebarOpen} | 318 | {#if sidebarOpen} |
| ... | @@ -611,4 +616,33 @@ | ... | @@ -611,4 +616,33 @@ |
| 611 | background-color: transparent; | 616 | background-color: transparent; |
| 612 | } | 617 | } |
| 613 | } | 618 | } |
| 619 | + | ||
| 620 | + /* Layout principal - fallback nativo */ | ||
| 621 | + .clasificador-layout { | ||
| 622 | + display: flex !important; | ||
| 623 | + flex-direction: row !important; | ||
| 624 | + } | ||
| 625 | + | ||
| 626 | + /* Sidebar - fallback para responsive */ | ||
| 627 | + .sidebar-left { | ||
| 628 | + position: fixed; | ||
| 629 | + transform: translateX(-100%); | ||
| 630 | + } | ||
| 631 | + | ||
| 632 | + @media (min-width: 1024px) { | ||
| 633 | + .sidebar-left { | ||
| 634 | + position: relative !important; | ||
| 635 | + transform: translateX(0) !important; | ||
| 636 | + flex-shrink: 0; | ||
| 637 | + width: 16rem; | ||
| 638 | + z-index: auto !important; | ||
| 639 | + box-shadow: none !important; | ||
| 640 | + } | ||
| 641 | + } | ||
| 642 | + | ||
| 643 | + @media (max-width: 1023px) { | ||
| 644 | + .clasificador-layout { | ||
| 645 | + display: block !important; | ||
| 646 | + } | ||
| 647 | + } | ||
| 614 | </style> | 648 | </style> | ... | ... |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
src/routes/finfun/[codigo]/+page.server.js
0 → 100644
| 1 | +import { supabase } from '$lib/supabase'; | ||
| 2 | +import { error } from '@sveltejs/kit'; | ||
| 3 | + | ||
| 4 | +// Funciones para derivar jerarquía del código finfun | ||
| 5 | +// Jerarquía: Finalidad (1 dígito) → Grupo Función (2 dígitos) → Función (3+ dígitos) | ||
| 6 | +function getFinalidadCode(finfun) { | ||
| 7 | + return finfun.charAt(0); | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +function getGrpFuncionCode(finfun) { | ||
| 11 | + return finfun.substring(0, 2); | ||
| 12 | +} | ||
| 13 | + | ||
| 14 | +function getNivel(finfun) { | ||
| 15 | + if (finfun.length === 1) return 'finalidad'; | ||
| 16 | + if (finfun.length === 2) return 'grpfuncion'; | ||
| 17 | + return 'funcion'; | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +export async function load({ params }) { | ||
| 21 | + console.time('[SERVER] Total load finfun'); | ||
| 22 | + const { codigo } = params; | ||
| 23 | + | ||
| 24 | + console.time('[SERVER] Query clas_finfun'); | ||
| 25 | + const { data, error: dbError } = await supabase | ||
| 26 | + .schema('ppto') | ||
| 27 | + .from('clas_finfun') | ||
| 28 | + .select('*') | ||
| 29 | + .eq('finfun', codigo); | ||
| 30 | + console.timeEnd('[SERVER] Query clas_finfun'); | ||
| 31 | + | ||
| 32 | + if (dbError || !data || data.length === 0) { | ||
| 33 | + throw error(404, 'Finalidad/Función no encontrada'); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + // Tomar el primer resultado | ||
| 37 | + const finfun = data[0]; | ||
| 38 | + const nivel = finfun.nivel || getNivel(codigo); | ||
| 39 | + | ||
| 40 | + // Obtener jerarquía (padres e hijos) | ||
| 41 | + let padres = []; | ||
| 42 | + let hijos = []; | ||
| 43 | + | ||
| 44 | + console.time('[SERVER] Query padres'); | ||
| 45 | + | ||
| 46 | + // Buscar padres según nivel | ||
| 47 | + if (nivel === 'funcion') { | ||
| 48 | + // Padres: finalidad y grupo función | ||
| 49 | + const finalidadCode = getFinalidadCode(codigo); | ||
| 50 | + const grpFuncionCode = getGrpFuncionCode(codigo); | ||
| 51 | + | ||
| 52 | + const { data: padresData } = await supabase | ||
| 53 | + .schema('ppto') | ||
| 54 | + .from('clas_finfun') | ||
| 55 | + .select('*') | ||
| 56 | + .in('finfun', [finalidadCode, grpFuncionCode]) | ||
| 57 | + .order('finfun'); | ||
| 58 | + | ||
| 59 | + if (padresData) padres = padresData; | ||
| 60 | + } else if (nivel === 'grpfuncion') { | ||
| 61 | + // Padre: finalidad | ||
| 62 | + const finalidadCode = getFinalidadCode(codigo); | ||
| 63 | + | ||
| 64 | + const { data: padresData } = await supabase | ||
| 65 | + .schema('ppto') | ||
| 66 | + .from('clas_finfun') | ||
| 67 | + .select('*') | ||
| 68 | + .eq('finfun', finalidadCode); | ||
| 69 | + | ||
| 70 | + if (padresData) padres = padresData; | ||
| 71 | + } | ||
| 72 | + // finalidad no tiene padres | ||
| 73 | + | ||
| 74 | + console.timeEnd('[SERVER] Query padres'); | ||
| 75 | + | ||
| 76 | + console.time('[SERVER] Query hijos'); | ||
| 77 | + | ||
| 78 | + // Buscar hijos según nivel | ||
| 79 | + if (nivel === 'finalidad') { | ||
| 80 | + // Hijos: grupos de función que empiecen con el mismo dígito | ||
| 81 | + const { data: hijosData } = await supabase | ||
| 82 | + .schema('ppto') | ||
| 83 | + .from('clas_finfun') | ||
| 84 | + .select('*') | ||
| 85 | + .eq('nivel', 'grpfuncion') | ||
| 86 | + .like('finfun', `${codigo}%`) | ||
| 87 | + .order('finfun'); | ||
| 88 | + | ||
| 89 | + hijos = hijosData || []; | ||
| 90 | + } else if (nivel === 'grpfuncion') { | ||
| 91 | + // Hijos: funciones que empiecen con los mismos 2 dígitos | ||
| 92 | + const { data: hijosData } = await supabase | ||
| 93 | + .schema('ppto') | ||
| 94 | + .from('clas_finfun') | ||
| 95 | + .select('*') | ||
| 96 | + .eq('nivel', 'funcion') | ||
| 97 | + .like('finfun', `${codigo}%`) | ||
| 98 | + .order('finfun'); | ||
| 99 | + | ||
| 100 | + hijos = hijosData || []; | ||
| 101 | + } | ||
| 102 | + // funcion no tiene hijos | ||
| 103 | + | ||
| 104 | + console.timeEnd('[SERVER] Query hijos'); | ||
| 105 | + | ||
| 106 | + console.timeEnd('[SERVER] Total load finfun'); | ||
| 107 | + return { | ||
| 108 | + finfun, | ||
| 109 | + padres, | ||
| 110 | + hijos | ||
| 111 | + }; | ||
| 112 | +} |
src/routes/finfun/[codigo]/+page.svelte
0 → 100644
This diff could not be displayed because it is too large.
| 1 | import { supabase } from '$lib/supabase'; | 1 | import { supabase } from '$lib/supabase'; |
| 2 | import { error } from '@sveltejs/kit'; | 2 | import { error } from '@sveltejs/kit'; |
| 3 | 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 | + | ||
| 4 | export async function load({ params }) { | 24 | export async function load({ params }) { |
| 5 | console.time('[SERVER] Total load objeto'); | 25 | console.time('[SERVER] Total load objeto'); |
| 6 | const { codigo } = params; | 26 | const { codigo } = params; |
| ... | @@ -17,95 +37,102 @@ export async function load({ params }) { | ... | @@ -17,95 +37,102 @@ export async function load({ params }) { |
| 17 | throw error(404, 'Objeto no encontrado'); | 37 | throw error(404, 'Objeto no encontrado'); |
| 18 | } | 38 | } |
| 19 | 39 | ||
| 20 | - // Tomar el primer resultado (puede haber duplicados) | 40 | + // Tomar el primer resultado |
| 21 | const objeto = data[0]; | 41 | const objeto = data[0]; |
| 42 | + const nivel = objeto.nivel || getNivel(codigo); | ||
| 22 | 43 | ||
| 23 | // Obtener jerarquía (padres e hijos) | 44 | // Obtener jerarquía (padres e hijos) |
| 24 | let padres = []; | 45 | let padres = []; |
| 25 | let hijos = []; | 46 | let hijos = []; |
| 26 | 47 | ||
| 27 | console.time('[SERVER] Query padres'); | 48 | console.time('[SERVER] Query padres'); |
| 28 | - // Buscar padre según nivel | 49 | + |
| 29 | - if (objeto.nivel === 'subpartida') { | 50 | + // Buscar padres según nivel |
| 30 | - // Padre es partida | 51 | + if (nivel === 'subpartida') { |
| 31 | - const { data: padreData } = await supabase | 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 | ||
| 32 | .schema('ppto') | 58 | .schema('ppto') |
| 33 | .from('clas_objetos') | 59 | .from('clas_objetos') |
| 34 | .select('*') | 60 | .select('*') |
| 35 | - .eq('nivel', 'partida') | 61 | + .in('objeto', [grupoCode, subgrupoCode, partidaCode]) |
| 36 | - .eq('grupo', objeto.grupo) | 62 | + .order('objeto'); |
| 37 | - .eq('subgrupo', objeto.subgrupo) | ||
| 38 | - .eq('partida', objeto.partida); | ||
| 39 | - if (padreData?.length) padres.push(padreData[0]); | ||
| 40 | - } | ||
| 41 | 63 | ||
| 42 | - if (objeto.nivel === 'partida' || objeto.nivel === 'subpartida') { | 64 | + if (padresData) padres = padresData; |
| 43 | - // Padre es subgrupo | 65 | + } else if (nivel === 'partida') { |
| 44 | - const { data: padreData } = await supabase | 66 | + // Padres: grupo, subgrupo |
| 67 | + const grupoCode = getGrupoCode(codigo); | ||
| 68 | + const subgrupoCode = getSubgrupoCode(codigo); | ||
| 69 | + | ||
| 70 | + const { data: padresData } = await supabase | ||
| 45 | .schema('ppto') | 71 | .schema('ppto') |
| 46 | .from('clas_objetos') | 72 | .from('clas_objetos') |
| 47 | .select('*') | 73 | .select('*') |
| 48 | - .eq('nivel', 'subgrupo') | 74 | + .in('objeto', [grupoCode, subgrupoCode]) |
| 49 | - .eq('grupo', objeto.grupo) | 75 | + .order('objeto'); |
| 50 | - .eq('subgrupo', objeto.subgrupo); | 76 | + |
| 51 | - if (padreData?.length) padres.unshift(padreData[0]); | 77 | + if (padresData) padres = padresData; |
| 52 | - } | 78 | + } else if (nivel === 'subgrupo') { |
| 79 | + // Padre: grupo | ||
| 80 | + const grupoCode = getGrupoCode(codigo); | ||
| 53 | 81 | ||
| 54 | - if (objeto.nivel !== 'grupo') { | 82 | + const { data: padresData } = await supabase |
| 55 | - // Padre es grupo | ||
| 56 | - const grupoCodigo = objeto.grupo + '0000'; | ||
| 57 | - const { data: padreData } = await supabase | ||
| 58 | .schema('ppto') | 83 | .schema('ppto') |
| 59 | .from('clas_objetos') | 84 | .from('clas_objetos') |
| 60 | .select('*') | 85 | .select('*') |
| 61 | - .eq('nivel', 'grupo') | 86 | + .eq('objeto', grupoCode); |
| 62 | - .eq('objeto', grupoCodigo); | 87 | + |
| 63 | - if (padreData?.length) padres.unshift(padreData[0]); | 88 | + if (padresData) padres = padresData; |
| 64 | } | 89 | } |
| 90 | + // grupo no tiene padres | ||
| 91 | + | ||
| 65 | console.timeEnd('[SERVER] Query padres'); | 92 | console.timeEnd('[SERVER] Query padres'); |
| 66 | 93 | ||
| 67 | console.time('[SERVER] Query hijos'); | 94 | console.time('[SERVER] Query hijos'); |
| 95 | + | ||
| 68 | // Buscar hijos según nivel | 96 | // Buscar hijos según nivel |
| 69 | - if (objeto.nivel === 'grupo') { | 97 | + if (nivel === 'grupo') { |
| 98 | + // Hijos: subgrupos que empiecen con el mismo dígito | ||
| 99 | + const prefix = codigo.charAt(0); | ||
| 70 | const { data: hijosData } = await supabase | 100 | const { data: hijosData } = await supabase |
| 71 | .schema('ppto') | 101 | .schema('ppto') |
| 72 | .from('clas_objetos') | 102 | .from('clas_objetos') |
| 73 | .select('*') | 103 | .select('*') |
| 74 | .eq('nivel', 'subgrupo') | 104 | .eq('nivel', 'subgrupo') |
| 75 | - .eq('grupo', objeto.grupo) | 105 | + .like('objeto', `${prefix}%`) |
| 76 | .order('objeto'); | 106 | .order('objeto'); |
| 77 | - hijos = hijosData?.reduce((acc, item) => { | 107 | + |
| 78 | - if (!acc.find(h => h.objeto === item.objeto)) acc.push(item); | 108 | + hijos = hijosData || []; |
| 79 | - return acc; | 109 | + } else if (nivel === 'subgrupo') { |
| 80 | - }, []) || []; | 110 | + // Hijos: partidas que empiecen con los mismos 2 dígitos |
| 81 | - } else if (objeto.nivel === 'subgrupo') { | 111 | + const prefix = codigo.substring(0, 2); |
| 82 | const { data: hijosData } = await supabase | 112 | const { data: hijosData } = await supabase |
| 83 | .schema('ppto') | 113 | .schema('ppto') |
| 84 | .from('clas_objetos') | 114 | .from('clas_objetos') |
| 85 | .select('*') | 115 | .select('*') |
| 86 | .eq('nivel', 'partida') | 116 | .eq('nivel', 'partida') |
| 87 | - .eq('grupo', objeto.grupo) | 117 | + .like('objeto', `${prefix}%`) |
| 88 | - .eq('subgrupo', objeto.subgrupo) | ||
| 89 | .order('objeto'); | 118 | .order('objeto'); |
| 90 | - hijos = hijosData?.reduce((acc, item) => { | 119 | + |
| 91 | - if (!acc.find(h => h.objeto === item.objeto)) acc.push(item); | 120 | + hijos = hijosData || []; |
| 92 | - return acc; | 121 | + } else if (nivel === 'partida') { |
| 93 | - }, []) || []; | 122 | + // Hijos: subpartidas que empiecen con los mismos 3 dígitos |
| 94 | - } else if (objeto.nivel === 'partida') { | 123 | + const prefix = codigo.substring(0, 3); |
| 95 | const { data: hijosData } = await supabase | 124 | const { data: hijosData } = await supabase |
| 96 | .schema('ppto') | 125 | .schema('ppto') |
| 97 | .from('clas_objetos') | 126 | .from('clas_objetos') |
| 98 | .select('*') | 127 | .select('*') |
| 99 | .eq('nivel', 'subpartida') | 128 | .eq('nivel', 'subpartida') |
| 100 | - .eq('grupo', objeto.grupo) | 129 | + .like('objeto', `${prefix}%`) |
| 101 | - .eq('subgrupo', objeto.subgrupo) | ||
| 102 | - .eq('partida', objeto.partida) | ||
| 103 | .order('objeto'); | 130 | .order('objeto'); |
| 104 | - hijos = hijosData?.reduce((acc, item) => { | 131 | + |
| 105 | - if (!acc.find(h => h.objeto === item.objeto)) acc.push(item); | 132 | + hijos = hijosData || []; |
| 106 | - return acc; | ||
| 107 | - }, []) || []; | ||
| 108 | } | 133 | } |
| 134 | + // subpartida no tiene hijos | ||
| 135 | + | ||
| 109 | console.timeEnd('[SERVER] Query hijos'); | 136 | console.timeEnd('[SERVER] Query hijos'); |
| 110 | 137 | ||
| 111 | console.timeEnd('[SERVER] Total load objeto'); | 138 | console.timeEnd('[SERVER] Total load objeto'); | ... | ... |
| ... | @@ -357,12 +357,16 @@ | ... | @@ -357,12 +357,16 @@ |
| 357 | // VALORES DERIVADOS | 357 | // VALORES DERIVADOS |
| 358 | // ══════════════════════════════════════════════════════════════ | 358 | // ══════════════════════════════════════════════════════════════ |
| 359 | 359 | ||
| 360 | + // Constante de población para cálculos per cápita | ||
| 361 | + const POBLACION = 12000000; | ||
| 362 | + | ||
| 360 | // Datos para el gráfico (monto o per_capita según preferencia) | 363 | // Datos para el gráfico (monto o per_capita según preferencia) |
| 364 | + // Nota: vista_objeto_entidad solo tiene 'devengado', no 'per_capita' | ||
| 361 | let gastoPerCapita = $derived( | 365 | let gastoPerCapita = $derived( |
| 362 | datosAnuales.map(d => ({ | 366 | datosAnuales.map(d => ({ |
| 363 | año: d.gestion, | 367 | año: d.gestion, |
| 364 | - monto: selectedEntity ? d.monto : d.total, | 368 | + monto: selectedEntity ? (d.monto ?? d.devengado) : d.total, |
| 365 | - perCapita: d.per_capita | 369 | + perCapita: d.per_capita ?? (d.devengado ? d.devengado / POBLACION : 0) |
| 366 | })) | 370 | })) |
| 367 | ); | 371 | ); |
| 368 | 372 | ||
| ... | @@ -991,7 +995,7 @@ | ... | @@ -991,7 +995,7 @@ |
| 991 | <div class="page" class:mounted> | 995 | <div class="page" class:mounted> |
| 992 | <!-- Link a clasificadores --> | 996 | <!-- Link a clasificadores --> |
| 993 | <nav class="page-nav"> | 997 | <nav class="page-nav"> |
| 994 | - <a href="/clasificadores/objeto-gasto" class="back-link"> | 998 | + <a href="/clasificadores/objeto-gasto" class="back-link" data-sveltekit-reload> |
| 995 | <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | 999 | <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 996 | <path d="M19 12H5M12 19l-7-7 7-7"/> | 1000 | <path d="M19 12H5M12 19l-7-7 7-7"/> |
| 997 | </svg> | 1001 | </svg> |
| ... | @@ -1149,7 +1153,13 @@ | ... | @@ -1149,7 +1153,13 @@ |
| 1149 | <div class="chart-header"> | 1153 | <div class="chart-header"> |
| 1150 | <span class="chart-title">Bs/habitante <span class="chart-period">· {displayPeriodo}</span></span> | 1154 | <span class="chart-title">Bs/habitante <span class="chart-period">· {displayPeriodo}</span></span> |
| 1151 | </div> | 1155 | </div> |
| 1156 | + {#if loading} | ||
| 1157 | + <div class="chart-loading" style="height: 280px;"> | ||
| 1158 | + <span>Cargando...</span> | ||
| 1159 | + </div> | ||
| 1160 | + {:else} | ||
| 1152 | <BarChart data={gastoPerCapita} bind:hoveredYear height={280} fill={!!selectedEntity} /> | 1161 | <BarChart data={gastoPerCapita} bind:hoveredYear height={280} fill={!!selectedEntity} /> |
| 1162 | + {/if} | ||
| 1153 | 1163 | ||
| 1154 | <!-- KPIs abajo --> | 1164 | <!-- KPIs abajo --> |
| 1155 | <div class="kpis"> | 1165 | <div class="kpis"> |
| ... | @@ -2581,6 +2591,17 @@ | ... | @@ -2581,6 +2591,17 @@ |
| 2581 | letter-spacing: 0; | 2591 | letter-spacing: 0; |
| 2582 | } | 2592 | } |
| 2583 | 2593 | ||
| 2594 | + .chart-loading { | ||
| 2595 | + display: flex; | ||
| 2596 | + align-items: center; | ||
| 2597 | + justify-content: center; | ||
| 2598 | + color: var(--theme-texto); | ||
| 2599 | + opacity: 0.5; | ||
| 2600 | + font-size: 0.875rem; | ||
| 2601 | + border: 1px dashed var(--theme-borde); | ||
| 2602 | + border-radius: 8px; | ||
| 2603 | + } | ||
| 2604 | + | ||
| 2584 | .chart-controls { | 2605 | .chart-controls { |
| 2585 | display: flex; | 2606 | display: flex; |
| 2586 | align-items: center; | 2607 | align-items: center; | ... | ... |
src/routes/sobre/+page.svelte
0 → 100644
| 1 | +<script> | ||
| 2 | + let institucion = "Ministerio de Economía y Finanzas Públicas"; | ||
| 3 | + let pais = "Bolivia"; | ||
| 4 | +</script> | ||
| 5 | + | ||
| 6 | +<svelte:head> | ||
| 7 | + <title>Sobre | Presupuesto Público</title> | ||
| 8 | + <link rel="preconnect" href="https://fonts.googleapis.com" /> | ||
| 9 | + <link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,300;0,8..60,400;0,8..60,600;1,8..60,300;1,8..60,400&family=JetBrains+Mono:wght@400&display=swap" rel="stylesheet" /> | ||
| 10 | +</svelte:head> | ||
| 11 | + | ||
| 12 | +<div class="manifesto-outer"> | ||
| 13 | + <div class="manifesto-inner"> | ||
| 14 | + | ||
| 15 | + <div class="manifesto-label"> | ||
| 16 | + Presentación · Liberación de la base histórica | ||
| 17 | + </div> | ||
| 18 | + | ||
| 19 | + <div class="manifesto-fecha"> | ||
| 20 | + A fines de 2025 decidimos abrir los datos históricos<br> | ||
| 21 | + de presupuesto del Estado boliviano. | ||
| 22 | + </div> | ||
| 23 | + | ||
| 24 | + <div class="manifesto-cuerpo"> | ||
| 25 | + | ||
| 26 | + <p class="p1"> | ||
| 27 | + Cada año el Estado recibe y gasta dinero a tu nombre. ¿Sabes de dónde viene, | ||
| 28 | + en qué se usa y qué se logra con él? Esa información es tuya. Siempre lo fue, | ||
| 29 | + pero durante décadas permaneció encerrada en archivos PDF, en sistemas que pocos | ||
| 30 | + saben usar y en las paredes de un ministerio. | ||
| 31 | + </p> | ||
| 32 | + | ||
| 33 | + <div class="manifesto-hoy">Hoy cambia eso.</div> | ||
| 34 | + | ||
| 35 | + <p class="p3"> | ||
| 36 | + Aquí puedes explorar más de veinte años de ejecución presupuestaria, con | ||
| 37 | + actualización semanal. Puedes ver qué hizo el Estado en tu región, en tu sector | ||
| 38 | + y en el año que te interesa. Puedes comparar, cuestionar y entender. Y si | ||
| 39 | + encuentras algo que no cuadra o que vale la pena contar, puedes hacerlo tuyo. | ||
| 40 | + </p> | ||
| 41 | + | ||
| 42 | + <hr class="manifesto-regla" /> | ||
| 43 | + | ||
| 44 | + <p class="p4"> | ||
| 45 | + No publicamos esto para cumplir un trámite de transparencia. Lo hacemos porque | ||
| 46 | + creemos que un Estado que trabaja de espaldas a su sociedad se vuelve impune, | ||
| 47 | + y una sociedad que no entiende al Estado se desconecta de él. | ||
| 48 | + </p> | ||
| 49 | + | ||
| 50 | + <blockquote class="manifesto-apuesta"> | ||
| 51 | + Un presupuesto abierto es una apuesta: que la confianza se construye con | ||
| 52 | + <strong>información</strong> y no con promesas. | ||
| 53 | + </blockquote> | ||
| 54 | + | ||
| 55 | + </div> | ||
| 56 | + | ||
| 57 | + <div class="manifesto-cierre"> | ||
| 58 | + <p class="manifesto-cierre-texto">Abrimos para no cerrar.</p> | ||
| 59 | + <p class="manifesto-cierre-sub">{institucion} · {pais}</p> | ||
| 60 | + </div> | ||
| 61 | + | ||
| 62 | + </div> | ||
| 63 | +</div> | ||
| 64 | + | ||
| 65 | +<style> | ||
| 66 | + .manifesto-outer { | ||
| 67 | + min-height: 100vh; | ||
| 68 | + background: var(--manifesto-bg); | ||
| 69 | + overflow: hidden; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + .manifesto-inner { | ||
| 73 | + max-width: 640px; | ||
| 74 | + margin: 0 auto; | ||
| 75 | + padding: 72px 48px 88px; | ||
| 76 | + font-family: 'Source Serif 4', Georgia, 'Times New Roman', serif; | ||
| 77 | + color: var(--manifesto-text); | ||
| 78 | + } | ||
| 79 | + | ||
| 80 | + /* === etiqueta superior === */ | ||
| 81 | + | ||
| 82 | + .manifesto-label { | ||
| 83 | + font-family: 'JetBrains Mono', 'Courier New', monospace; | ||
| 84 | + font-size: 10px; | ||
| 85 | + letter-spacing: 0.18em; | ||
| 86 | + color: var(--manifesto-muted); | ||
| 87 | + text-transform: uppercase; | ||
| 88 | + margin-bottom: 56px; | ||
| 89 | + display: flex; | ||
| 90 | + align-items: center; | ||
| 91 | + gap: 12px; | ||
| 92 | + opacity: 0; | ||
| 93 | + animation: fadeUp 0.6s ease forwards; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + .manifesto-label::after { | ||
| 97 | + content: ''; | ||
| 98 | + flex: 1; | ||
| 99 | + height: 0.5px; | ||
| 100 | + background: var(--manifesto-rule); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + /* === fecha === */ | ||
| 104 | + | ||
| 105 | + .manifesto-fecha { | ||
| 106 | + font-family: 'Source Serif 4', Georgia, serif; | ||
| 107 | + font-style: italic; | ||
| 108 | + font-weight: 300; | ||
| 109 | + font-size: 14px; | ||
| 110 | + color: var(--manifesto-subtle); | ||
| 111 | + letter-spacing: 0.02em; | ||
| 112 | + margin-bottom: 40px; | ||
| 113 | + opacity: 0; | ||
| 114 | + animation: fadeUp 0.6s ease 0.1s forwards; | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + /* === cuerpo === */ | ||
| 118 | + | ||
| 119 | + .manifesto-cuerpo { | ||
| 120 | + font-size: 18.5px; | ||
| 121 | + line-height: 1.78; | ||
| 122 | + font-weight: 300; | ||
| 123 | + color: var(--manifesto-body); | ||
| 124 | + letter-spacing: 0.01em; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + .p1 { | ||
| 128 | + opacity: 0; | ||
| 129 | + animation: fadeUp 0.7s ease 0.2s forwards; | ||
| 130 | + margin-bottom: 28px; | ||
| 131 | + margin-top: 0; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + .manifesto-hoy { | ||
| 135 | + opacity: 0; | ||
| 136 | + animation: fadeUp 0.7s ease 0.5s forwards; | ||
| 137 | + margin: 44px 0; | ||
| 138 | + font-size: 26px; | ||
| 139 | + font-weight: 400; | ||
| 140 | + color: var(--manifesto-text); | ||
| 141 | + letter-spacing: -0.01em; | ||
| 142 | + line-height: 1.3; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + .p3 { | ||
| 146 | + opacity: 0; | ||
| 147 | + animation: fadeUp 0.7s ease 0.65s forwards; | ||
| 148 | + margin-bottom: 28px; | ||
| 149 | + margin-top: 0; | ||
| 150 | + } | ||
| 151 | + | ||
| 152 | + .manifesto-regla { | ||
| 153 | + opacity: 0; | ||
| 154 | + animation: fadeUp 0.6s ease 0.75s forwards; | ||
| 155 | + border: none; | ||
| 156 | + border-top: 0.5px solid var(--manifesto-rule); | ||
| 157 | + margin: 44px 0; | ||
| 158 | + } | ||
| 159 | + | ||
| 160 | + .p4 { | ||
| 161 | + opacity: 0; | ||
| 162 | + animation: fadeUp 0.7s ease 0.85s forwards; | ||
| 163 | + margin-bottom: 0; | ||
| 164 | + margin-top: 0; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + .manifesto-apuesta { | ||
| 168 | + opacity: 0; | ||
| 169 | + animation: fadeUp 0.7s ease 0.95s forwards; | ||
| 170 | + margin: 44px 0; | ||
| 171 | + padding: 0 0 0 24px; | ||
| 172 | + border-left: 1.5px solid var(--manifesto-quote-border); | ||
| 173 | + font-style: italic; | ||
| 174 | + font-weight: 300; | ||
| 175 | + font-size: 20px; | ||
| 176 | + line-height: 1.65; | ||
| 177 | + color: var(--manifesto-quote); | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + .manifesto-apuesta strong { | ||
| 181 | + font-style: normal; | ||
| 182 | + font-weight: 400; | ||
| 183 | + color: var(--manifesto-body); | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + /* === cierre === */ | ||
| 187 | + | ||
| 188 | + .manifesto-cierre { | ||
| 189 | + opacity: 0; | ||
| 190 | + animation: fadeUp 0.8s ease 1.1s forwards; | ||
| 191 | + margin-top: 56px; | ||
| 192 | + padding-top: 36px; | ||
| 193 | + border-top: 0.5px solid var(--manifesto-rule); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + .manifesto-cierre-texto { | ||
| 197 | + font-size: 36px; | ||
| 198 | + font-weight: 400; | ||
| 199 | + color: var(--color-gold); | ||
| 200 | + letter-spacing: -0.02em; | ||
| 201 | + line-height: 1.1; | ||
| 202 | + margin: 0; | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + .manifesto-cierre-sub { | ||
| 206 | + font-family: 'JetBrains Mono', 'Courier New', monospace; | ||
| 207 | + font-size: 10px; | ||
| 208 | + letter-spacing: 0.16em; | ||
| 209 | + color: var(--manifesto-muted); | ||
| 210 | + text-transform: uppercase; | ||
| 211 | + margin-top: 20px; | ||
| 212 | + margin-bottom: 0; | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + /* === animación === */ | ||
| 216 | + | ||
| 217 | + @keyframes -global-fadeUp { | ||
| 218 | + from { | ||
| 219 | + opacity: 0; | ||
| 220 | + transform: translateY(14px); | ||
| 221 | + } | ||
| 222 | + to { | ||
| 223 | + opacity: 1; | ||
| 224 | + transform: translateY(0); | ||
| 225 | + } | ||
| 226 | + } | ||
| 227 | + | ||
| 228 | + /* === MODO OSCURO (default) === */ | ||
| 229 | + .manifesto-outer { | ||
| 230 | + --manifesto-bg: #0C0C0C; | ||
| 231 | + --manifesto-text: #EDE9E1; | ||
| 232 | + --manifesto-body: #D9D4CB; | ||
| 233 | + --manifesto-muted: #5A5650; | ||
| 234 | + --manifesto-subtle: #6B6660; | ||
| 235 | + --manifesto-rule: #2A2822; | ||
| 236 | + --manifesto-quote: #C4BFB6; | ||
| 237 | + --manifesto-quote-border: #3A3530; | ||
| 238 | + } | ||
| 239 | + | ||
| 240 | + /* === MODO CLARO === */ | ||
| 241 | + :global(html:not(.dark)) .manifesto-outer { | ||
| 242 | + --manifesto-bg: #FAFAF8; | ||
| 243 | + --manifesto-text: #1a1a1a; | ||
| 244 | + --manifesto-body: #3a3a3a; | ||
| 245 | + --manifesto-muted: #8a8a8a; | ||
| 246 | + --manifesto-subtle: #6a6a6a; | ||
| 247 | + --manifesto-rule: #e0e0e0; | ||
| 248 | + --manifesto-quote: #4a4a4a; | ||
| 249 | + --manifesto-quote-border: #d0d0d0; | ||
| 250 | + } | ||
| 251 | + | ||
| 252 | + /* === responsive === */ | ||
| 253 | + | ||
| 254 | + @media (max-width: 600px) { | ||
| 255 | + .manifesto-inner { | ||
| 256 | + padding: 48px 28px 64px; | ||
| 257 | + } | ||
| 258 | + | ||
| 259 | + .manifesto-cuerpo { | ||
| 260 | + font-size: 17px; | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + .manifesto-hoy { | ||
| 264 | + font-size: 22px; | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + .manifesto-apuesta { | ||
| 268 | + font-size: 18px; | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + .manifesto-cierre-texto { | ||
| 272 | + font-size: 28px; | ||
| 273 | + } | ||
| 274 | + } | ||
| 275 | +</style> |
src/routes/test1/+page.svelte
0 → 100644
This diff is collapsed. Click to expand it.
static/data.csv
deleted
100644 → 0
| 1 | -gestion,objeto,devengado | ||
| 2 | -2025,11100,7010195151.280003 | ||
| 3 | -2025,11210,5812831318.110004 | ||
| 4 | -2025,11220,3960643633.5099993 | ||
| 5 | -2025,11310,477377380.7399999 | ||
| 6 | -2025,11321,611358929.5699998 | ||
| 7 | -2025,11322,344284069.2800001 | ||
| 8 | -2025,11323,8492765.11 | ||
| 9 | -2025,11324,119472850.73000005 | ||
| 10 | -2025,11331,3741918.29 | ||
| 11 | -2025,11332,222831.86 | ||
| 12 | -2025,11339,991911009.5900005 | ||
| 13 | -2025,11400,2598265843.6899953 | ||
| 14 | -2025,11510,115618445.64 | ||
| 15 | -2025,11520,3684768.92 | ||
| 16 | -2025,11600,347937539.3 | ||
| 17 | -2025,11700,16012422722.88999 | ||
| 18 | -2025,11810,1897633.19 | ||
| 19 | -2025,11820,5236920.13 | ||
| 20 | -2025,11910,418427037.15000004 | ||
| 21 | -2025,11920,49552831.83999999 | ||
| 22 | -2025,11930,141140855.32999998 | ||
| 23 | -2025,11940,4603197.24 | ||
| 24 | -2025,12100,3204535824.6000023 | ||
| 25 | -2025,13110,3901953807.7400007 | ||
| 26 | -2025,13120,619414677.6200007 | ||
| 27 | -2025,13131,1362025647.0700052 | ||
| 28 | -2025,13132,16517337.85 | ||
| 29 | -2025,13200,780321050.7899984 | ||
| 30 | -2025,14100,1139341529.1000001 | ||
| 31 | -2025,15100,0 | ||
| 32 | -2025,15200,0 | ||
| 33 | -2025,15300,0 | ||
| 34 | -2025,15400,4691146.74 | ||
| 35 | -2025,21100,18994647.069999997 | ||
| 36 | -2025,21200,1185053965.7300012 | ||
| 37 | -2025,21300,187133399.53000006 | ||
| 38 | -2025,21400,53465476.169999935 | ||
| 39 | -2025,21500,32025660.46999999 | ||
| 40 | -2025,21600,194624988.81999987 | ||
| 41 | -2025,22110,91267157.03 | ||
| 42 | -2025,22120,18054096.22 | ||
| 43 | -2025,22210,150388054.74000007 | ||
| 44 | -2025,22220,34629325.89 | ||
| 45 | -2025,22300,1959574229.3100035 | ||
| 46 | -2025,22400,2341473.77 | ||
| 47 | -2025,22500,701307983.6299998 | ||
| 48 | -2025,22600,129774059.36000001 | ||
| 49 | -2025,23100,177818037.08 | ||
| 50 | -2025,23200,705817678.630001 | ||
| 51 | -2025,23300,267332.29 | ||
| 52 | -2025,23400,102877216.77999996 | ||
| 53 | -2025,24110,347305124.4300007 | ||
| 54 | -2025,24120,495875030.0700008 | ||
| 55 | -2025,24130,4734068.450000001 | ||
| 56 | -2025,24200,186441122.7200001 | ||
| 57 | -2025,24300,2640074895.480003 | ||
| 58 | -2025,25120,968577449.3700005 | ||
| 59 | -2025,25130,48331129.9 | ||
| 60 | -2025,25210,124279655.01999998 | ||
| 61 | -2025,25220,1788157637.100003 | ||
| 62 | -2025,25230,38750297.28 | ||
| 63 | -2025,25300,561398734.3999997 | ||
| 64 | -2025,25400,878953716.1200004 | ||
| 65 | -2025,25500,306587141.63999945 | ||
| 66 | -2025,25600,313083444.33000004 | ||
| 67 | -2025,25700,6976563.890000001 | ||
| 68 | -2025,25810,119466843.19999999 | ||
| 69 | -2025,25820,224542509.50000012 | ||
| 70 | -2025,25900,237665083.13999984 | ||
| 71 | -2025,26200,15655261.7 | ||
| 72 | -2025,26300,34604066.51 | ||
| 73 | -2025,26610,123238100.68000004 | ||
| 74 | -2025,26620,65803840.900000006 | ||
| 75 | -2025,26630,5856917.720000001 | ||
| 76 | -2025,26640,12578208.32 | ||
| 77 | -2025,26700,14848951.62 | ||
| 78 | -2025,26910,663385.5700000003 | ||
| 79 | -2025,26920,235250 | ||
| 80 | -2025,26930,8978735.689999998 | ||
| 81 | -2025,26940,66563836.099999994 | ||
| 82 | -2025,26990,1503662082.0000036 | ||
| 83 | -2025,27110,1825790733.1499996 | ||
| 84 | -2025,27120,364659427.3 | ||
| 85 | -2025,31110,542443427.4200002 | ||
| 86 | -2025,31120,216381918.43999982 | ||
| 87 | -2025,31130,664933780.7900007 | ||
| 88 | -2025,31140,546467610.53 | ||
| 89 | -2025,31150,58934973.47 | ||
| 90 | -2025,31200,33094567.35000001 | ||
| 91 | -2025,31300,2447995585.1100035 | ||
| 92 | -2025,32100,143276681.52000007 | ||
| 93 | -2025,32200,132315063.70000002 | ||
| 94 | -2025,32300,5561928.509999998 | ||
| 95 | -2025,32400,159320 | ||
| 96 | -2025,32500,1136682.8700000003 | ||
| 97 | -2025,33100,24196989.06 | ||
| 98 | -2025,33200,44402437.73000002 | ||
| 99 | -2025,33300,140159482.78000006 | ||
| 100 | -2025,33400,44503112.73000003 | ||
| 101 | -2025,34110,1233206780.699983 | ||
| 102 | -2025,34120,22281523272.74 | ||
| 103 | -2025,34130,210854679.98 | ||
| 104 | -2025,34200,2971103666.2100005 | ||
| 105 | -2025,34300,107990911.47999994 | ||
| 106 | -2025,34400,7452099.93 | ||
| 107 | -2025,34500,643334205.2399997 | ||
| 108 | -2025,34600,256516535.3800006 | ||
| 109 | -2025,34700,4499642859.289998 | ||
| 110 | -2025,34800,31720752.09 | ||
| 111 | -2025,34900,3886088.93 | ||
| 112 | -2025,39100,110497000.54 | ||
| 113 | -2025,39200,48738034.710000016 | ||
| 114 | -2025,39300,4137761.2899999996 | ||
| 115 | -2025,39400,88709616.89000002 | ||
| 116 | -2025,39500,308909532.08000034 | ||
| 117 | -2025,39600,13789089.190000001 | ||
| 118 | -2025,39700,260527546.88999993 | ||
| 119 | -2025,39800,711478491.3899997 | ||
| 120 | -2025,39911,25451599.84 | ||
| 121 | -2025,39912,229716435.09 | ||
| 122 | -2025,39990,85810785.37999989 | ||
| 123 | -2025,41100,4018555.16 | ||
| 124 | -2025,41200,11738231.740000002 | ||
| 125 | -2025,41300,0 | ||
| 126 | -2025,42210,2475688.8800000004 | ||
| 127 | -2025,42220,5772449.3 | ||
| 128 | -2025,42230,3644887583.5699887 | ||
| 129 | -2025,42240,119884214.51000004 | ||
| 130 | -2025,42310,3262092590.7700067 | ||
| 131 | -2025,42320,162411814.5 | ||
| 132 | -2025,42400,748574159.99 | ||
| 133 | -2025,42500,368399418.97999996 | ||
| 134 | -2025,43110,68317124.34 | ||
| 135 | -2025,43120,223834030.73999995 | ||
| 136 | -2025,43200,145257372.71 | ||
| 137 | -2025,43310,18770602.6 | ||
| 138 | -2025,43320,7603011.960000001 | ||
| 139 | -2025,43330,290260838.97 | ||
| 140 | -2025,43340,4231983.279999999 | ||
| 141 | -2025,43400,398948895.01000005 | ||
| 142 | -2025,43500,328470832.01999986 | ||
| 143 | -2025,43600,51696765.46999999 | ||
| 144 | -2025,43700,169086594.95000005 | ||
| 145 | -2025,46110,125733899.86000003 | ||
| 146 | -2025,46120,74691013.75999999 | ||
| 147 | -2025,46210,57348534.56999999 | ||
| 148 | -2025,46220,9583654.360000001 | ||
| 149 | -2025,46310,30831570.299999986 | ||
| 150 | -2025,46320,2784494.7899999996 | ||
| 151 | -2025,49100,41480273 | ||
| 152 | -2025,49300,492862.94999999995 | ||
| 153 | -2025,49400,85275 | ||
| 154 | -2025,49900,660922.38 | ||
| 155 | -2025,51100,0 | ||
| 156 | -2025,51200,620015014.37 | ||
| 157 | -2025,51600,481042090 | ||
| 158 | -2025,51700,29014116.87 | ||
| 159 | -2025,53410,52050949.82 | ||
| 160 | -2025,53420,351090144.51 | ||
| 161 | -2025,53430,3378151.15 | ||
| 162 | -2025,53440,25716472.12 | ||
| 163 | -2025,54300,77289717.23 | ||
| 164 | -2025,54800,632675260.65 | ||
| 165 | -2025,55130,0 | ||
| 166 | -2025,56100,2147721911.8500004 | ||
| 167 | -2025,57100,836275.9 | ||
| 168 | -2025,57200,0 | ||
| 169 | -2025,61100,70227731033.1 | ||
| 170 | -2025,61200,3503973693.6899977 | ||
| 171 | -2025,61300,7686201.74 | ||
| 172 | -2025,61400,165316.78 | ||
| 173 | -2025,61600,4660620766.32 | ||
| 174 | -2025,61700,3610015023.1800003 | ||
| 175 | -2025,61800,578767.5200000001 | ||
| 176 | -2025,61900,560031.13 | ||
| 177 | -2025,62100,106585021.14999999 | ||
| 178 | -2025,62200,38756619.58 | ||
| 179 | -2025,62300,3500499.439999999 | ||
| 180 | -2025,62400,405.55 | ||
| 181 | -2025,62600,4871024753.510001 | ||
| 182 | -2025,62700,3091378138.92 | ||
| 183 | -2025,62800,66184743.53000001 | ||
| 184 | -2025,62900,236631.16 | ||
| 185 | -2025,63100,6480763.82 | ||
| 186 | -2025,63200,0 | ||
| 187 | -2025,63300,100360.43 | ||
| 188 | -2025,63400,462857.7 | ||
| 189 | -2025,63500,35529.2 | ||
| 190 | -2025,63600,0 | ||
| 191 | -2025,63700,2369055.65 | ||
| 192 | -2025,63800,0 | ||
| 193 | -2025,63900,1087614.1800000002 | ||
| 194 | -2025,64100,0 | ||
| 195 | -2025,64200,0 | ||
| 196 | -2025,65100,586447491.8299999 | ||
| 197 | -2025,65210,398987753.5799999 | ||
| 198 | -2025,65220,240387686.01999998 | ||
| 199 | -2025,65230,132581381.01 | ||
| 200 | -2025,65240,0 | ||
| 201 | -2025,65300,2444818356.6 | ||
| 202 | -2025,65400,644864385.6300001 | ||
| 203 | -2025,65500,797927308.79 | ||
| 204 | -2025,65600,622100032.9 | ||
| 205 | -2025,65800,6897016.98 | ||
| 206 | -2025,65900,66705420.480000004 | ||
| 207 | -2025,66100,403828926.02000004 | ||
| 208 | -2025,66210,2597435653.4000015 | ||
| 209 | -2025,66220,1829365908.85 | ||
| 210 | -2025,66230,646299428.4800001 | ||
| 211 | -2025,66240,80232240.73 | ||
| 212 | -2025,66250,209697820.00000003 | ||
| 213 | -2025,66300,239921321.82000005 | ||
| 214 | -2025,66400,134798065.3299999 | ||
| 215 | -2025,66900,1844595842.08 | ||
| 216 | -2025,67100,23208064.040000003 | ||
| 217 | -2025,68200,230881944.88000008 | ||
| 218 | -2025,69100,29581681.77 | ||
| 219 | -2025,69200,203500678.33 | ||
| 220 | -2025,71100,7630007944.97 | ||
| 221 | -2025,71210,2392898.6 | ||
| 222 | -2025,71220,322149243.09 | ||
| 223 | -2025,71230,4408152.6 | ||
| 224 | -2025,71300,26644234.430000003 | ||
| 225 | -2025,71610,1883091507.0600004 | ||
| 226 | -2025,71630,343800974.93 | ||
| 227 | -2025,71700,65080225.449999996 | ||
| 228 | -2025,71800,4478984170.690001 | ||
| 229 | -2025,72200,2046897058.8299997 | ||
| 230 | -2025,72420,316010589.22 | ||
| 231 | -2025,72520,7584584602.65001 | ||
| 232 | -2025,73100,2664574022.970007 | ||
| 233 | -2025,73200,24681254941.659996 | ||
| 234 | -2025,73410,4845222515.11 | ||
| 235 | -2025,73420,315258596.03999996 | ||
| 236 | -2025,73430,4314037.58 | ||
| 237 | -2025,73440,1652127 | ||
| 238 | -2025,73700,15015040108.359999 | ||
| 239 | -2025,73820,1364681.67 | ||
| 240 | -2025,75110,0 | ||
| 241 | -2025,75120,683772757.9200002 | ||
| 242 | -2025,75211,469127620.05 | ||
| 243 | -2025,75212,50308009.760000005 | ||
| 244 | -2025,75221,11649919.909999998 | ||
| 245 | -2025,75222,305831148.79999995 | ||
| 246 | -2025,75320,0 | ||
| 247 | -2025,77100,346626643.30999994 | ||
| 248 | -2025,77200,1783047515.49 | ||
| 249 | -2025,77410,154404059.40000007 | ||
| 250 | -2025,77440,13005182.149999999 | ||
| 251 | -2025,77520,34542653.12 | ||
| 252 | -2025,77530,1359464924.2300012 | ||
| 253 | -2025,77700,0 | ||
| 254 | -2025,77820,42931153.11 | ||
| 255 | -2025,78100,346333.4 | ||
| 256 | -2025,79100,20183063.04 | ||
| 257 | -2025,79200,74336.66 | ||
| 258 | -2025,79310,69600 | ||
| 259 | -2025,81100,189467352 | ||
| 260 | -2025,81200,1327189189.5399992 | ||
| 261 | -2025,81300,551652107.6699998 | ||
| 262 | -2025,81400,299412884.65 | ||
| 263 | -2025,81500,2442434 | ||
| 264 | -2025,81600,395569 | ||
| 265 | -2025,81950,39137 | ||
| 266 | -2025,81960,32790665.14 | ||
| 267 | -2025,81990,2007174694.16 | ||
| 268 | -2025,82100,879007438.5400001 | ||
| 269 | -2025,83110,29113391.8 | ||
| 270 | -2025,83120,4240482.35 | ||
| 271 | -2025,83210,351070.72 | ||
| 272 | -2025,83220,50460 | ||
| 273 | -2025,84100,65887753.279999994 | ||
| 274 | -2025,84230,394819507.59 | ||
| 275 | -2025,84240,723835763.5600002 | ||
| 276 | -2025,84250,65803251.14 | ||
| 277 | -2025,84900,8503359.91 | ||
| 278 | -2025,85100,94254502.63999999 | ||
| 279 | -2025,85200,10478575.300000003 | ||
| 280 | -2025,85400,6221225.630000003 | ||
| 281 | -2025,85500,3581209.3799999994 | ||
| 282 | -2025,85900,20640115.529999997 | ||
| 283 | -2025,86100,29028844.980000008 | ||
| 284 | -2025,91200,512102826.06 | ||
| 285 | -2025,92100,0 | ||
| 286 | -2025,94100,11526054.86 | ||
| 287 | -2025,94200,7279202.82 | ||
| 288 | -2025,94300,1551638.3499999999 | ||
| 289 | -2025,95100,291453722.56 | ||
| 290 | -2025,96100,5934986991.019999 | ||
| 291 | -2025,96200,614954091.44 | ||
| 292 | -2025,96900,2947311655.2299995 | ||
| 293 | -2025,97100,70099589.35000001 | ||
| 294 | -2025,98300,125000000 | ||
| 295 | -2025,99100,0 | ||
| 296 | -2025,99200,0 |
static/muetra_base.csv
deleted
100644 → 0
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment