|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log("[proa.js v14] Script cargado. Esperando DOMContentLoaded..."); |
|
|
window.addEventListener('DOMContentLoaded', () => { |
|
|
console.log("[proa.js v14] DOMContentLoaded detectado. Iniciando setup..."); |
|
|
|
|
|
|
|
|
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 = './data/guides_data.json'; |
|
|
|
|
|
|
|
|
if (!guideSelector || !diagnosisSelectorContainer || !diagnosisSelector || !guideContentDisplay || !togglePediatricCheckbox) { |
|
|
console.error("[proa.js v14] Error Crítico: No se encontraron elementos DOM esenciales."); |
|
|
guideContentDisplay.innerHTML = '<p class="text-red-500 font-semibold text-center py-10">Error: Interfaz no inicializada correctamente.</p>'; |
|
|
return; |
|
|
} |
|
|
console.log("[proa.js v14] Elementos DOM encontrados."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let allGuides = []; |
|
|
let currentSelectedGuideData = null; |
|
|
let currentGuideHTMLContent = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function loadGuidesData() { |
|
|
console.log(`[proa.js v14] Iniciando loadGuidesData desde: ${guidesDataUrl}`); |
|
|
guideSelector.innerHTML = '<option value="">Cargando...</option>'; |
|
|
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 = `<option value="">Error al cargar</option>`; |
|
|
guideSelector.disabled = true; |
|
|
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>`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function resetUI(fullReset = true) { |
|
|
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>'; |
|
|
diagnosisSelector.innerHTML = '<option value="">-- Seleccione Diagnóstico --</option>'; |
|
|
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 = `<option value="">-- Seleccione Guía (${showOnlyPediatric ? 'Pediátricas' : 'Adultos'}) --</option>`; |
|
|
|
|
|
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 = `<option value="">-- No hay guías ${showOnlyPediatric ? 'Pediátricas' : 'Adultos'} --</option>`; |
|
|
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 = '<option value="">-- Seleccione Diagnóstico --</option>'; |
|
|
|
|
|
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'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function loadFullGuideContent(guideFile) { |
|
|
if (!guideFile) { |
|
|
resetUI(); |
|
|
return; |
|
|
} |
|
|
|
|
|
const guideUrl = guideFile; |
|
|
console.log(`[proa.js v14] Solicitando contenido COMPLETO de: ${guideUrl}`); |
|
|
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>'; |
|
|
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'); |
|
|
|
|
|
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 { |
|
|
|
|
|
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 = `<div class="text-center py-20 text-red-600">Error al cargar contenido: ${error.message}</div>`; |
|
|
} |
|
|
} |
|
|
|
|
|
async function loadAndDisplayDiagnosisContent(guideData, diagnosisId) { |
|
|
|
|
|
const guideFileUrl = guideData.file; |
|
|
console.log(`[proa.js v14] Solicitando diagnóstico '${diagnosisId}' de la guía '${guideData.title}' (${guideFileUrl})`); |
|
|
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>'; |
|
|
|
|
|
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 = `<div class="text-center py-20 text-red-600">Error al cargar diagnóstico: ${error.message}</div>`; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = '<p class="text-red-500 text-center py-10">Error: Datos de guía no encontrados.</p>'; |
|
|
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 = '<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>'; |
|
|
} 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 = '<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>'; |
|
|
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 = '<p class="text-red-500 text-center py-10">Error: Guía base no seleccionada correctamente.</p>'; |
|
|
} |
|
|
}); |
|
|
|
|
|
togglePediatricCheckbox.addEventListener('change', () => { |
|
|
console.log('[proa.js v14] Cambiado filtro pediátrico.'); |
|
|
populateGuideSelector(); |
|
|
}); |
|
|
|
|
|
console.log("[proa.js v14] Listeners añadidos."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
loadGuidesData(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}); |
|
|
console.log("[proa.js v14] Script completamente definido."); |
|
|
|