// js/proa.js - Lógica para el visor de Guías PROA (v12 - Con Diagnósticos) // ====================================================================== // BLOCK START: DOM Elements Selection & Initial Setup // ====================================================================== console.log("[proa.js v12] Script cargado. Esperando DOMContentLoaded..."); window.addEventListener('DOMContentLoaded', () => { console.log("[proa.js v12] DOMContentLoaded detectado. Iniciando setup..."); // Selectores y Contenedores const guideSelector = document.getElementById('guideSelector'); const diagnosisSelectorContainer = document.getElementById('diagnosis-selector-container'); const diagnosisSelector = document.getElementById('diagnosisSelector'); const guideContentDisplay = document.getElementById('guide-content-display'); const togglePediatricCheckbox = document.getElementById('togglePediatric'); const guidesDataUrl = 'guides_data.json'; // Asume que está en proa/ // Verificar elementos críticos if (!guideSelector || !diagnosisSelectorContainer || !diagnosisSelector || !guideContentDisplay || !togglePediatricCheckbox) { console.error("[proa.js v12] Error Crítico: No se encontraron elementos DOM esenciales."); guideContentDisplay.innerHTML = '

Error: Interfaz no inicializada correctamente.

'; return; } console.log("[proa.js v12] Elementos DOM encontrados."); // ====================================================================== // BLOCK END: DOM Elements Selection & Initial Setup // ====================================================================== // ====================================================================== // BLOCK START: State Variables // ====================================================================== let allGuides = []; // Almacenará todas las guías del JSON let currentSelectedGuideData = null; // Guarda los datos completos de la guía seleccionada let currentGuideHTMLContent = null; // Cache para el HTML de la guía actual con diagnósticos // ====================================================================== // BLOCK END: State Variables // ====================================================================== // ====================================================================== // BLOCK START: Function to Fetch Guides Data (from JSON) // ====================================================================== async function loadGuidesData() { console.log(`[proa.js v12] Iniciando loadGuidesData desde: ${guidesDataUrl}`); guideSelector.innerHTML = ''; guideSelector.disabled = true; resetUI(); // Limpia todo try { console.log("[proa.js v12] Realizando fetch..."); const response = await fetch(guidesDataUrl); console.log(`[proa.js v12] Fetch completado. Status: ${response.status}`); if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guidesDataUrl}. Verifica que el archivo exista y sea accesible.`); console.log("[proa.js v12] Parseando JSON..."); const rawData = await response.json(); console.log("[proa.js v12] JSON parseado."); if (!Array.isArray(rawData)) throw new Error("El formato del JSON no es un array válido."); // Filtrar y validar guías allGuides = rawData.filter(g => g.id && g.title && g.file && typeof g.isPediatric === 'boolean'); console.log(`[proa.js v12] Guías válidas iniciales: ${allGuides.length}`); // Validar estructura de diagnóstico si existe allGuides = allGuides.map(g => { if (g.hasDiagnoses === true) { if (!Array.isArray(g.diagnoses) || g.diagnoses.some(d => !d.id || !d.title)) { console.warn(`[proa.js v12] Guía '${g.title}' marcada con 'hasDiagnoses' pero la estructura 'diagnoses' es inválida. Se tratará como guía normal.`); return { ...g, hasDiagnoses: false, diagnoses: undefined }; // Corregir datos inválidos } } return g; }); if (allGuides.length === 0) throw new Error("No se encontraron guías válidas en los datos después de la validación."); // Ordenar alfabéticamente para el desplegable principal allGuides.sort((a, b) => a.title.localeCompare(b.title)); console.log("[proa.js v12] Llamando a populateGuideSelector (mostrará Adultos por defecto)..."); populateGuideSelector(); // Poblar el desplegable principal guideSelector.disabled = false; // Habilitar selector principal console.log("[proa.js v12] Carga inicial de datos completada."); } catch (error) { console.error("[proa.js v12] Error durante loadGuidesData:", error); guideSelector.innerHTML = ``; guideSelector.disabled = true; guideContentDisplay.innerHTML = `

Error crítico al cargar datos: ${error.message}. Revisa la consola y el archivo '${guidesDataUrl}'.

`; } } // ====================================================================== // BLOCK END: Function to Fetch Guides Data (from JSON) // ====================================================================== // ====================================================================== // BLOCK START: UI Update Functions // ====================================================================== // Resetea el área de contenido y el selector de diagnóstico function resetUI(fullReset = true) { guideContentDisplay.innerHTML = '

Selecciona una guía del desplegable.

'; diagnosisSelector.innerHTML = ''; // Limpiar opciones diagnosisSelectorContainer.classList.add('hidden'); // Ocultar contenedor currentSelectedGuideData = null; currentGuideHTMLContent = null; // Limpiar cache de HTML if(fullReset && guideSelector.options.length > 1) { guideSelector.value = ""; // Resetear también el selector principal si no es el reset inicial } } // Llena el selector PRINCIPAL de guías aplicando el filtro Pediátrico/Adulto function populateGuideSelector() { const showOnlyPediatric = togglePediatricCheckbox.checked; console.log(`[proa.js v12] Poblando selector principal. Mostrar Pediátricas: ${showOnlyPediatric}`); // Filtrar por Adulto o Pediátrico const filteredGuides = allGuides.filter(guide => guide.isPediatric === showOnlyPediatric); // Ordenar alfabéticamente (ya deberían estar ordenadas, pero por si acaso) filteredGuides.sort((a, b) => a.title.localeCompare(b.title)); // Limpiar selector principal guideSelector.innerHTML = ``; if (filteredGuides.length > 0) { const fragment = document.createDocumentFragment(); filteredGuides.forEach(guide => { const option = document.createElement('option'); option.value = guide.id; // Usar el ID único de la guía como valor option.textContent = guide.isPediatric ? `${guide.title} (PED)` : guide.title; // Guardar datos importantes en el dataset para fácil acceso option.dataset.hasDiagnoses = guide.hasDiagnoses || false; option.dataset.file = guide.file; fragment.appendChild(option); }); guideSelector.appendChild(fragment); console.log(`[proa.js v12] Selector principal poblado con ${filteredGuides.length} guías.`); } else { guideSelector.innerHTML = ``; console.log(`[proa.js v12] No se encontraron guías para el filtro actual.`); } resetUI(false); // Resetear UI secundaria sin deseleccionar la guía principal } // Puebla el selector de DIAGNÓSTICOS function populateDiagnosisSelector(guideData) { console.log(`[proa.js v12] Poblando selector de diagnósticos para: ${guideData.title}`); diagnosisSelector.innerHTML = ''; // Limpiar if (guideData.hasDiagnoses && Array.isArray(guideData.diagnoses)) { const fragment = document.createDocumentFragment(); guideData.diagnoses.forEach(diagnosis => { const option = document.createElement('option'); option.value = diagnosis.id; // Usar el ID del diagnóstico como valor option.textContent = diagnosis.title; fragment.appendChild(option); }); diagnosisSelector.appendChild(fragment); diagnosisSelectorContainer.classList.remove('hidden'); // Mostrar contenedor console.log(`[proa.js v12] Selector de diagnósticos poblado con ${guideData.diagnoses.length} opciones.`); } else { console.warn("[proa.js v12] Se intentó poblar diagnósticos para una guía sin ellos o con datos inválidos."); diagnosisSelectorContainer.classList.add('hidden'); // Asegurarse que esté oculto } } // ====================================================================== // BLOCK END: UI Update Functions // ====================================================================== // ====================================================================== // BLOCK START: Content Loading Functions // ====================================================================== // Carga el CONTENIDO COMPLETO de una guía (para guías SIN diagnósticos) async function loadFullGuideContent(guideFile) { if (!guideFile) { resetUI(); return; } console.log(`[proa.js v12] Solicitando contenido COMPLETO de: ${guideFile}`); guideContentDisplay.innerHTML = '

Cargando guía completa...

'; currentGuideHTMLContent = null; // Limpiar cache try { const response = await fetch(guideFile); if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideFile}`); const htmlText = await response.text(); // Parsear y extraer contenido principal (mismo método que antes) const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, 'text/html'); // Intentar selector específico, si no, usar body const contentNode = doc.querySelector('.max-w-4xl.mx-auto.px-4.py-8') || doc.body; if (contentNode) { const clonedContent = contentNode.cloneNode(true); // Eliminar scripts del contenido clonado const scripts = clonedContent.querySelectorAll('script'); scripts.forEach(script => script.remove()); if (scripts.length > 0) console.log(`[proa.js v12] Eliminados ${scripts.length} script(s) de ${guideFile}.`); guideContentDisplay.innerHTML = ''; // Limpiar área guideContentDisplay.appendChild(clonedContent); // Añadir contenido limpio console.log(`[proa.js v12] Contenido COMPLETO de ${guideFile} mostrado.`); guideContentDisplay.scrollTop = 0; // Ir al inicio del contenido } else { throw new Error(`No se encontró nodo de contenido principal en '${guideFile}'.`); } } catch (error) { console.error(`[proa.js v12] Error al cargar/mostrar contenido COMPLETO de ${guideFile}:`, error); guideContentDisplay.innerHTML = `
Error al cargar contenido: ${error.message}
`; } } // Carga y cachea el HTML de una guía CON diagnósticos, luego muestra el diagnóstico especificado async function loadAndDisplayDiagnosisContent(guideData, diagnosisId) { console.log(`[proa.js v12] Solicitando diagnóstico '${diagnosisId}' de la guía '${guideData.title}' (${guideData.file})`); guideContentDisplay.innerHTML = '

Cargando diagnóstico...

'; try { // Si el HTML de la guía no está cacheado, cargarlo if (!currentGuideHTMLContent) { console.log(`[proa.js v12] HTML de ${guideData.file} no cacheado. Realizando fetch...`); const response = await fetch(guideData.file); if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideData.file}`); currentGuideHTMLContent = await response.text(); console.log(`[proa.js v12] HTML de ${guideData.file} cargado y cacheado.`); } else { console.log(`[proa.js v12] Usando HTML cacheado de ${guideData.file}.`); } // Parsear el HTML (cacheado o recién cargado) const parser = new DOMParser(); const doc = parser.parseFromString(currentGuideHTMLContent, 'text/html'); // Buscar el div específico del diagnóstico por su ID const diagnosisNode = doc.getElementById(diagnosisId); if (diagnosisNode) { console.log(`[proa.js v12] Nodo para diagnóstico ID '${diagnosisId}' encontrado.`); const clonedDiagnosisContent = diagnosisNode.cloneNode(true); // Opcional: Limpiar scripts si los hubiera dentro del div del diagnóstico (poco probable pero seguro) const scripts = clonedDiagnosisContent.querySelectorAll('script'); scripts.forEach(script => script.remove()); if (scripts.length > 0) console.log(`[proa.js v12] Eliminados ${scripts.length} script(s) del nodo de diagnóstico.`); guideContentDisplay.innerHTML = ''; // Limpiar área guideContentDisplay.appendChild(clonedDiagnosisContent); // Añadir contenido del diagnóstico console.log(`[proa.js v12] Contenido del diagnóstico '${diagnosisId}' mostrado.`); guideContentDisplay.scrollTop = 0; // Ir al inicio } else { throw new Error(`No se encontró el elemento con ID '${diagnosisId}' dentro de '${guideData.file}'. Verifica la estructura del HTML de la guía.`); } } catch (error) { console.error(`[proa.js v12] Error al cargar/mostrar diagnóstico '${diagnosisId}' de ${guideData.file}:`, error); guideContentDisplay.innerHTML = `
Error al cargar diagnóstico: ${error.message}
`; // Podríamos querer limpiar el cache si falla la carga // currentGuideHTMLContent = null; } } // ====================================================================== // BLOCK END: Content Loading Functions // ====================================================================== // ====================================================================== // BLOCK START: Event Listeners Setup // ====================================================================== // --- Listener para el selector PRINCIPAL de Guías --- guideSelector.addEventListener('change', (event) => { const selectedOption = event.target.selectedOptions[0]; const guideId = selectedOption.value; console.log(`[proa.js v12] Cambió la guía principal seleccionada. ID: ${guideId}`); // Limpiar UI secundaria y cache de contenido resetUI(false); // No resetea el selector principal if (!guideId) { // Si se seleccionó la opción placeholder "-- Seleccione Guía --" return; // No hacer nada más } // Encontrar los datos completos de la guía seleccionada currentSelectedGuideData = allGuides.find(g => g.id === guideId); if (!currentSelectedGuideData) { console.error(`[proa.js v12] No se encontraron datos para la guía con ID: ${guideId}`); guideContentDisplay.innerHTML = '

Error: Datos de guía no encontrados.

'; return; } // Decidir si mostrar selector de diagnóstico o cargar contenido completo if (currentSelectedGuideData.hasDiagnoses === true) { console.log(`[proa.js v12] La guía '${currentSelectedGuideData.title}' tiene diagnósticos. Poblando selector secundario.`); populateDiagnosisSelector(currentSelectedGuideData); // Mostrar un mensaje inicial diferente en el área de contenido guideContentDisplay.innerHTML = '

Selecciona un diagnóstico específico del desplegable superior.

'; } else { console.log(`[proa.js v12] La guía '${currentSelectedGuideData.title}' no tiene diagnósticos. Cargando contenido completo.`); diagnosisSelectorContainer.classList.add('hidden'); // Asegurarse que el selector de diagnóstico esté oculto loadFullGuideContent(currentSelectedGuideData.file); } }); // --- Listener para el selector SECUNDARIO de Diagnósticos --- diagnosisSelector.addEventListener('change', (event) => { const diagnosisId = event.target.value; console.log(`[proa.js v12] Cambió el diagnóstico seleccionado. ID: ${diagnosisId}`); if (!diagnosisId) { // Si se seleccionó "-- Seleccione Diagnóstico --" guideContentDisplay.innerHTML = '

Selecciona un diagnóstico específico del desplegable superior.

'; return; } if (currentSelectedGuideData && currentSelectedGuideData.hasDiagnoses) { loadAndDisplayDiagnosisContent(currentSelectedGuideData, diagnosisId); } else { console.error("[proa.js v12] Se intentó cargar un diagnóstico pero no hay guía con diagnósticos seleccionada."); guideContentDisplay.innerHTML = '

Error: Guía base no seleccionada correctamente.

'; } }); // --- Listener para el checkbox Pediátrico/Adulto --- togglePediatricCheckbox.addEventListener('change', () => { console.log('[proa.js v12] Cambiado filtro pediátrico.'); // Repoblar el selector principal y resetear completamente la UI populateGuideSelector(); // resetUI() ya se llama dentro de populateGuideSelector, así que no hace falta llamarlo de nuevo explícitamente aquí. }); console.log("[proa.js v12] Listeners añadidos."); // ====================================================================== // BLOCK END: Event Listeners Setup // ====================================================================== // ====================================================================== // BLOCK START: Initial Execution // ====================================================================== loadGuidesData(); // Cargar JSON e iniciar UI // ====================================================================== // BLOCK END: Initial Execution // ====================================================================== }); // Fin DOMContentLoaded console.log("[proa.js v12] Script completamente definido.");