AppConsulta360 / js /main.js
aarnal80's picture
Update js/main.js
63226fc verified
// js/main.js
// --- INICIO: Importaciones ---
import { renderIaConfigForm, transcriptionProviders, getIaConfig } from './iaConfigModule.js';
import { initRecorder } from './recordingModule.js';
import { analyzeMedical } from './analysisModule.js';
import { copyText } from './clipboardModule.js';
import { analyzeLabResults, displayLabResults } from './labAnalysisModule.js';
// --- FIN: Importaciones ---
console.log("[Main] Script main.js cargado. Esperando DOMContentLoaded...");
window.addEventListener('DOMContentLoaded', () => {
console.log("[Main] Evento DOMContentLoaded detectado.");
// --- Variables y Estado ---
let lastLabResultText = '';
// --- Selecci贸n de Elementos DOM (con validaci贸n b谩sica) ---
console.log("[Main] Seleccionando elementos...");
const btnConfig = document.getElementById('btnConfig'); if (!btnConfig) console.error("!!! #btnConfig NO ENCONTRADO!");
const modal = document.getElementById('configModal'); if (!modal) console.error("!!! #configModal NO ENCONTRADO!");
const transcriptEl = document.getElementById('transcript'); if (!transcriptEl) console.error("!!! #transcript NO ENCONTRADO!");
const outputEnfermedadEl = document.getElementById('output-enfermedad'); if (!outputEnfermedadEl) console.error("!!! #output-enfermedad NO ENCONTRADO!");
const outputExploracionEl = document.getElementById('output-exploracion'); if (!outputExploracionEl) console.error("!!! #output-exploracion NO ENCONTRADO!");
const btnStart = document.getElementById('btnStart'); if (!btnStart) console.error("!!! #btnStart NO ENCONTRADO!");
const btnStop = document.getElementById('btnStop'); if (!btnStop) console.error("!!! #btnStop NO ENCONTRADO!");
const allTabButtons = document.querySelectorAll('.tab-button'); if (allTabButtons.length === 0) console.error("!!! No .tab-button encontrados!");
const allTabContents = document.querySelectorAll('.tab-content'); if (allTabContents.length === 0) console.error("!!! No .tab-content encontrados!");
const labInputText = document.getElementById('lab-input-text'); if (!labInputText) console.error("!!! #lab-input-text NO ENCONTRADO!");
const btnAnalyzeLabs = document.getElementById('btnAnalyzeLabs'); if (!btnAnalyzeLabs) console.error("!!! #btnAnalyzeLabs NO ENCONTRADO!");
const labLoadingIndicator = document.getElementById('lab-loading-indicator'); if (!labLoadingIndicator) console.error("!!! #lab-loading-indicator NO ENCONTRADO!");
const filterAlteredLabsCheckbox = document.getElementById('filterAlteredLabs'); if (!filterAlteredLabsCheckbox) console.error("!!! #filterAlteredLabs NO ENCONTRADO!");
const labResultsOutput = document.getElementById('lab-results-output'); if (!labResultsOutput) console.error("!!! #lab-results-output NO ENCONTRADO!");
const btnCopyTranscript = document.getElementById('btnCopyTranscript'); if (!btnCopyTranscript) console.error("!!! #btnCopyTranscript NO ENCONTRADO!");
const btnCopyAnalysis = document.getElementById('btnCopyAnalysis'); if (!btnCopyAnalysis) console.error("!!! #btnCopyAnalysis NO ENCONTRADO!");
const btnCopyLabResults = document.getElementById('btnCopyLabResults'); if (!btnCopyLabResults) console.error("!!! #btnCopyLabResults NO ENCONTRADO!");
console.log("[Main] Selecci贸n elementos finalizada.");
// --- Funci贸n updateModelLabels (DENTRO de DOMContentLoaded) ---
function updateModelLabels() {
console.log("[Main] Ejecutando updateModelLabels...");
// (C贸digo interno de la funci贸n sin cambios)
try{ const cfg=getIaConfig(); const tP=cfg?.transcription?.provider; const tM=cfg?.transcription?.models?.[tP]||'N/A'; const lP=cfg?.llm?.provider; const lM=cfg?.llm?.model||'N/A'; const tL=document.getElementById('trans-model-label'); if(tL)tL.textContent=tM?`(${tM})`:''; const aL=document.getElementById('analysis-model-label'); if(aL)aL.textContent=lM?`(${lM})`:''; const labL=document.getElementById('lab-model-label'); if(labL)labL.textContent=lM?`(${lM})`:''; } catch(e){console.error("Error en updateModelLabels:",e)}
}
// --- Funci贸n para Limpiar Campos de UI ---
function clearUIFields() {
console.log('[Main] Ejecutando clearUIFields...');
if (transcriptEl) transcriptEl.value = 'Aqu铆 aparecer谩 la transcripci贸n...'; // Valor inicial o ''
if (outputEnfermedadEl) outputEnfermedadEl.textContent = '';
if (outputExploracionEl) outputExploracionEl.textContent = '';
// Tambi茅n limpiamos los campos de la pesta帽a de Laboratorio por consistencia
if (labInputText) labInputText.value = '';
if (labResultsOutput) labResultsOutput.innerHTML = '';
lastLabResultText = ''; // Reiniciar variable de estado
console.log('[Main] Campos de UI limpiados.');
}
// --- Configuraci贸n Inicial y Listeners ---
try {
updateModelLabels(); // Llamada inicial
document.addEventListener('iaConfigChanged', updateModelLabels);
renderIaConfigForm('iaConfigContainer');
if(btnConfig) { btnConfig.addEventListener('click', () => { renderIaConfigForm('iaConfigContainer'); if (modal) modal.classList.add('active'); }); }
if(modal) { modal.addEventListener('mousedown', e => { if (e.target === modal) modal.classList.remove('active'); }); }
} catch(e) { console.error("Error en setup inicial (config/labels):", e); }
// --- Listener AN脕LISIS M脡DICO ---
try {
document.addEventListener('transcriptionReady', async (e) => {
console.log("[Main] Evento 'transcriptionReady' recibido.");
const transcriptText = e.detail; if (!transcriptText) return;
// Mostrar 'Analizando...' solo si los elementos existen
if(outputEnfermedadEl) outputEnfermedadEl.textContent='Analizando...';
if(outputExploracionEl) outputExploracionEl.textContent=''; // Limpiar el segundo campo
try {
const result = await analyzeMedical(transcriptText);
console.log("[Main] An谩lisis m茅dico completado.");
const sections = result.split(/\n\s*\n/);
// Actualizar elementos solo si existen
if(outputEnfermedadEl) outputEnfermedadEl.textContent = sections[0]?.trim() || '(No generado)';
if(outputExploracionEl) outputExploracionEl.textContent = sections.slice(1).join('\n\n').trim() || '(No generado)';
}
catch (err) {
console.error("Error en analyzeMedical:", err);
if(outputEnfermedadEl) outputEnfermedadEl.textContent = `Error an谩lisis: ${err.message}`;
if(outputExploracionEl) outputExploracionEl.textContent = ''; // Limpiar si hubo error
alert(`Error an谩lisis m茅dico: ${err.message}`);
}
});
console.log("[Main] Listener 'transcriptionReady' a帽adido.");
} catch(e) { console.error("Error a帽adiendo listener 'transcriptionReady':", e); }
// --- Inicializar Grabadora ---
try {
// La funci贸n getTranscriptionProviderUrl est谩 definida dentro de este try-catch
function getTranscriptionProviderUrl() {
console.log("[Main] Ejecutando getTranscriptionProviderUrl...");
const cfg = getIaConfig();
const providerValue = cfg?.transcription?.provider;
if (providerValue) {
const prov = transcriptionProviders.find(p => p.value === providerValue);
if (prov?.url) {
console.log(`[Main] URL encontrada para ${providerValue}: ${prov.url}`);
return prov.url;
} else {
console.warn(`[Main] URL no encontrada para el proveedor '${providerValue}'.`);
}
} else {
console.warn('[Main] No se encontr贸 providerValue en cfg.transcription.provider.');
}
console.error('[Main] Fallo al obtener URL del proveedor. Retornando vac铆o.');
return '';
}
if (btnStart && btnStop && transcriptEl && typeof initRecorder === 'function') {
// Pasamos la funci贸n clearUIFields como callback
initRecorder({
btnStart,
btnStop,
transcriptEl,
getProvider: getTranscriptionProviderUrl,
clearFieldsCallback: clearUIFields
});
} else {
console.error("Faltan elementos/funci贸n para initRecorder");
}
} catch(e) { console.error("Error inicializando Recorder:", e); }
// --- Botones Copiar (An谩lisis M茅dico) --- (MODIFICADO CON FEEDBACK)
try {
// Bot贸n Copiar Transcripci贸n
if (btnCopyTranscript && transcriptEl) {
btnCopyTranscript.addEventListener('click', async () => {
const textToCopy = transcriptEl.value;
if (textToCopy && textToCopy !== 'Aqu铆 aparecer谩 la transcripci贸n...') {
try {
await copyText(textToCopy);
// --- INICIO: L贸gica de Feedback Visual ---
const buttonElement = btnCopyTranscript;
const originalHtml = buttonElement.innerHTML;
buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
buttonElement.disabled = true;
setTimeout(() => {
// Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
if (document.body.contains(buttonElement) && buttonElement.disabled) {
buttonElement.innerHTML = originalHtml;
buttonElement.disabled = false;
}
}, 2000);
// --- FIN: L贸gica de Feedback Visual ---
} catch (err) {
console.error('Error copia transcripci贸n:', err);
alert('Error al copiar transcripci贸n.');
// Asegurarse de rehabilitar el bot贸n si falla la copia
if (document.body.contains(btnCopyTranscript)) {
btnCopyTranscript.disabled = false;
}
}
} else {
alert('No hay transcripci贸n v谩lida para copiar.');
}
});
} else {
console.error("Faltan elementos para bot贸n Copiar Transcripci贸n.");
}
// Bot贸n Copiar An谩lisis M茅dico (Enfermedad + Exploraci贸n)
if (btnCopyAnalysis && outputEnfermedadEl && outputExploracionEl) {
btnCopyAnalysis.addEventListener('click', async () => {
const textToCopy = `${outputEnfermedadEl.textContent || ''}\n\n${outputExploracionEl.textContent || ''}`.trim();
// Validar que no est茅 vac铆o y no contenga mensajes de error o "no generado"
if (textToCopy && !textToCopy.toLowerCase().includes('error') && !textToCopy.toLowerCase().includes('(no generado)')) {
try {
await copyText(textToCopy);
// --- INICIO: L贸gica de Feedback Visual ---
const buttonElement = btnCopyAnalysis;
const originalHtml = buttonElement.innerHTML;
buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
buttonElement.disabled = true;
setTimeout(() => {
// Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
if (document.body.contains(buttonElement) && buttonElement.disabled) {
buttonElement.innerHTML = originalHtml;
buttonElement.disabled = false;
}
}, 2000);
// --- FIN: L贸gica de Feedback Visual ---
} catch (err) {
console.error('Error copia an谩lisis:', err);
alert('Error al copiar an谩lisis.');
// Asegurarse de rehabilitar el bot贸n si falla la copia
if (document.body.contains(btnCopyAnalysis)) {
btnCopyAnalysis.disabled = false;
}
}
} else {
alert('No hay an谩lisis v谩lido para copiar.');
}
});
} else {
console.error("Faltan elementos para bot贸n Copiar An谩lisis.");
}
} catch(e) {
console.error("Error a帽adiendo listeners botones Copiar (M茅dico):", e);
}
// --- Cambio de Pesta帽as ---
try {
function switchTab(clickedTab) {
const targetContentId = clickedTab.dataset.contentId;
const targetContentElement = document.getElementById(targetContentId);
if(targetContentElement && !targetContentElement.classList.contains('active')){
// Desactivar todos los botones y contenidos
allTabButtons.forEach(button => {
const activeClasses = button.dataset.activeClasses.split(' ').filter(c => c);
const inactiveClasses = button.dataset.inactiveClasses.split(' ').filter(c => c);
button.classList.remove(...activeClasses);
button.classList.add(...inactiveClasses);
});
allTabContents.forEach(content => {
content.classList.remove('active');
});
// Activar el bot贸n y contenido clickeado
const activeClassesToAdd = clickedTab.dataset.activeClasses.split(' ').filter(c => c);
const inactiveClassesToRemove = clickedTab.dataset.inactiveClasses.split(' ').filter(c => c);
clickedTab.classList.remove(...inactiveClassesToRemove);
clickedTab.classList.add(...activeClassesToAdd);
targetContentElement.classList.add('active');
console.log(`Pesta帽a activada: ${targetContentId}`);
}
}
if(allTabButtons.length > 0){
allTabButtons.forEach(button => {
button.addEventListener('click', (e) => {
switchTab(e.currentTarget);
});
});
// Activar la primera pesta帽a por defecto si ninguna est谩 activa
const initiallyActive = document.querySelector('.tab-button.bg-indigo-600'); // Busca la clase activa inicial del HTML
if (initiallyActive && !document.querySelector('.tab-content.active')) {
switchTab(initiallyActive);
} else if (!document.querySelector('.tab-content.active') && allTabButtons.length > 0) {
switchTab(allTabButtons[0]); // Activa la primera si no hay ninguna activa por defecto
}
} else {
console.error("No se pueden a帽adir listeners a los botones de pesta帽a.");
}
} catch(e) { console.error("Error en setup Cambio de Pesta帽as:", e); }
// --- ELIMINADO: Bloque del listener 'newRecordingStarted' ---
// --- L贸gica Pesta帽a Laboratorio ---
try {
// Listener Analizar Laboratorio
if (btnAnalyzeLabs && labInputText && labLoadingIndicator && filterAlteredLabsCheckbox && labResultsOutput) {
btnAnalyzeLabs.addEventListener('click', async () => {
console.log("[Main] Click en btnAnalyzeLabs.");
const inputText = labInputText.value;
if (!inputText.trim()) {
alert("Por favor, pega los resultados del laboratorio en el 谩rea de texto.");
return;
}
labLoadingIndicator.style.display = 'flex';
btnAnalyzeLabs.disabled = true;
filterAlteredLabsCheckbox.disabled = true;
labResultsOutput.innerHTML = ''; // Limpiar resultados anteriores
lastLabResultText = '';
try {
const resultText = await analyzeLabResults(inputText);
console.log("RAW AI RESPONSE:", resultText);
lastLabResultText = resultText; // Guardar el resultado crudo
const filterIsActive = filterAlteredLabsCheckbox.checked;
displayLabResults(resultText, labResultsOutput, filterIsActive); // Mostrar resultados
// Llamada a updateModelLabels
console.log("[Main] Intentando llamar a updateModelLabels desde listener btnAnalyzeLabs...");
updateModelLabels();
console.log("[Main] Llamada a updateModelLabels desde listener btnAnalyzeLabs completada.");
} catch (error) {
console.error("Error DENTRO listener btnAnalyzeLabs:", error);
if(labResultsOutput) labResultsOutput.innerHTML = `<p class="text-red-600 font-semibold">Error al procesar: ${error.message}</p>`;
alert(`Error al analizar resultados: ${error.message}`);
} finally {
labLoadingIndicator.style.display = 'none';
btnAnalyzeLabs.disabled = false;
filterAlteredLabsCheckbox.disabled = false;
}
});
// Listener Checkbox Filtro
filterAlteredLabsCheckbox.addEventListener('change', () => {
if (!lastLabResultText || !labResultsOutput) return;
const filterIsActive = filterAlteredLabsCheckbox.checked;
displayLabResults(lastLabResultText, labResultsOutput, filterIsActive);
});
} else {
console.error("Faltan elementos esenciales para la Pesta帽a de An谩lisis de Ex谩menes.");
}
// Listener Copiar Laboratorio (con feedback)
if (btnCopyLabResults && labResultsOutput) {
btnCopyLabResults.addEventListener('click', async () => {
const currentOutputText = labResultsOutput.textContent?.trim();
if(!currentOutputText || currentOutputText.startsWith('Error')) {
alert('No hay resultados v谩lidos para copiar.');
return;
}
try {
await copyText(currentOutputText);
// --- INICIO: L贸gica de Feedback Visual ---
const buttonElement = btnCopyLabResults;
const originalHtml = buttonElement.innerHTML;
buttonElement.innerHTML = '<i class="fas fa-check mr-2"></i>Copiado!';
buttonElement.disabled = true;
setTimeout(() => {
// Solo restaurar si el bot贸n sigue existiendo y est谩 deshabilitado
if (document.body.contains(buttonElement) && buttonElement.disabled) {
buttonElement.innerHTML = originalHtml;
buttonElement.disabled = false;
}
}, 2000);
// --- FIN: L贸gica de Feedback Visual ---
} catch(e){
console.error("Error al copiar resultados de laboratorio:", e);
alert("Error al intentar copiar los resultados.");
// Asegurarse de rehabilitar el bot贸n si falla la copia
if (document.body.contains(btnCopyLabResults)) {
btnCopyLabResults.disabled = false;
}
}
});
} else {
console.error("Faltan elementos para el bot贸n Copiar Resultados de Laboratorio.");
}
} catch(e) {
console.error("Error general en el setup de la Pesta帽a de An谩lisis de Ex谩menes:", e);
}
console.log("[Main] Configuraci贸n de listeners y UI inicial finalizada.");
}); // Fin de window.addEventListener('DOMContentLoaded', ...)