// js/proa.js - Lógica para el visor de Guías PROA (v14 - Rutas corregidas) // ====================================================================== // BLOCK START: DOM Elements Selection & Initial Setup // ====================================================================== console.log("[proa.js v14] Script cargado. Esperando DOMContentLoaded..."); window.addEventListener('DOMContentLoaded', () => { console.log("[proa.js v14] 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'); // Ruta al JSON const guidesDataUrl = './data/guides_data.json'; // Mantenemos ./ aquí, ya que funciona // Verificar elementos críticos if (!guideSelector || !diagnosisSelectorContainer || !diagnosisSelector || !guideContentDisplay || !togglePediatricCheckbox) { console.error("[proa.js v14] Error Crítico: No se encontraron elementos DOM esenciales."); guideContentDisplay.innerHTML = '

Error: Interfaz no inicializada correctamente.

'; return; } console.log("[proa.js v14] Elementos DOM encontrados."); // ====================================================================== // BLOCK END: DOM Elements Selection & Initial Setup // ====================================================================== // ====================================================================== // BLOCK START: State Variables // ====================================================================== let allGuides = []; let currentSelectedGuideData = null; let currentGuideHTMLContent = null; // ====================================================================== // BLOCK END: State Variables // ====================================================================== // ====================================================================== // BLOCK START: Function to Fetch Guides Data (from JSON) // ====================================================================== async function loadGuidesData() { console.log(`[proa.js v14] Iniciando loadGuidesData desde: ${guidesDataUrl}`); guideSelector.innerHTML = ''; guideSelector.disabled = true; resetUI(); try { console.log("[proa.js v14] Realizando fetch..."); const response = await fetch(guidesDataUrl); console.log(`[proa.js v14] 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 v14] Parseando JSON..."); const rawData = await response.json(); console.log("[proa.js v14] JSON parseado."); if (!Array.isArray(rawData)) throw new Error("El formato del JSON no es un array válido."); allGuides = rawData.filter(g => g.id && g.title && g.file && typeof g.isPediatric === 'boolean'); console.log(`[proa.js v14] Guías válidas iniciales: ${allGuides.length}`); 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 v14] 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 }; } } 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."); allGuides.sort((a, b) => a.title.localeCompare(b.title)); console.log("[proa.js v14] Llamando a populateGuideSelector (mostrará Adultos por defecto)..."); populateGuideSelector(); guideSelector.disabled = false; console.log("[proa.js v14] Carga inicial de datos completada."); } catch (error) { console.error("[proa.js v14] 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 // ====================================================================== function resetUI(fullReset = true) { guideContentDisplay.innerHTML = '

Selecciona una guía del desplegable.

'; diagnosisSelector.innerHTML = ''; diagnosisSelectorContainer.classList.add('hidden'); currentSelectedGuideData = null; currentGuideHTMLContent = null; if(fullReset && guideSelector.options.length > 1) { guideSelector.value = ""; } } function populateGuideSelector() { const showOnlyPediatric = togglePediatricCheckbox.checked; console.log(`[proa.js v14] Poblando selector principal. Mostrar Pediátricas: ${showOnlyPediatric}`); const filteredGuides = allGuides.filter(guide => guide.isPediatric === showOnlyPediatric); filteredGuides.sort((a, b) => a.title.localeCompare(b.title)); guideSelector.innerHTML = ``; if (filteredGuides.length > 0) { const fragment = document.createDocumentFragment(); filteredGuides.forEach(guide => { const option = document.createElement('option'); option.value = guide.id; option.textContent = guide.isPediatric ? `${guide.title} (PED)` : guide.title; option.dataset.hasDiagnoses = guide.hasDiagnoses || false; option.dataset.file = guide.file; fragment.appendChild(option); }); guideSelector.appendChild(fragment); console.log(`[proa.js v14] Selector principal poblado con ${filteredGuides.length} guías.`); } else { guideSelector.innerHTML = ``; console.log(`[proa.js v14] No se encontraron guías para el filtro actual.`); } resetUI(false); } function populateDiagnosisSelector(guideData) { console.log(`[proa.js v14] Poblando selector de diagnósticos para: ${guideData.title}`); diagnosisSelector.innerHTML = ''; if (guideData.hasDiagnoses && Array.isArray(guideData.diagnoses)) { const fragment = document.createDocumentFragment(); guideData.diagnoses.forEach(diagnosis => { const option = document.createElement('option'); option.value = diagnosis.id; option.textContent = diagnosis.title; fragment.appendChild(option); }); diagnosisSelector.appendChild(fragment); diagnosisSelectorContainer.classList.remove('hidden'); console.log(`[proa.js v14] Selector de diagnósticos poblado con ${guideData.diagnoses.length} opciones.`); } else { console.warn("[proa.js v14] Se intentó poblar diagnósticos para una guía sin ellos o con datos inválidos."); diagnosisSelectorContainer.classList.add('hidden'); } } // ====================================================================== // BLOCK END: UI Update Functions // ====================================================================== // ====================================================================== // BLOCK START: Content Loading Functions // ====================================================================== async function loadFullGuideContent(guideFile) { if (!guideFile) { resetUI(); return; } // ! RUTA CORREGIDA: Sin ./ ! const guideUrl = guideFile; // Asume que la ruta en JSON (ej. "guias/archivo.html") es relativa a la raíz console.log(`[proa.js v14] Solicitando contenido COMPLETO de: ${guideUrl}`); guideContentDisplay.innerHTML = '

Cargando guía completa...

'; currentGuideHTMLContent = null; try { const response = await fetch(guideUrl); if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideUrl}`); const htmlText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, 'text/html'); // Intenta buscar el primer div con clase treatment-card como contenedor principal const contentNode = doc.querySelector('.treatment-card') || doc.body; if (contentNode) { const clonedContent = contentNode.cloneNode(true); const scripts = clonedContent.querySelectorAll('script'); scripts.forEach(script => script.remove()); if (scripts.length > 0) console.log(`[proa.js v14] Eliminados ${scripts.length} script(s) de ${guideUrl}.`); guideContentDisplay.innerHTML = ''; guideContentDisplay.appendChild(clonedContent); console.log(`[proa.js v14] Contenido COMPLETO de ${guideUrl} mostrado.`); guideContentDisplay.scrollTop = 0; } else { // Si no encuentra .treatment-card, intenta mostrar el body entero (menos scripts) const bodyNode = doc.body; if(bodyNode){ const clonedBody = bodyNode.cloneNode(true); const scripts = clonedBody.querySelectorAll('script'); scripts.forEach(script => script.remove()); guideContentDisplay.innerHTML = ''; guideContentDisplay.appendChild(clonedBody); console.warn(`[proa.js v14] No se encontró .treatment-card en '${guideUrl}'. Mostrando contenido del body.`); guideContentDisplay.scrollTop = 0; } else { throw new Error(`No se encontró nodo de contenido principal (ni .treatment-card ni body) en '${guideUrl}'.`); } } } catch (error) { console.error(`[proa.js v14] Error al cargar/mostrar contenido COMPLETO de ${guideUrl}:`, error); guideContentDisplay.innerHTML = `
Error al cargar contenido: ${error.message}
`; } } async function loadAndDisplayDiagnosisContent(guideData, diagnosisId) { // ! RUTA CORREGIDA: Sin ./ ! const guideFileUrl = guideData.file; // Asume que la ruta en JSON es relativa a la raíz console.log(`[proa.js v14] Solicitando diagnóstico '${diagnosisId}' de la guía '${guideData.title}' (${guideFileUrl})`); guideContentDisplay.innerHTML = '

Cargando diagnóstico...

'; try { if (!currentGuideHTMLContent) { console.log(`[proa.js v14] HTML de ${guideFileUrl} no cacheado. Realizando fetch...`); const response = await fetch(guideFileUrl); if (!response.ok) throw new Error(`Error HTTP ${response.status} al cargar ${guideFileUrl}`); currentGuideHTMLContent = await response.text(); console.log(`[proa.js v14] HTML de ${guideFileUrl} cargado y cacheado.`); } else { console.log(`[proa.js v14] Usando HTML cacheado de ${guideFileUrl}.`); } const parser = new DOMParser(); const doc = parser.parseFromString(currentGuideHTMLContent, 'text/html'); const diagnosisNode = doc.getElementById(diagnosisId); if (diagnosisNode) { console.log(`[proa.js v14] Nodo para diagnóstico ID '${diagnosisId}' encontrado.`); const clonedDiagnosisContent = diagnosisNode.cloneNode(true); const scripts = clonedDiagnosisContent.querySelectorAll('script'); scripts.forEach(script => script.remove()); if (scripts.length > 0) console.log(`[proa.js v14] Eliminados ${scripts.length} script(s) del nodo de diagnóstico.`); guideContentDisplay.innerHTML = ''; guideContentDisplay.appendChild(clonedDiagnosisContent); console.log(`[proa.js v14] Contenido del diagnóstico '${diagnosisId}' mostrado.`); guideContentDisplay.scrollTop = 0; } else { throw new Error(`No se encontró el elemento con ID '${diagnosisId}' dentro de '${guideFileUrl}'. Verifica la estructura del HTML de la guía.`); } } catch (error) { console.error(`[proa.js v14] Error al cargar/mostrar diagnóstico '${diagnosisId}' de ${guideFileUrl}:`, error); guideContentDisplay.innerHTML = `
Error al cargar diagnóstico: ${error.message}
`; } } // ====================================================================== // BLOCK END: Content Loading Functions // ====================================================================== // ====================================================================== // BLOCK START: Event Listeners Setup // ====================================================================== guideSelector.addEventListener('change', (event) => { const selectedOption = event.target.selectedOptions[0]; const guideId = selectedOption.value; console.log(`[proa.js v14] Cambió la guía principal seleccionada. ID: ${guideId}`); resetUI(false); if (!guideId) { return; } currentSelectedGuideData = allGuides.find(g => g.id === guideId); if (!currentSelectedGuideData) { console.error(`[proa.js v14] No se encontraron datos para la guía con ID: ${guideId}`); guideContentDisplay.innerHTML = '

Error: Datos de guía no encontrados.

'; return; } if (currentSelectedGuideData.hasDiagnoses === true) { console.log(`[proa.js v14] La guía '${currentSelectedGuideData.title}' tiene diagnósticos. Poblando selector secundario.`); populateDiagnosisSelector(currentSelectedGuideData); guideContentDisplay.innerHTML = '

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

'; } else { console.log(`[proa.js v14] La guía '${currentSelectedGuideData.title}' no tiene diagnósticos. Cargando contenido completo.`); diagnosisSelectorContainer.classList.add('hidden'); loadFullGuideContent(currentSelectedGuideData.file); } }); diagnosisSelector.addEventListener('change', (event) => { const diagnosisId = event.target.value; console.log(`[proa.js v14] Cambió el diagnóstico seleccionado. ID: ${diagnosisId}`); if (!diagnosisId) { guideContentDisplay.innerHTML = '

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

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

Error: Guía base no seleccionada correctamente.

'; } }); togglePediatricCheckbox.addEventListener('change', () => { console.log('[proa.js v14] Cambiado filtro pediátrico.'); populateGuideSelector(); }); console.log("[proa.js v14] Listeners añadidos."); // ====================================================================== // BLOCK END: Event Listeners Setup // ====================================================================== // ====================================================================== // BLOCK START: Initial Execution // ====================================================================== loadGuidesData(); // ====================================================================== // BLOCK END: Initial Execution // ====================================================================== }); // Fin DOMContentLoaded console.log("[proa.js v14] Script completamente definido.");