From 8c4f103f82c8560a8ac5902db84dcc5bca8c5f8d Mon Sep 17 00:00:00 2001 From: Sergio Nicolas Lavaise Date: Wed, 15 Apr 2026 20:15:16 -0300 Subject: [PATCH] Agregar modal para importar laboratorios con parser de texto --- src/sections/HistoriaClinica.tsx | 189 ++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 1 deletion(-) diff --git a/src/sections/HistoriaClinica.tsx b/src/sections/HistoriaClinica.tsx index 90af0e5..3b3c52f 100644 --- a/src/sections/HistoriaClinica.tsx +++ b/src/sections/HistoriaClinica.tsx @@ -565,6 +565,11 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { const [kptt, setKptt] = useState(''); const [rin, setRin] = useState(''); const [parametroEvolucion, setParametroEvolucion] = useState(''); + const [importDialog, setImportDialog] = useState(false); + const [importFecha, setImportFecha] = useState(new Date().toISOString().split('T')[0]); + const [importTexto, setImportTexto] = useState(''); + const [importResultados, setImportResultados] = useState([]); + const [importObservaciones, setImportObservaciones] = useState(''); const parametrosLaboratorio = [ 'Hematocrito', 'Hemoglobina', 'Leucocitos', 'Plaquetas', @@ -629,7 +634,7 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { if (tp) res.push({ parametro: 'Tiempo de Protrombina', valor: tp, unidad: 'seg', estado: calcularEstadoLaboratorio('Tiempo de Protrombina', tp) }); if (kptt) res.push({ parametro: 'KPTT', valor: kptt, unidad: 'seg', estado: calcularEstadoLaboratorio('KPTT', kptt) }); if (rin) res.push({ parametro: 'INR', valor: rin, unidad: '', estado: calcularEstadoLaboratorio('INR', rin) }); - return res; +return res; }; const reset = () => { @@ -643,6 +648,114 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { setEdit(null); }; + const parseLaboratorioTexto = (texto: string): { resultados: ResultadoLaboratorio[]; observaciones: string } => { + const resultados: ResultadoLaboratorio[] = []; + const observacionesExtra: string[] = []; + + const mapeoParametros: Record = { + 'hematíes': { nombre: 'Hematíes', unidad: '10⁶/µl', esPrincipal: false }, + 'hematocrito': { nombre: 'Hematocrito', unidad: '%', esPrincipal: true }, + 'hemoglobina corpuscular media': { nombre: 'HCM', unidad: 'pg', esPrincipal: false }, + 'concentración de hemoglobina media': { nombre: 'CHCM', unidad: 'g/dL', esPrincipal: false }, + 'hemoglobina': { nombre: 'Hemoglobina', unidad: 'g/dL', esPrincipal: true }, + 'volumen corpuscular medio': { nombre: 'VCM', unidad: 'fL', esPrincipal: false }, + 'rdw': { nombre: 'RDW', unidad: '%', esPrincipal: false }, + 'eritroblastos': { nombre: 'Eritroblastos', unidad: '%', esPrincipal: false }, + 'neutrófilos': { nombre: 'Neutrófilos', unidad: '%', esPrincipal: false }, + 'linfocitos': { nombre: 'Linfocitos', unidad: '%', esPrincipal: false }, + 'monocitos': { nombre: 'Monocitos', unidad: '%', esPrincipal: false }, + 'eosinófilos': { nombre: 'Eosinófilos', unidad: '%', esPrincipal: false }, + 'basófilos': { nombre: 'Basófilos', unidad: '%', esPrincipal: false }, + 'leucocitos': { nombre: 'Leucocitos', unidad: '10³/µl', esPrincipal: true }, + 'recuento de leucocitos': { nombre: 'Leucocitos', unidad: '10³/µl', esPrincipal: true }, + 'recuento de plaquetas': { nombre: 'Plaquetas', unidad: '10³/µl', esPrincipal: true }, + 'plaquetas': { nombre: 'Plaquetas', unidad: '10³/µl', esPrincipal: true }, + 'volumen plaquetario medio': { nombre: 'VPM', unidad: 'fL', esPrincipal: false }, + 'procalcitonina': { nombre: 'Procalcitonina', unidad: 'ng/mL', esPrincipal: false }, + 'glucosa': { nombre: 'Glucemia', unidad: 'mg/dL', esPrincipal: true }, + 'urea': { nombre: 'Urea', unidad: 'mg/dL', esPrincipal: true }, + 'creatinina': { nombre: 'Creatinina', unidad: 'mg/dL', esPrincipal: true }, + 'mdrd': { nombre: 'Filtrado Glomerular (MDRD)', unidad: 'ml/min', esPrincipal: false }, + 'sodio': { nombre: 'Sodio', unidad: 'mEq/L', esPrincipal: true }, + 'potasio': { nombre: 'Potasio', unidad: 'mEq/L', esPrincipal: true }, + 'cloro': { nombre: 'Cloro', unidad: 'mEq/L', esPrincipal: true }, + 'bilirrubina total': { nombre: 'Bilirrubina Total', unidad: 'mg/dL', esPrincipal: true }, + 'bilirrubina directa': { nombre: 'Bilirrubina Directa', unidad: 'mg/dL', esPrincipal: true }, + 'got': { nombre: 'GOT', unidad: 'U/L', esPrincipal: true }, + 'gpt': { nombre: 'GPT', unidad: 'U/L', esPrincipal: true }, + 'fosfatasa alcalina': { nombre: 'Fosfatasa Alcalina', unidad: 'U/L', esPrincipal: false }, + 'proteínas totales': { nombre: 'Proteínas Totales', unidad: 'g/dL', esPrincipal: false }, + 'albúmina': { nombre: 'Albúmina', unidad: 'g/dL', esPrincipal: false }, + 'tiempo de protrombina': { nombre: 'Tiempo de Protrombina', unidad: '%', esPrincipal: true }, + 'rin': { nombre: 'INR', unidad: '', esPrincipal: true }, + 'aptt': { nombre: 'KPTT', unidad: 'seg', esPrincipal: true }, + 'kptt': { nombre: 'KPTT', unidad: 'seg', esPrincipal: true }, + }; + + const lineas = texto.split('\n'); + + for (const linea of lineas) { + const lineaLower = linea.toLowerCase().trim(); + + for (const [clave, info] of Object.entries(mapeoParametros)) { + if (lineaLower.includes(clave)) { + const cleanLinea = linea.replace(/show_chart|list_alt/g, '').trim(); + const partes = cleanLinea.split(/\s+/); + + for (let i = 0; i < partes.length; i++) { + const parte = partes[i].replace(',', '.'); + const valor = parseFloat(parte); + if (!isNaN(valor) && valor > 0 && valor < 1000) { + const esUnidadSiguiente = partes[i + 1] && /^(10[\^*]?[³6]?[\/]?µl|%|g\/dl|mg\/dl|mEq\/L|u\/l|fL|pg|seg|ng\/ml)?$/i.test(partes[i + 1]); + + if (!esUnidadSiguiente) { + const nombreNormalizado = info.nombre === 'Plajetas' ? 'Plaquetas' : info.nombre; + + if (info.esPrincipal) { + resultados.push({ + parametro: nombreNormalizado, + valor: valor, + unidad: info.unidad, + estado: calcularEstadoLaboratorio(nombreNormalizado, parte) + }); + } else if (!['Eritroblastos', 'Neutrófilos', 'Linfocitos', 'Monocitos', 'Eosinófilos', 'Basófilos'].includes(info.nombre)) { + observacionesExtra.push(`${info.nombre}: ${valor} ${info.unidad}`.trim()); + } + break; + } + } + } + break; + } + } + } + + return { resultados, observaciones: observacionesExtra.join('\n') }; + }; + + const handleProcesarTexto = () => { + const { resultados, observaciones } = parseLaboratorioTexto(importTexto); + setImportResultados(resultados); + setImportObservaciones(observaciones); + }; + + const handleImportarLaboratorio = () => { + if (importResultados.length === 0 && !importObservaciones) return; + + add({ + pacienteId: patientId, + fecha: importFecha, + resultados: importResultados, + observaciones: importObservaciones + }); + + setImportDialog(false); + setImportTexto(''); + setImportResultados([]); + setImportObservaciones(''); + setImportFecha(new Date().toISOString().split('T')[0]); + }; + const loadEdit = (l: Laboratorio) => { setEdit(l); setFecha(l.fecha); @@ -686,6 +799,7 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: {
+
@@ -819,6 +933,79 @@ function SeccionLaboratorios({ lab, patientId, add, update, del }: { + + + + + + Importar Laboratorio + + +
+
+ + setImportFecha(e.target.value)} /> +
+
+ +