aarnal80 commited on
Commit
cee812a
·
verified ·
1 Parent(s): 75291da

Create proa.js

Browse files
Files changed (1) hide show
  1. js/proa.js +280 -0
js/proa.js ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // js/proa.js - Lógica para el visor de Guías PROA
2
+
3
+ // ======================================================================
4
+ // BLOCK START: DOM Elements Selection & Initial Setup
5
+ // ======================================================================
6
+ console.log("[proa.js] Script cargado. Esperando DOMContentLoaded...");
7
+
8
+ // Usamos DOMContentLoaded para asegurarnos que el HTML está completamente cargado y parseado
9
+ window.addEventListener('DOMContentLoaded', () => {
10
+ console.log("[proa.js] DOMContentLoaded detectado. Iniciando setup...");
11
+
12
+ // Seleccionar los elementos del DOM que necesitaremos manipular
13
+ const guideListContainer = document.getElementById('guide-list-container'); // Div donde irá la lista de guías
14
+ const guideContentArea = document.getElementById('guide-content-area'); // Div donde se mostrará el contenido de la guía
15
+ const togglePediatricCheckbox = document.getElementById('togglePediatric'); // Checkbox para filtrar guías pediátricas
16
+
17
+ // URL del archivo que contiene el índice principal de las guías (el index.html con los enlaces a cada guía)
18
+ // Asegúrate de que este archivo esté en la raíz de tu proyecto en Hugging Face
19
+ const guideIndexUrl = 'index.html';
20
+
21
+ // Verificación de que los elementos esenciales existen en proa.html
22
+ if (!guideListContainer || !guideContentArea || !togglePediatricCheckbox) {
23
+ console.error("[proa.js] Error Crítico: No se encontraron elementos esenciales del DOM (contenedor lista, área contenido o checkbox). Revisa proa.html.");
24
+ // Mostrar un error en la interfaz si falta algo
25
+ if(guideListContainer) guideListContainer.innerHTML = '<p class="text-red-500 font-semibold">Error: No se pudo inicializar la interfaz del visor de guías.</p>';
26
+ return; // Detener la ejecución del script si falta algo crítico
27
+ }
28
+ // ======================================================================
29
+ // BLOCK END: DOM Elements Selection & Initial Setup
30
+ // ======================================================================
31
+
32
+ // ======================================================================
33
+ // BLOCK START: State Variable
34
+ // ======================================================================
35
+ // Variable para almacenar los datos de todas las guías una vez cargados del índice
36
+ // Estructura: [{ title: "Nombre Guía", url: "archivo.html", isPediatric: true/false }, ...]
37
+ let allGuidesData = [];
38
+ // ======================================================================
39
+ // BLOCK END: State Variable
40
+ // ======================================================================
41
+
42
+ // ======================================================================
43
+ // BLOCK START: Function to Fetch and Parse Guide Index (Cargar Índice)
44
+ // ======================================================================
45
+ // Función asíncrona para cargar y procesar el archivo index.html de las guías
46
+ async function loadGuideIndex() {
47
+ console.log(`[proa.js] Cargando índice de guías desde: ${guideIndexUrl}`);
48
+ // Mostrar indicador de carga inicial en la lista
49
+ guideListContainer.innerHTML = '<p class="text-gray-500">Cargando lista de guías...</p>';
50
+ try {
51
+ // Intentar obtener el contenido del archivo índice usando fetch
52
+ // NOTA: Requiere que la página se sirva desde un servidor (http:// o https://),
53
+ // no funcionará correctamente si se abre como archivo local (file:///) por CORS.
54
+ const response = await fetch(guideIndexUrl);
55
+
56
+ // Verificar si la carga fue exitosa (status 200 OK)
57
+ if (!response.ok) {
58
+ throw new Error(`Error HTTP ${response.status} al cargar ${guideIndexUrl}: ${response.statusText}`);
59
+ }
60
+
61
+ // Obtener el contenido HTML como texto
62
+ const htmlText = await response.text();
63
+ console.log("[proa.js] Índice HTML cargado correctamente, iniciando parseo...");
64
+
65
+ // Usar DOMParser para convertir el texto HTML en un documento DOM manipulable
66
+ const parser = new DOMParser();
67
+ const doc = parser.parseFromString(htmlText, 'text/html');
68
+
69
+ // Buscar todos los enlaces ('a') que tengan la clase 'category-card' dentro del div con clase 'grid'
70
+ // (Basado en la estructura de tu archivo index.html de guías)
71
+ const guideLinks = doc.querySelectorAll('.grid a.category-card');
72
+ console.log(`[proa.js] Parseo completado. Encontrados ${guideLinks.length} enlaces de guías en el índice.`);
73
+
74
+ allGuidesData = []; // Limpiar datos previos por si se recarga
75
+
76
+ // Iterar sobre cada enlace encontrado para extraer la información
77
+ guideLinks.forEach((link, index) => {
78
+ const url = link.getAttribute('href'); // Obtener el archivo HTML de la guía (ej. "digestivo.html")
79
+ const titleElement = link.querySelector('.category-text'); // Elemento que contiene el título
80
+
81
+ // Extraer el título base y verificar si tiene la etiqueta pediátrica
82
+ let title = 'Título Desconocido';
83
+ let isPediatric = false;
84
+
85
+ if (titleElement) {
86
+ // Clonamos el nodo para poder manipularlo sin afectar al original durante el proceso
87
+ const titleClone = titleElement.cloneNode(true);
88
+ // Buscamos y eliminamos la etiqueta pediátrica si existe DENTRO del clon
89
+ const pediatricTag = titleClone.querySelector('.pediatric-tag');
90
+ if (pediatricTag) {
91
+ isPediatric = true;
92
+ pediatricTag.remove(); // Eliminar la etiqueta del clon para obtener solo el título base
93
+ }
94
+ title = titleClone.textContent.trim(); // Obtener el texto limpio
95
+ }
96
+
97
+ // Si tenemos URL y un título válido, guardar los datos
98
+ if (url && title !== 'Título Desconocido') {
99
+ allGuidesData.push({
100
+ title: title, // Nombre limpio de la guía
101
+ url: url, // Archivo HTML de la guía
102
+ isPediatric: isPediatric // Booleano indicando si es pediátrica
103
+ });
104
+ } else {
105
+ console.warn(`[proa.js] Enlace de guía #${index+1} omitido por falta de URL o título claro:`, link.outerHTML);
106
+ }
107
+ });
108
+
109
+ console.log("[proa.js] Datos de guías extraídos y almacenados:", allGuidesData);
110
+
111
+ // Una vez extraídos los datos, llamar a la función para mostrar la lista en la UI
112
+ renderGuideList();
113
+
114
+ } catch (error) {
115
+ // Manejo de errores durante la carga o el parseo
116
+ console.error("[proa.js] Error fatal al cargar o parsear el índice de guías:", error);
117
+ guideListContainer.innerHTML = `
118
+ <p class="text-red-600 font-semibold">Error al cargar lista de guías.</p>
119
+ <p class="text-sm text-gray-600 mt-1">Detalle: ${error.message}.</p>
120
+ <p class="text-xs text-gray-500 mt-2">Asegúrate de que el archivo '${guideIndexUrl}' exista en la raíz del proyecto y que la aplicación se ejecute desde un servidor web (Hugging Face o local), no como archivo local (file:///...).</p>`;
121
+ // Limpiar también el área de contenido en caso de error
122
+ guideContentArea.innerHTML = '<p class="text-gray-500 text-center mt-10">Error al cargar guías.</p>';
123
+ }
124
+ }
125
+ // ======================================================================
126
+ // BLOCK END: Function to Fetch and Parse Guide Index
127
+ // ======================================================================
128
+
129
+ // ======================================================================
130
+ // BLOCK START: Function to Render Guide List (Mostrar Lista en UI)
131
+ // ======================================================================
132
+ // Función para generar el HTML de la lista de guías y mostrarlo
133
+ function renderGuideList() {
134
+ console.log("[proa.js] Renderizando lista de guías en la UI...");
135
+ guideListContainer.innerHTML = ''; // Limpiar el contenedor antes de añadir nuevos elementos
136
+
137
+ // Verificar el estado del checkbox para saber si mostrar las guías pediátricas
138
+ const showPediatric = togglePediatricCheckbox.checked;
139
+ console.log(`[proa.js] Filtro pediátrico activado: ${showPediatric}`);
140
+
141
+ // Filtrar la lista completa de guías según el estado del checkbox
142
+ const filteredGuides = allGuidesData.filter(guide => {
143
+ // Mantener la guía si NO es pediátrica, O si ES pediátrica Y el checkbox está marcado
144
+ return !guide.isPediatric || showPediatric;
145
+ });
146
+
147
+ // Si no hay guías tras filtrar, mostrar un mensaje
148
+ if (filteredGuides.length === 0) {
149
+ guideListContainer.innerHTML = '<p class="text-gray-500">No hay guías para mostrar.</p>';
150
+ console.log("[proa.js] No hay guías para mostrar con el filtro actual.");
151
+ return;
152
+ }
153
+
154
+ // Crear y añadir cada elemento de la lista al contenedor
155
+ filteredGuides.forEach(guide => {
156
+ const listItem = document.createElement('a'); // Usamos 'a' para que sea semánticamente un enlace/botón
157
+ listItem.href = '#'; // Usamos '#' para evitar navegación, el click lo maneja JS
158
+ listItem.className = 'guide-list-item block'; // Aplicar clases de estilo definidas en proa.html
159
+ listItem.dataset.url = guide.url; // Guardar la URL real en un atributo data-* para fácil acceso
160
+ listItem.textContent = guide.title; // Poner el título base como texto
161
+
162
+ // Si la guía es pediátrica, añadir la clase y la etiqueta visual
163
+ if (guide.isPediatric) {
164
+ listItem.classList.add('pediatric'); // Clase para posible estilo específico
165
+ const tag = document.createElement('span');
166
+ tag.className = 'pediatric-tag-inline'; // Clase para la etiqueta "PED"
167
+ tag.textContent = 'PED';
168
+ listItem.appendChild(tag); // Añadir la etiqueta al final del texto del título
169
+ }
170
+
171
+ // Añadir el listener para que al hacer clic se cargue el contenido de esta guía
172
+ listItem.addEventListener('click', (event) => {
173
+ event.preventDefault(); // Prevenir el comportamiento por defecto del enlace '#'
174
+ console.log(`[proa.js] Clic en guía: ${guide.title} (${guide.url})`);
175
+ loadGuideContent(guide.url); // Llamar a la función que carga el contenido
176
+ });
177
+
178
+ guideListContainer.appendChild(listItem); // Añadir el elemento creado al contenedor de la lista
179
+ });
180
+ console.log(`[proa.js] Lista renderizada con ${filteredGuides.length} guías.`);
181
+ }
182
+ // ======================================================================
183
+ // BLOCK END: Function to Render Guide List
184
+ // ======================================================================
185
+
186
+ // ======================================================================
187
+ // BLOCK START: Function to Load Guide Content (Cargar Contenido Guía)
188
+ // ======================================================================
189
+ // Función asíncrona para cargar el contenido HTML de una guía específica
190
+ async function loadGuideContent(guideUrl) {
191
+ console.log(`[proa.js] Solicitando contenido de la guía: ${guideUrl}`);
192
+ // Mostrar indicador de carga en el área de contenido
193
+ guideContentArea.innerHTML = '<p class="text-gray-500 text-center mt-10"><i class="fas fa-spinner fa-spin mr-2"></i>Cargando contenido de la guía...</p>';
194
+
195
+ try {
196
+ // Intentar obtener el contenido del archivo HTML de la guía específica
197
+ // NOTA: También requiere ejecución desde servidor (http:// o https://) por CORS.
198
+ const response = await fetch(guideUrl);
199
+ if (!response.ok) {
200
+ throw new Error(`Error HTTP ${response.status} al cargar ${guideUrl}: ${response.statusText}`);
201
+ }
202
+
203
+ // Obtener el contenido HTML como texto
204
+ const htmlText = await response.text();
205
+ console.log(`[proa.js] Contenido HTML de ${guideUrl} cargado, extrayendo sección relevante...`);
206
+
207
+ // Parsear el HTML de la guía
208
+ const parser = new DOMParser();
209
+ const doc = parser.parseFromString(htmlText, 'text/html');
210
+
211
+ // Extraer el nodo de contenido principal. ¡Este selector es CRUCIAL!
212
+ // Debe coincidir con el contenedor principal en TODOS tus archivos HTML de guías.
213
+ // Basado en tus archivos, parece ser: <div class="max-w-4xl mx-auto px-4 py-8">
214
+ const contentNode = doc.querySelector('.max-w-4xl.mx-auto.px-4.py-8');
215
+
216
+ if (contentNode) {
217
+ // Clonamos el nodo para asegurar que no modificamos el documento parseado original
218
+ const clonedContent = contentNode.cloneNode(true);
219
+
220
+ // **Importante:** Eliminar los scripts internos de las guías cargadas.
221
+ // Tus guías tienen un script al final para manejar su propio selector interno.
222
+ // Si no lo eliminamos, podría interferir o dar errores al cargarlo aquí.
223
+ const scripts = clonedContent.querySelectorAll('script');
224
+ scripts.forEach(script => script.remove());
225
+ if (scripts.length > 0) {
226
+ console.log(`[proa.js] Eliminados ${scripts.length} script(s) internos de la guía cargada.`);
227
+ }
228
+
229
+ // Limpiar el área de contenido y añadir el contenido extraído de la guía
230
+ guideContentArea.innerHTML = '';
231
+ guideContentArea.appendChild(clonedContent);
232
+ console.log(`[proa.js] Contenido de ${guideUrl} mostrado correctamente.`);
233
+
234
+ } else {
235
+ // Error si no se encuentra el contenedor esperado dentro del HTML de la guía
236
+ console.error(`[proa.js] No se pudo encontrar el nodo de contenido principal (selector: '.max-w-4xl.mx-auto.px-4.py-8') en ${guideUrl}`);
237
+ throw new Error("Estructura interna del archivo de guía no reconocida.");
238
+ }
239
+
240
+ } catch (error) {
241
+ // Manejo de errores al cargar o procesar el contenido de la guía
242
+ console.error(`[proa.js] Error al cargar o mostrar el contenido de ${guideUrl}:`, error);
243
+ guideContentArea.innerHTML = `
244
+ <p class="text-red-600 font-semibold text-center mt-10">Error al cargar el contenido de la guía.</p>
245
+ <p class="text-sm text-gray-600 mt-1 text-center">Detalle: ${error.message}.</p>
246
+ <p class="text-xs text-gray-500 mt-2 text-center">Verifica que el archivo '${guideUrl}' exista y que la aplicación se ejecute desde un servidor web.</p>`;
247
+ }
248
+ }
249
+ // ======================================================================
250
+ // BLOCK END: Function to Load Guide Content
251
+ // ======================================================================
252
+
253
+ // ======================================================================
254
+ // BLOCK START: Event Listeners Setup
255
+ // ======================================================================
256
+ // Añadir listener al checkbox de filtro pediátrico.
257
+ // Cada vez que cambie su estado (marcado/desmarcado), volver a renderizar la lista.
258
+ togglePediatricCheckbox.addEventListener('change', renderGuideList);
259
+ console.log("[proa.js] Listener añadido al checkbox pediátrico.");
260
+
261
+ // (Opcional: Añadir aquí listeners para el botón de Configuración IA si se activa en proa.html)
262
+ // const btnConfigProa = document.getElementById('btnConfigProa'); ... etc ...
263
+ // ======================================================================
264
+ // BLOCK END: Event Listeners Setup
265
+ // ======================================================================
266
+
267
+ // ======================================================================
268
+ // BLOCK START: Initial Execution
269
+ // ======================================================================
270
+ // Llamar a la función para cargar el índice de guías tan pronto como el DOM esté listo.
271
+ // Esto iniciará todo el proceso.
272
+ loadGuideIndex();
273
+ console.log("[proa.js] Llamada inicial a loadGuideIndex() realizada.");
274
+ // ======================================================================
275
+ // BLOCK END: Initial Execution
276
+ // ======================================================================
277
+
278
+ }); // Fin del listener DOMContentLoaded
279
+
280
+ console.log("[proa.js] Script completamente definido.");