aarnal80 commited on
Commit
bfbc15b
verified
1 Parent(s): 602333e

Create js/proa.js

Browse files
Files changed (1) hide show
  1. js/proa.js +356 -0
js/proa.js ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // js/proa.js - L贸gica para el visor de Gu铆as PROA (v13 - Rutas para Space)
2
+ // ======================================================================
3
+ // BLOCK START: DOM Elements Selection & Initial Setup
4
+ // ======================================================================
5
+ console.log("[proa.js v13] Script cargado. Esperando DOMContentLoaded...");
6
+ window.addEventListener('DOMContentLoaded', () => {
7
+ console.log("[proa.js v13] DOMContentLoaded detectado. Iniciando setup...");
8
+
9
+ // Selectores y Contenedores
10
+ const guideSelector = document.getElementById('guideSelector');
11
+ const diagnosisSelectorContainer = document.getElementById('diagnosis-selector-container');
12
+ const diagnosisSelector = document.getElementById('diagnosisSelector');
13
+ const guideContentDisplay = document.getElementById('guide-content-display');
14
+ const togglePediatricCheckbox = document.getElementById('togglePediatric');
15
+
16
+ // ! RUTA ACTUALIZADA AL JSON !
17
+ const guidesDataUrl = './data/guides_data.json'; // Asume que est谩 en data/
18
+
19
+ // Verificar elementos cr铆ticos
20
+ if (!guideSelector || !diagnosisSelectorContainer || !diagnosisSelector || !guideContentDisplay || !togglePediatricCheckbox) {
21
+ console.error("[proa.js v13] Error Cr铆tico: No se encontraron elementos DOM esenciales.");
22
+ guideContentDisplay.innerHTML = '<p class="text-red-500 font-semibold text-center py-10">Error: Interfaz no inicializada correctamente.</p>';
23
+ return;
24
+ }
25
+ console.log("[proa.js v13] Elementos DOM encontrados.");
26
+ // ======================================================================
27
+ // BLOCK END: DOM Elements Selection & Initial Setup
28
+ // ======================================================================
29
+
30
+ // ======================================================================
31
+ // BLOCK START: State Variables
32
+ // ======================================================================
33
+ let allGuides = []; // Almacenar谩 todas las gu铆as del JSON
34
+ let currentSelectedGuideData = null; // Guarda los datos completos de la gu铆a seleccionada
35
+ let currentGuideHTMLContent = null; // Cache para el HTML de la gu铆a actual con diagn贸sticos
36
+ // ======================================================================
37
+ // BLOCK END: State Variables
38
+ // ======================================================================
39
+
40
+ // ======================================================================
41
+ // BLOCK START: Function to Fetch Guides Data (from JSON)
42
+ // ======================================================================
43
+ async function loadGuidesData() {
44
+ console.log(`[proa.js v13] Iniciando loadGuidesData desde: ${guidesDataUrl}`);
45
+ guideSelector.innerHTML = '<option value="">Cargando...</option>';
46
+ guideSelector.disabled = true;
47
+ resetUI(); // Limpia todo
48
+
49
+ try {
50
+ console.log("[proa.js v13] Realizando fetch...");
51
+ const response = await fetch(guidesDataUrl);
52
+ console.log(`[proa.js v13] Fetch completado. Status: ${response.status}`);
53
+ if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guidesDataUrl}. Verifica que el archivo exista y sea accesible.`);
54
+
55
+ console.log("[proa.js v13] Parseando JSON...");
56
+ const rawData = await response.json();
57
+ console.log("[proa.js v13] JSON parseado.");
58
+
59
+ if (!Array.isArray(rawData)) throw new Error("El formato del JSON no es un array v谩lido.");
60
+
61
+ // Filtrar y validar gu铆as
62
+ allGuides = rawData.filter(g => g.id && g.title && g.file && typeof g.isPediatric === 'boolean');
63
+ console.log(`[proa.js v13] Gu铆as v谩lidas iniciales: ${allGuides.length}`);
64
+
65
+ // Validar estructura de diagn贸stico si existe
66
+ allGuides = allGuides.map(g => {
67
+ if (g.hasDiagnoses === true) {
68
+ if (!Array.isArray(g.diagnoses) || g.diagnoses.some(d => !d.id || !d.title)) {
69
+ console.warn(`[proa.js v13] Gu铆a '${g.title}' marcada con 'hasDiagnoses' pero la estructura 'diagnoses' es inv谩lida. Se tratar谩 como gu铆a normal.`);
70
+ return { ...g, hasDiagnoses: false, diagnoses: undefined }; // Corregir datos inv谩lidos
71
+ }
72
+ }
73
+ return g;
74
+ });
75
+
76
+ if (allGuides.length === 0) throw new Error("No se encontraron gu铆as v谩lidas en los datos despu茅s de la validaci贸n.");
77
+
78
+ // Ordenar alfab茅ticamente para el desplegable principal
79
+ allGuides.sort((a, b) => a.title.localeCompare(b.title));
80
+
81
+ console.log("[proa.js v13] Llamando a populateGuideSelector (mostrar谩 Adultos por defecto)...");
82
+ populateGuideSelector(); // Poblar el desplegable principal
83
+ guideSelector.disabled = false; // Habilitar selector principal
84
+ console.log("[proa.js v13] Carga inicial de datos completada.");
85
+
86
+ } catch (error) {
87
+ console.error("[proa.js v13] Error durante loadGuidesData:", error);
88
+ guideSelector.innerHTML = `<option value="">Error al cargar</option>`;
89
+ guideSelector.disabled = true;
90
+ guideContentDisplay.innerHTML = `<p class="text-red-600 font-semibold text-center py-10">Error cr铆tico al cargar datos: ${error.message}. Revisa la consola y el archivo '${guidesDataUrl}'.</p>`;
91
+ }
92
+ }
93
+ // ======================================================================
94
+ // BLOCK END: Function to Fetch Guides Data (from JSON)
95
+ // ======================================================================
96
+
97
+ // ======================================================================
98
+ // BLOCK START: UI Update Functions
99
+ // ======================================================================
100
+
101
+ // Resetea el 谩rea de contenido y el selector de diagn贸stico
102
+ function resetUI(fullReset = true) {
103
+ guideContentDisplay.innerHTML = '<div class="text-center py-16 text-gray-400"><i class="fas fa-file-alt text-5xl mb-4"></i><p>Selecciona una gu铆a del desplegable.</p></div>';
104
+ diagnosisSelector.innerHTML = '<option value="">-- Seleccione Diagn贸stico --</option>'; // Limpiar opciones
105
+ diagnosisSelectorContainer.classList.add('hidden'); // Ocultar contenedor
106
+ currentSelectedGuideData = null;
107
+ currentGuideHTMLContent = null; // Limpiar cache de HTML
108
+
109
+ if(fullReset && guideSelector.options.length > 1) {
110
+ guideSelector.value = ""; // Resetear tambi茅n el selector principal si no es el reset inicial
111
+ }
112
+ }
113
+
114
+ // Llena el selector PRINCIPAL de gu铆as aplicando el filtro Pedi谩trico/Adulto
115
+ function populateGuideSelector() {
116
+ const showOnlyPediatric = togglePediatricCheckbox.checked;
117
+ console.log(`[proa.js v13] Poblando selector principal. Mostrar Pedi谩tricas: ${showOnlyPediatric}`);
118
+
119
+ // Filtrar por Adulto o Pedi谩trico
120
+ const filteredGuides = allGuides.filter(guide => guide.isPediatric === showOnlyPediatric);
121
+
122
+ // Ordenar alfab茅ticamente (ya deber铆an estar ordenadas, pero por si acaso)
123
+ filteredGuides.sort((a, b) => a.title.localeCompare(b.title));
124
+
125
+ // Limpiar selector principal
126
+ guideSelector.innerHTML = `<option value="">-- Seleccione Gu铆a (${showOnlyPediatric ? 'Pedi谩tricas' : 'Adultos'}) --</option>`;
127
+
128
+ if (filteredGuides.length > 0) {
129
+ const fragment = document.createDocumentFragment();
130
+ filteredGuides.forEach(guide => {
131
+ const option = document.createElement('option');
132
+ option.value = guide.id; // Usar el ID 煤nico de la gu铆a como valor
133
+ option.textContent = guide.isPediatric ? `${guide.title} (PED)` : guide.title;
134
+ // Guardar datos importantes en el dataset para f谩cil acceso
135
+ option.dataset.hasDiagnoses = guide.hasDiagnoses || false;
136
+ option.dataset.file = guide.file; // La ruta al archivo HTML de la gu铆a (debe estar correcta en el JSON)
137
+ fragment.appendChild(option);
138
+ });
139
+ guideSelector.appendChild(fragment);
140
+ console.log(`[proa.js v13] Selector principal poblado con ${filteredGuides.length} gu铆as.`);
141
+ } else {
142
+ guideSelector.innerHTML = `<option value="">-- No hay gu铆as ${showOnlyPediatric ? 'Pedi谩tricas' : 'Adultos'} --</option>`;
143
+ console.log(`[proa.js v13] No se encontraron gu铆as para el filtro actual.`);
144
+ }
145
+ resetUI(false); // Resetear UI secundaria sin deseleccionar la gu铆a principal
146
+ }
147
+
148
+ // Puebla el selector de DIAGN脫STICOS
149
+ function populateDiagnosisSelector(guideData) {
150
+ console.log(`[proa.js v13] Poblando selector de diagn贸sticos para: ${guideData.title}`);
151
+ diagnosisSelector.innerHTML = '<option value="">-- Seleccione Diagn贸stico --</option>'; // Limpiar
152
+
153
+ if (guideData.hasDiagnoses && Array.isArray(guideData.diagnoses)) {
154
+ const fragment = document.createDocumentFragment();
155
+ guideData.diagnoses.forEach(diagnosis => {
156
+ const option = document.createElement('option');
157
+ option.value = diagnosis.id; // Usar el ID del diagn贸stico como valor
158
+ option.textContent = diagnosis.title;
159
+ fragment.appendChild(option);
160
+ });
161
+ diagnosisSelector.appendChild(fragment);
162
+ diagnosisSelectorContainer.classList.remove('hidden'); // Mostrar contenedor
163
+ console.log(`[proa.js v13] Selector de diagn贸sticos poblado con ${guideData.diagnoses.length} opciones.`);
164
+ } else {
165
+ console.warn("[proa.js v13] Se intent贸 poblar diagn贸sticos para una gu铆a sin ellos o con datos inv谩lidos.");
166
+ diagnosisSelectorContainer.classList.add('hidden'); // Asegurarse que est茅 oculto
167
+ }
168
+ }
169
+
170
+ // ======================================================================
171
+ // BLOCK END: UI Update Functions
172
+ // ======================================================================
173
+
174
+ // ======================================================================
175
+ // BLOCK START: Content Loading Functions
176
+ // ======================================================================
177
+
178
+ // Carga el CONTENIDO COMPLETO de una gu铆a (para gu铆as SIN diagn贸sticos)
179
+ async function loadFullGuideContent(guideFile) {
180
+ if (!guideFile) {
181
+ resetUI();
182
+ return;
183
+ }
184
+ // ! RUTA ACTUALIZADA PARA CARGAR GU脥A !
185
+ const guideUrl = `./${guideFile}`; // Asume que la ruta en JSON (ej. "guias/archivo.html") es relativa a la ra铆z
186
+ console.log(`[proa.js v13] Solicitando contenido COMPLETO de: ${guideUrl}`);
187
+ guideContentDisplay.innerHTML = '<div class="text-center py-20"><i class="fas fa-spinner fa-spin text-3xl text-gray-400"></i><p class="mt-2 text-gray-500">Cargando gu铆a completa...</p></div>';
188
+ currentGuideHTMLContent = null; // Limpiar cache
189
+
190
+ try {
191
+ const response = await fetch(guideUrl); // Usar la ruta completa
192
+ if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideUrl}`);
193
+ const htmlText = await response.text();
194
+
195
+ // Parsear y extraer contenido principal (mismo m茅todo que antes)
196
+ const parser = new DOMParser();
197
+ const doc = parser.parseFromString(htmlText, 'text/html');
198
+ // Intentar selector espec铆fico, si no, usar body
199
+ const contentNode = doc.querySelector('.treatment-card') || doc.body; // Ajustado para buscar .treatment-card si no hay un contenedor principal definido
200
+
201
+ if (contentNode) {
202
+ const clonedContent = contentNode.cloneNode(true);
203
+ // Eliminar scripts del contenido clonado
204
+ const scripts = clonedContent.querySelectorAll('script');
205
+ scripts.forEach(script => script.remove());
206
+ if (scripts.length > 0) console.log(`[proa.js v13] Eliminados ${scripts.length} script(s) de ${guideUrl}.`);
207
+
208
+ guideContentDisplay.innerHTML = ''; // Limpiar 谩rea
209
+ guideContentDisplay.appendChild(clonedContent); // A帽adir contenido limpio
210
+ console.log(`[proa.js v13] Contenido COMPLETO de ${guideUrl} mostrado.`);
211
+ guideContentDisplay.scrollTop = 0; // Ir al inicio del contenido
212
+ } else {
213
+ throw new Error(`No se encontr贸 nodo de contenido principal en '${guideUrl}'.`);
214
+ }
215
+ } catch (error) {
216
+ console.error(`[proa.js v13] Error al cargar/mostrar contenido COMPLETO de ${guideUrl}:`, error);
217
+ guideContentDisplay.innerHTML = `<div class="text-center py-20 text-red-600">Error al cargar contenido: ${error.message}</div>`;
218
+ }
219
+ }
220
+
221
+ // Carga y cachea el HTML de una gu铆a CON diagn贸sticos, luego muestra el diagn贸stico especificado
222
+ async function loadAndDisplayDiagnosisContent(guideData, diagnosisId) {
223
+ // ! RUTA ACTUALIZADA PARA CARGAR GU脥A !
224
+ const guideFileUrl = `./${guideData.file}`; // Asume que la ruta en JSON es relativa a la ra铆z
225
+ console.log(`[proa.js v13] Solicitando diagn贸stico '${diagnosisId}' de la gu铆a '${guideData.title}' (${guideFileUrl})`);
226
+ guideContentDisplay.innerHTML = '<div class="text-center py-20"><i class="fas fa-spinner fa-spin text-3xl text-gray-400"></i><p class="mt-2 text-gray-500">Cargando diagn贸stico...</p></div>';
227
+
228
+ try {
229
+ // Si el HTML de la gu铆a no est谩 cacheado, cargarlo
230
+ if (!currentGuideHTMLContent) {
231
+ console.log(`[proa.js v13] HTML de ${guideFileUrl} no cacheado. Realizando fetch...`);
232
+ const response = await fetch(guideFileUrl); // Usar la ruta completa
233
+ if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideFileUrl}`);
234
+ currentGuideHTMLContent = await response.text();
235
+ console.log(`[proa.js v13] HTML de ${guideFileUrl} cargado y cacheado.`);
236
+ } else {
237
+ console.log(`[proa.js v13] Usando HTML cacheado de ${guideFileUrl}.`);
238
+ }
239
+
240
+ // Parsear el HTML (cacheado o reci茅n cargado)
241
+ const parser = new DOMParser();
242
+ const doc = parser.parseFromString(currentGuideHTMLContent, 'text/html');
243
+
244
+ // Buscar el div espec铆fico del diagn贸stico por su ID
245
+ const diagnosisNode = doc.getElementById(diagnosisId);
246
+
247
+ if (diagnosisNode) {
248
+ console.log(`[proa.js v13] Nodo para diagn贸stico ID '${diagnosisId}' encontrado.`);
249
+ const clonedDiagnosisContent = diagnosisNode.cloneNode(true);
250
+
251
+ // Opcional: Limpiar scripts si los hubiera dentro del div del diagn贸stico
252
+ const scripts = clonedDiagnosisContent.querySelectorAll('script');
253
+ scripts.forEach(script => script.remove());
254
+ if (scripts.length > 0) console.log(`[proa.js v13] Eliminados ${scripts.length} script(s) del nodo de diagn贸stico.`);
255
+
256
+ guideContentDisplay.innerHTML = ''; // Limpiar 谩rea
257
+ guideContentDisplay.appendChild(clonedDiagnosisContent); // A帽adir contenido del diagn贸stico
258
+ console.log(`[proa.js v13] Contenido del diagn贸stico '${diagnosisId}' mostrado.`);
259
+ guideContentDisplay.scrollTop = 0; // Ir al inicio
260
+ } else {
261
+ throw new Error(`No se encontr贸 el elemento con ID '${diagnosisId}' dentro de '${guideFileUrl}'. Verifica la estructura del HTML de la gu铆a.`);
262
+ }
263
+ } catch (error) {
264
+ console.error(`[proa.js v13] Error al cargar/mostrar diagn贸stico '${diagnosisId}' de ${guideFileUrl}:`, error);
265
+ guideContentDisplay.innerHTML = `<div class="text-center py-20 text-red-600">Error al cargar diagn贸stico: ${error.message}</div>`;
266
+ // Podr铆amos querer limpiar el cache si falla la carga
267
+ // currentGuideHTMLContent = null;
268
+ }
269
+ }
270
+
271
+ // ======================================================================
272
+ // BLOCK END: Content Loading Functions
273
+ // ======================================================================
274
+
275
+ // ======================================================================
276
+ // BLOCK START: Event Listeners Setup
277
+ // ======================================================================
278
+
279
+ // --- Listener para el selector PRINCIPAL de Gu铆as ---
280
+ guideSelector.addEventListener('change', (event) => {
281
+ const selectedOption = event.target.selectedOptions[0];
282
+ const guideId = selectedOption.value;
283
+ console.log(`[proa.js v13] Cambi贸 la gu铆a principal seleccionada. ID: ${guideId}`);
284
+
285
+ // Limpiar UI secundaria y cache de contenido
286
+ resetUI(false); // No resetea el selector principal
287
+
288
+ if (!guideId) {
289
+ // Si se seleccion贸 la opci贸n placeholder "-- Seleccione Gu铆a --"
290
+ return; // No hacer nada m谩s
291
+ }
292
+
293
+ // Encontrar los datos completos de la gu铆a seleccionada
294
+ currentSelectedGuideData = allGuides.find(g => g.id === guideId);
295
+
296
+ if (!currentSelectedGuideData) {
297
+ console.error(`[proa.js v13] No se encontraron datos para la gu铆a con ID: ${guideId}`);
298
+ guideContentDisplay.innerHTML = '<p class="text-red-500 text-center py-10">Error: Datos de gu铆a no encontrados.</p>';
299
+ return;
300
+ }
301
+
302
+ // Decidir si mostrar selector de diagn贸stico o cargar contenido completo
303
+ if (currentSelectedGuideData.hasDiagnoses === true) {
304
+ console.log(`[proa.js v13] La gu铆a '${currentSelectedGuideData.title}' tiene diagn贸sticos. Poblando selector secundario.`);
305
+ populateDiagnosisSelector(currentSelectedGuideData);
306
+ // Mostrar un mensaje inicial diferente en el 谩rea de contenido
307
+ guideContentDisplay.innerHTML = '<div class="text-center py-16 text-gray-400"><i class="fas fa-stethoscope text-5xl mb-4"></i><p>Selecciona un diagn贸stico espec铆fico del desplegable superior.</p></div>';
308
+ } else {
309
+ console.log(`[proa.js v13] La gu铆a '${currentSelectedGuideData.title}' no tiene diagn贸sticos. Cargando contenido completo.`);
310
+ diagnosisSelectorContainer.classList.add('hidden'); // Asegurarse que el selector de diagn贸stico est茅 oculto
311
+ loadFullGuideContent(currentSelectedGuideData.file); // Pasamos la ruta relativa desde el JSON
312
+ }
313
+ });
314
+
315
+ // --- Listener para el selector SECUNDARIO de Diagn贸sticos ---
316
+ diagnosisSelector.addEventListener('change', (event) => {
317
+ const diagnosisId = event.target.value;
318
+ console.log(`[proa.js v13] Cambi贸 el diagn贸stico seleccionado. ID: ${diagnosisId}`);
319
+
320
+ if (!diagnosisId) {
321
+ // Si se seleccion贸 "-- Seleccione Diagn贸stico --"
322
+ guideContentDisplay.innerHTML = '<div class="text-center py-16 text-gray-400"><i class="fas fa-stethoscope text-5xl mb-4"></i><p>Selecciona un diagn贸stico espec铆fico del desplegable superior.</p></div>';
323
+ return;
324
+ }
325
+
326
+ if (currentSelectedGuideData && currentSelectedGuideData.hasDiagnoses) {
327
+ loadAndDisplayDiagnosisContent(currentSelectedGuideData, diagnosisId);
328
+ } else {
329
+ console.error("[proa.js v13] Se intent贸 cargar un diagn贸stico pero no hay gu铆a con diagn贸sticos seleccionada.");
330
+ guideContentDisplay.innerHTML = '<p class="text-red-500 text-center py-10">Error: Gu铆a base no seleccionada correctamente.</p>';
331
+ }
332
+ });
333
+
334
+ // --- Listener para el checkbox Pedi谩trico/Adulto ---
335
+ togglePediatricCheckbox.addEventListener('change', () => {
336
+ console.log('[proa.js v13] Cambiado filtro pedi谩trico.');
337
+ // Repoblar el selector principal y resetear completamente la UI
338
+ populateGuideSelector();
339
+ // resetUI() ya se llama dentro de populateGuideSelector, as铆 que no hace falta llamarlo de nuevo expl铆citamente aqu铆.
340
+ });
341
+
342
+ console.log("[proa.js v13] Listeners a帽adidos.");
343
+ // ======================================================================
344
+ // BLOCK END: Event Listeners Setup
345
+ // ======================================================================
346
+
347
+ // ======================================================================
348
+ // BLOCK START: Initial Execution
349
+ // ======================================================================
350
+ loadGuidesData(); // Cargar JSON e iniciar UI
351
+ // ======================================================================
352
+ // BLOCK END: Initial Execution
353
+ // ======================================================================
354
+
355
+ }); // Fin DOMContentLoaded
356
+ console.log("[proa.js v13] Script completamente definido.");