Rafael Lopez

final

Showing 43 changed files with 111 additions and 312 deletions
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 "version": "0.0.1", 4 "version": "0.0.1",
5 "type": "module", 5 "type": "module",
6 "scripts": { 6 "scripts": {
7 - "dev": "vite dev", 7 + "dev": "NODE_TLS_REJECT_UNAUTHORIZED=0 vite dev",
8 "build": "vite build", 8 "build": "vite build",
9 "preview": "vite preview", 9 "preview": "vite preview",
10 "prepare": "svelte-kit sync || echo ''" 10 "prepare": "svelte-kit sync || echo ''"
......
1 +// ═══════════════════════════════════════════════════════════════
2 +// CONFIGURACIÓN CENTRAL DE API
3 +// Cambiar la IP aquí actualiza todas las llamadas del proyecto
4 +// ═══════════════════════════════════════════════════════════════
5 +
6 +export const API_HOST = 'https://abierto.economiayfinanzas.gob.bo/presupuesto';
7 +export const DOWNLOAD_BASE = 'https://abierto.economiayfinanzas.gob.bo/presupuesto/descargas/';
This diff is collapsed. Click to expand it.
1 import { error } from '@sveltejs/kit'; 1 import { error } from '@sveltejs/kit';
2 2
3 -const API_BASE = 'http://136.112.29.74/api/acteco'; 3 +import { API_HOST } from '$lib/api.js';
4 +const API_BASE = API_HOST + '/api/acteco';
4 5
5 // Jerarquía acteco: códigos con punto "1" → "1.1" → "1.1.1" 6 // Jerarquía acteco: códigos con punto "1" → "1.1" → "1.1.1"
6 // Todos tienen nivel "actividad" en la API, derivamos la profundidad del código 7 // Todos tienen nivel "actividad" en la API, derivamos la profundidad del código
......
1 -const API_BASE = 'http://136.112.29.74/api/acteco/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/acteco/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/acteco'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/acteco';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/acteco'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/acteco';
2 3
3 let cachedClasificador = null; 4 let cachedClasificador = null;
4 let cachedEstados = null; 5 let cachedEstados = null;
......
1 -const API_BASE = 'http://136.112.29.74/api/acteco'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/acteco';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/diario'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/diario';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const tipo = url.searchParams.get('tipo') || 'status'; 5 const tipo = url.searchParams.get('tipo') || 'status';
......
1 -const API_BASE = 'http://136.112.29.74/api/entidad/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/entidad/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/entidad'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/entidad';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/finfun/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/finfun/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
5 const response = await fetch(API_BASE); 6 const response = await fetch(API_BASE);
6 - if (!response.ok) { 7 + if (!response.ok) throw new Error();
7 - return new Response(JSON.stringify({ error: `API error: ${response.status}` }), {
8 - status: response.status, headers: { 'Content-Type': 'application/json' }
9 - });
10 - }
11 const data = await response.json(); 8 const data = await response.json();
12 return new Response(JSON.stringify(data), { 9 return new Response(JSON.stringify(data), {
13 headers: { 'Content-Type': 'application/json' } 10 headers: { 'Content-Type': 'application/json' }
......
1 -const API_BASE = 'http://136.112.29.74/api/finfun'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/finfun';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/finfun'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/finfun';
2 3
4 +// Cache en memoria
3 let cachedClasificador = null; 5 let cachedClasificador = null;
4 let cachedEstados = null; 6 let cachedEstados = null;
5 let cachedTimestamp = 0; 7 let cachedTimestamp = 0;
6 const CACHE_TTL = 5 * 60 * 1000; 8 const CACHE_TTL = 5 * 60 * 1000;
7 9
8 -function getParent(finfun) { 10 +function getParent(finfun, nivel) {
9 - const idx = finfun.lastIndexOf('.'); 11 + const code = String(finfun);
10 - if (idx === -1) return null; 12 + if (nivel === 'finalidad') return null;
11 - return finfun.substring(0, idx); 13 + if (nivel === 'grp_funcion') {
14 + return code.startsWith('10') ? '10' : code.charAt(0);
15 + }
16 + if (nivel === 'funcion') {
17 + if (code.startsWith('10')) return code.substring(0, 3);
18 + return code.substring(0, 2);
19 + }
20 + return null;
12 } 21 }
13 22
14 async function loadAndCacheAll() { 23 async function loadAndCacheAll() {
...@@ -58,7 +67,7 @@ export async function GET({ url }) { ...@@ -58,7 +67,7 @@ export async function GET({ url }) {
58 nivel: item.nivel, 67 nivel: item.nivel,
59 finfun: item.finfun, 68 finfun: item.finfun,
60 desc_finfun: item.desc_finfun, 69 desc_finfun: item.desc_finfun,
61 - parent: getParent(item.finfun), 70 + parent: getParent(item.finfun, item.nivel),
62 devengado: yearData.total 71 devengado: yearData.total
63 }); 72 });
64 } 73 }
...@@ -89,7 +98,7 @@ export async function GET({ url }) { ...@@ -89,7 +98,7 @@ export async function GET({ url }) {
89 nivel: item.nivel, 98 nivel: item.nivel,
90 finfun: item.finfun, 99 finfun: item.finfun,
91 desc_finfun: item.desc_finfun, 100 desc_finfun: item.desc_finfun,
92 - parent: getParent(item.finfun), 101 + parent: getParent(item.finfun, item.nivel),
93 devengado: yearData.monto 102 devengado: yearData.monto
94 }; 103 };
95 } catch { return null; } 104 } catch { return null; }
......
1 -const API_BASE = 'http://136.112.29.74/api/finfun'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/finfun';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/objeto/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/objeto/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/objeto'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/objeto';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/entidad/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/entidad/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/objeto'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/objeto';
2 3
3 // Cache en memoria del servidor 4 // Cache en memoria del servidor
4 let cachedClasificador = null; 5 let cachedClasificador = null;
......
1 -const API_BASE = 'http://136.112.29.74/api/objeto'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/objeto';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/organismo/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/organismo/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/organismo'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/organismo';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/organismo'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/organismo';
2 3
3 let cachedClasificador = null; 4 let cachedClasificador = null;
4 let cachedEstados = null; 5 let cachedEstados = null;
......
1 -const API_BASE = 'http://136.112.29.74/api/programa_proyecto'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/programa_proyecto';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/rubro/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/rubro/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/rubro'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/rubro';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 -const API_BASE = 'http://136.112.29.74/api/rubro'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/rubro';
2 3
3 let cachedClasificador = null; 4 let cachedClasificador = null;
4 let cachedEstados = null; 5 let cachedEstados = null;
......
1 -const API_BASE = 'http://136.112.29.74/api/rubro'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/rubro';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
1 // Proxy para evitar CORS 1 // Proxy para evitar CORS
2 -const API_BASE = 'http://136.112.29.74/api/search'; 2 +import { API_HOST } from '$lib/api.js';
3 +const API_BASE = API_HOST + '/api/search';
3 4
4 export async function GET({ url }) { 5 export async function GET({ url }) {
5 const q = url.searchParams.get('q') || ''; 6 const q = url.searchParams.get('q') || '';
...@@ -37,8 +38,8 @@ export async function GET({ url }) { ...@@ -37,8 +38,8 @@ export async function GET({ url }) {
37 headers: { 'Content-Type': 'application/json' } 38 headers: { 'Content-Type': 'application/json' }
38 }); 39 });
39 } catch (err) { 40 } catch (err) {
40 - console.error('Proxy error:', err); 41 + console.error('Proxy error:', err.message, 'URL:', apiUrl.toString());
41 - return new Response(JSON.stringify({ error: 'Failed to fetch from API' }), { 42 + return new Response(JSON.stringify({ error: 'Failed to fetch from API', detail: err.message, url: apiUrl.toString() }), {
42 status: 500, 43 status: 500,
43 headers: { 'Content-Type': 'application/json' } 44 headers: { 'Content-Type': 'application/json' }
44 }); 45 });
......
1 -const API_BASE = 'http://136.112.29.74/api/ubigeo/clasificador'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/ubigeo/clasificador';
2 3
3 export async function GET() { 4 export async function GET() {
4 try { 5 try {
......
1 -const API_BASE = 'http://136.112.29.74/api/ubigeo'; 1 +import { API_HOST } from '$lib/api.js';
2 +const API_BASE = API_HOST + '/api/ubigeo';
2 3
3 export async function GET({ url }) { 4 export async function GET({ url }) {
4 const codigo = url.searchParams.get('codigo') || ''; 5 const codigo = url.searchParams.get('codigo') || '';
......
This diff is collapsed. Click to expand it.
1 <script> 1 <script>
2 - import { supabase } from '$lib/supabase';
3 import { onMount, untrack } from 'svelte'; 2 import { onMount, untrack } from 'svelte';
4 import { page } from '$app/stores'; 3 import { page } from '$app/stores';
5 import { goto } from '$app/navigation'; 4 import { goto } from '$app/navigation';
...@@ -154,16 +153,11 @@ ...@@ -154,16 +153,11 @@
154 treemapNodes = []; 153 treemapNodes = [];
155 try { 154 try {
156 const entidadFiltro = selectedEntity?.entidad ?? 0; 155 const entidadFiltro = selectedEntity?.entidad ?? 0;
157 - const { data, error: dbError } = await supabase 156 + const res = await fetch(`/api/finfun-treemap?gestion=${selectedYear}&entidad=${entidadFiltro}`);
158 - .schema('ppto') 157 + const data = await res.json();
159 - .from('treemap_finfun') 158 +
160 - .select('gestion, nivel, finfun, desc_funcion, parent, devengado') 159 + if (data.error) {
161 - .eq('gestion', selectedYear) 160 + console.error('Error fetching treemap data:', data.error);
162 - .eq('entidad', entidadFiltro)
163 - .gt('devengado', 0);
164 -
165 - if (dbError) {
166 - console.error('Error fetching treemap data:', dbError.message);
167 return; 161 return;
168 } 162 }
169 163
...@@ -171,7 +165,7 @@ ...@@ -171,7 +165,7 @@
171 gestion: d.gestion, 165 gestion: d.gestion,
172 nivel: d.nivel, 166 nivel: d.nivel,
173 finfun: d.finfun, 167 finfun: d.finfun,
174 - desc_finfun: d.desc_funcion, 168 + desc_finfun: d.desc_finfun,
175 parent: d.parent, 169 parent: d.parent,
176 devengado: d.devengado || 0 170 devengado: d.devengado || 0
177 })); 171 }));
...@@ -186,15 +180,11 @@ ...@@ -186,15 +180,11 @@
186 async function loadEntitiesForYear(year) { 180 async function loadEntitiesForYear(year) {
187 if (!year) return; 181 if (!year) return;
188 try { 182 try {
189 - const { data, error: dbError } = await supabase 183 + const res = await fetch('/api/objeto-treemap-entidades');
190 - .schema('ppto') 184 + const data = await res.json();
191 - .from('entidades_treemap') 185 +
192 - .select('entidad, desc_entidad, sigla_entidad') 186 + if (data.error) {
193 - .eq('gestion', year) 187 + console.error('Error loading entities:', data.error);
194 - .order('desc_entidad');
195 -
196 - if (dbError) {
197 - console.error('Error loading entities:', dbError.message);
198 return; 188 return;
199 } 189 }
200 entities = data || []; 190 entities = data || [];
...@@ -580,13 +570,10 @@ ...@@ -580,13 +570,10 @@
580 document.body.offsetHeight; // Force reflow 570 document.body.offsetHeight; // Force reflow
581 }); 571 });
582 572
583 - const { data, error } = await supabase 573 + const clasRes = await fetch('/api/finfun-clasificador');
584 - .schema('ppto') 574 + const data = await clasRes.json();
585 - .from('clas_finfun')
586 - .select('*')
587 - .order('finfun');
588 575
589 - if (!error && data) { 576 + if (Array.isArray(data)) {
590 allItems = data; 577 allItems = data;
591 578
592 // Extraer finalidades únicas (nivel más agregado) 579 // Extraer finalidades únicas (nivel más agregado)
...@@ -842,55 +829,6 @@ ...@@ -842,55 +829,6 @@
842 Jerarquía: Finalidad → Grupo Función → Función 829 Jerarquía: Finalidad → Grupo Función → Función
843 </p> 830 </p>
844 831
845 - <!-- Toggle de modos: Lista, Mapa, Comparar + Botón filtros móvil -->
846 - <div class="flex items-center gap-3">
847 - <div class="header-modes">
848 - <button
849 - class="header-mode-btn"
850 - class:active={viewMode === 'lista'}
851 - onclick={() => setMode('lista')}
852 - >
853 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
854 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
855 - </svg>
856 - Lista
857 - </button>
858 - <button
859 - class="header-mode-btn"
860 - class:active={viewMode === 'mapa'}
861 - onclick={() => setMode('mapa')}
862 - >
863 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
864 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM14 5a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1V5zM4 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1H5a1 1 0 01-1-1v-4zM14 15a1 1 0 011-1h4a1 1 0 011 1v4a1 1 0 01-1 1h-4a1 1 0 01-1-1v-4z" />
865 - </svg>
866 - Mapa
867 - </button>
868 - <button
869 - class="header-mode-btn"
870 - class:active={viewMode === 'comparar'}
871 - onclick={() => setMode('comparar')}
872 - >
873 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
874 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
875 - </svg>
876 - Comparar
877 - </button>
878 - </div>
879 -
880 - <!-- Botón filtros para móvil en modo mapa -->
881 - {#if viewMode === 'mapa'}
882 - <button
883 - class="lg:hidden flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm"
884 - style="background-color: var(--theme-fill); color: var(--theme-titulo);"
885 - onclick={() => mapaSidebarOpen = !mapaSidebarOpen}
886 - >
887 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
888 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
889 - </svg>
890 - Filtros
891 - </button>
892 - {/if}
893 - </div>
894 </div> 832 </div>
895 </div> 833 </div>
896 </header> 834 </header>
......
...@@ -1441,52 +1441,6 @@ ...@@ -1441,52 +1441,6 @@
1441 <div class="mt-2"> 1441 <div class="mt-2">
1442 <div class="flex flex-col md:flex-row gap-4 md:items-center md:justify-between"> 1442 <div class="flex flex-col md:flex-row gap-4 md:items-center md:justify-between">
1443 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4"> 1443 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4">
1444 - {#if viewMode === 'lista'}
1445 - <div class="header-modes">
1446 - <button
1447 - class="header-mode-btn active"
1448 - onclick={() => setMode('lista')}
1449 - >
1450 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1451 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
1452 - </svg>
1453 - Lista
1454 - </button>
1455 - <button
1456 - class="header-mode-btn"
1457 - onclick={() => setMode('mapa')}
1458 - >
1459 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1460 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
1461 - </svg>
1462 - Mapa
1463 - </button>
1464 - <button
1465 - class="header-mode-btn"
1466 - onclick={() => { setMode('comparar'); initCompareMode(); }}
1467 - >
1468 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1469 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
1470 - </svg>
1471 - Comparar
1472 - </button>
1473 - </div>
1474 -
1475 - <!-- Guía inline (solo para lista) -->
1476 - <div class="hidden sm:block text-sm border-l pl-4" style="color: var(--theme-texto); border-color: var(--theme-borde);">
1477 - <span class="flex items-center gap-1.5">
1478 - Clic en
1479 - <span class="inline-flex items-center justify-center w-5 h-5 rounded" style="background-color: color-mix(in srgb, var(--theme-accent) 20%, transparent); color: var(--theme-accent);">
1480 - <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1481 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
1482 - </svg>
1483 - </span>
1484 - para ver el presupuesto histórico ·
1485 - <span class="underline decoration-dotted font-medium" style="color: var(--theme-accent);">N var.</span>
1486 - = número de cambios en la descripción oficial
1487 - </span>
1488 - </div>
1489 - {/if}
1490 </div> 1444 </div>
1491 1445
1492 <div class="flex flex-wrap items-center gap-3 flex-shrink-0"> 1446 <div class="flex flex-wrap items-center gap-3 flex-shrink-0">
......
1 <script> 1 <script>
2 - import { supabase } from '$lib/supabase';
3 import { onMount } from 'svelte'; 2 import { onMount } from 'svelte';
4 import { page } from '$app/stores'; 3 import { page } from '$app/stores';
5 import { goto } from '$app/navigation'; 4 import { goto } from '$app/navigation';
...@@ -33,15 +32,12 @@ ...@@ -33,15 +32,12 @@
33 document.body.offsetHeight; // Force reflow 32 document.body.offsetHeight; // Force reflow
34 }); 33 });
35 34
36 - const { data, error } = await supabase 35 + try {
37 - .schema('ppto') 36 + const res = await fetch('/api/entidad-clasificador');
38 - .from('clas_institucional') 37 + const data = await res.json();
39 - .select('*')
40 - .order('desc_area')
41 - .order('desc_entidad');
42 38
43 - if (!error && data) { 39 + if (Array.isArray(data)) {
44 - allEntidades = data; 40 + allEntidades = data.sort((a, b) => (a.desc_area || '').localeCompare(b.desc_area || '') || (a.desc_entidad || '').localeCompare(b.desc_entidad || ''));
45 41
46 // Agrupar por área (segundo nivel) 42 // Agrupar por área (segundo nivel)
47 const areasMap = {}; 43 const areasMap = {};
...@@ -74,6 +70,9 @@ ...@@ -74,6 +70,9 @@
74 selectedArea = areas[0]; 70 selectedArea = areas[0];
75 } 71 }
76 } 72 }
73 + } catch (err) {
74 + console.error('Error loading clasificador:', err);
75 + }
77 76
78 loading = false; 77 loading = false;
79 }); 78 });
...@@ -238,49 +237,6 @@ ...@@ -238,49 +237,6 @@
238 237
239 <!-- Controles de visualización --> 238 <!-- Controles de visualización -->
240 <div class="mt-8"> 239 <div class="mt-8">
241 - <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4">
242 - <!-- Toggle Vista -->
243 - <div class="flex items-center gap-3">
244 - <span class="text-sm font-medium" style="color: var(--theme-titulo);">Explorar como</span>
245 - <nav class="inline-flex rounded-xl border-2 p-1 shadow-sm" style="border-color: var(--theme-titulo); background-color: var(--theme-surface);">
246 - <a
247 - href="?modo=lista"
248 - class="px-4 py-2 text-sm font-semibold rounded-lg transition-all"
249 - style="{viewMode === 'lista' ? `background-color: var(--theme-titulo); color: var(--theme-body);` : `color: var(--theme-texto);`}"
250 - onclick={(e) => { e.preventDefault(); setMode('lista'); }}
251 - >
252 - Lista
253 - </a>
254 - <a
255 - href="?modo=mapa"
256 - class="px-4 py-2 text-sm font-semibold rounded-lg transition-all"
257 - style="{viewMode === 'mapa' ? `background-color: var(--theme-titulo); color: var(--theme-body);` : `color: var(--theme-texto);`}"
258 - onclick={(e) => { e.preventDefault(); setMode('mapa'); }}
259 - >
260 - Mapa
261 - </a>
262 - <a
263 - href="?modo=comparar"
264 - class="px-4 py-2 text-sm font-semibold rounded-lg transition-all"
265 - style="{viewMode === 'comparar' ? `background-color: var(--theme-titulo); color: var(--theme-body);` : `color: var(--theme-texto);`}"
266 - onclick={(e) => { e.preventDefault(); setMode('comparar'); }}
267 - >
268 - Comparar
269 - </a>
270 - </nav>
271 - </div>
272 -
273 - <!-- Guía inline -->
274 - <div class="hidden sm:block text-sm border-l pl-4" style="color: var(--theme-texto); border-color: var(--theme-borde);">
275 - {#if viewMode === 'lista'}
276 - <span>Navega por áreas y subáreas</span>
277 - {:else if viewMode === 'mapa'}
278 - <span>Visualización geográfica del presupuesto</span>
279 - {:else}
280 - <span>Compara dos entidades o periodos</span>
281 - {/if}
282 - </div>
283 - </div>
284 </div> 240 </div>
285 </div> 241 </div>
286 </header> 242 </header>
......
...@@ -1604,52 +1604,6 @@ ...@@ -1604,52 +1604,6 @@
1604 <!-- Selector de modo + Guía inline (visible en sm+) --> 1604 <!-- Selector de modo + Guía inline (visible en sm+) -->
1605 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4"> 1605 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4">
1606 <!-- Selector de modo (solo para lista, en mapa y comparar está en el sidebar) --> 1606 <!-- Selector de modo (solo para lista, en mapa y comparar está en el sidebar) -->
1607 - {#if viewMode === 'lista'}
1608 - <div class="header-modes">
1609 - <button
1610 - class="header-mode-btn active"
1611 - onclick={() => setMode('lista')}
1612 - >
1613 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1614 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
1615 - </svg>
1616 - Lista
1617 - </button>
1618 - <button
1619 - class="header-mode-btn"
1620 - onclick={() => setMode('mapa')}
1621 - >
1622 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1623 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
1624 - </svg>
1625 - Mapa
1626 - </button>
1627 - <button
1628 - class="header-mode-btn"
1629 - onclick={() => { setMode('comparar'); initCompareMode(); }}
1630 - >
1631 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1632 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
1633 - </svg>
1634 - Comparar
1635 - </button>
1636 - </div>
1637 -
1638 - <!-- Guía inline (solo para lista) -->
1639 - <div class="hidden sm:block text-sm border-l pl-4" style="color: var(--theme-texto); border-color: var(--theme-borde);">
1640 - <span class="flex items-center gap-1.5">
1641 - Clic en
1642 - <span class="inline-flex items-center justify-center w-5 h-5 rounded" style="background-color: color-mix(in srgb, var(--theme-accent) 20%, transparent); color: var(--theme-accent);">
1643 - <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1644 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
1645 - </svg>
1646 - </span>
1647 - para ver el presupuesto histórico ·
1648 - <span class="underline decoration-dotted font-medium" style="color: var(--theme-accent);">N var.</span>
1649 - = número de cambios en la descripción oficial
1650 - </span>
1651 - </div>
1652 - {/if}
1653 </div> 1607 </div>
1654 1608
1655 <!-- Filtros (botón móvil para abrir sidebar en mapa y comparar) --> 1609 <!-- Filtros (botón móvil para abrir sidebar en mapa y comparar) -->
......
...@@ -1453,52 +1453,6 @@ ...@@ -1453,52 +1453,6 @@
1453 <div class="mt-2"> 1453 <div class="mt-2">
1454 <div class="flex flex-col md:flex-row gap-4 md:items-center md:justify-between"> 1454 <div class="flex flex-col md:flex-row gap-4 md:items-center md:justify-between">
1455 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4"> 1455 <div class="flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4">
1456 - {#if viewMode === 'lista'}
1457 - <div class="header-modes">
1458 - <button
1459 - class="header-mode-btn active"
1460 - onclick={() => setMode('lista')}
1461 - >
1462 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1463 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16" />
1464 - </svg>
1465 - Lista
1466 - </button>
1467 - <button
1468 - class="header-mode-btn"
1469 - onclick={() => setMode('mapa')}
1470 - >
1471 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1472 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" />
1473 - </svg>
1474 - Mapa
1475 - </button>
1476 - <button
1477 - class="header-mode-btn"
1478 - onclick={() => { setMode('comparar'); initCompareMode(); }}
1479 - >
1480 - <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1481 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
1482 - </svg>
1483 - Comparar
1484 - </button>
1485 - </div>
1486 -
1487 - <!-- Guía inline (solo para lista) -->
1488 - <div class="hidden sm:block text-sm border-l pl-4" style="color: var(--theme-texto); border-color: var(--theme-borde);">
1489 - <span class="flex items-center gap-1.5">
1490 - Clic en
1491 - <span class="inline-flex items-center justify-center w-5 h-5 rounded" style="background-color: color-mix(in srgb, var(--theme-accent) 20%, transparent); color: var(--theme-accent);">
1492 - <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1493 - <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
1494 - </svg>
1495 - </span>
1496 - para ver el presupuesto histórico ·
1497 - <span class="underline decoration-dotted font-medium" style="color: var(--theme-accent);">N var.</span>
1498 - = número de cambios en la descripción oficial
1499 - </span>
1500 - </div>
1501 - {/if}
1502 </div> 1456 </div>
1503 1457
1504 <!-- Filtros (botón móvil para abrir sidebar en mapa y comparar) --> 1458 <!-- Filtros (botón móvil para abrir sidebar en mapa y comparar) -->
......
This diff is collapsed. Click to expand it.
1 import { error } from '@sveltejs/kit'; 1 import { error } from '@sveltejs/kit';
2 2
3 -const API_BASE = 'http://136.112.29.74/api/finfun'; 3 +import { API_HOST } from '$lib/api.js';
4 +const API_BASE = API_HOST + '/api/finfun';
4 5
5 // Jerarquía finfun: Finalidad → Grupo Función → Función 6 // Jerarquía finfun: Finalidad → Grupo Función → Función
6 // Códigos con punto: "1" (finalidad), "1.1" (grpfuncion), "1.1.1" (función) 7 // Códigos con punto: "1" (finalidad), "1.1" (grpfuncion), "1.1.1" (función)
......
1 import { error } from '@sveltejs/kit'; 1 import { error } from '@sveltejs/kit';
2 2
3 -const API_BASE = 'http://136.112.29.74/api/objeto'; 3 +import { API_HOST } from '$lib/api.js';
4 +const API_BASE = API_HOST + '/api/objeto';
4 5
5 export async function load({ params }) { 6 export async function load({ params }) {
6 const { codigo } = params; 7 const { codigo } = params;
......
1 import { error } from '@sveltejs/kit'; 1 import { error } from '@sveltejs/kit';
2 2
3 -const API_BASE = 'http://136.112.29.74/api/organismo'; 3 +import { API_HOST } from '$lib/api.js';
4 +const API_BASE = API_HOST + '/api/organismo';
4 5
5 export async function load({ params }) { 6 export async function load({ params }) {
6 const { codigo } = params; 7 const { codigo } = params;
......
1 import { error } from '@sveltejs/kit'; 1 import { error } from '@sveltejs/kit';
2 2
3 -const API_BASE = 'http://136.112.29.74/api/rubro'; 3 +import { API_HOST } from '$lib/api.js';
4 +const API_BASE = API_HOST + '/api/rubro';
4 5
5 export async function load({ params }) { 6 export async function load({ params }) {
6 const { codigo } = params; 7 const { codigo } = params;
......
This diff is collapsed. Click to expand it.