import { useState } from 'react'; import { createPortal } from 'react-dom'; import { toast } from 'sonner'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { Plus, Pencil, Trash2, X } from 'lucide-react'; import type { Indicacion, IndicacionTipo, ViaAdministracion, TipoPlanHidratacion, TipoInsulina, ATB } from '@/types'; import { useHospitalStore } from '@/hooks/useHospitalStore'; import { getNombreProfesional, getLocalToday } from '@/lib/utils'; export function SeccionIndicaciones({ recomendaciones, internacionId, pacienteId, add, update, del, movimientos, onAgregarMovimiento, canEdit, atbList = [], addATB, updateATB, portalNode}: { recomendaciones: Indicacion[]; internacionId: string; pacienteId?: string; add: (i: Omit) => Promise; update: (id: string, datos: Partial) => void; del: (id: string) => void; movimientos?: unknown[]; onAgregarMovimiento?: (m: unknown) => void; canEdit?: boolean; portalNode?: HTMLDivElement | null; atbList?: ATB[]; addATB?: (a: Omit) => Promise; updateATB?: (id: string, datos: Partial) => void; }) { const { currentUser } = useHospitalStore(); const list: Indicacion[] = Array.isArray(recomendaciones) ? recomendaciones : []; const movs = Array.isArray(movimientos) ? movimientos : []; const [dialog, setDialog] = useState(false); const [edit, setEdit] = useState(null); const [deleteConfirmInd, setDeleteConfirmInd] = useState(null); const effectiveDeleteMedico = getNombreProfesional(currentUser); const formatIndicacion = (i: Indicacion): string => { if (i.tipo === 'Farmacologica' || i.tipo === 'Farmacologica Profilactica' || i.tipo === 'Farmacologica Antibiótico') return `${i.droga || ''} ${i.dosis || ''} ${i.frecuenciaHoras ? `c/${i.frecuenciaHoras}hs` : ''} ${i.via || ''}`.trim(); if (i.tipo === 'Farmacologica Insulina') return `${i.tipoInsulina || ''}${i.unidadesDesayuno ? ` - PreDesayuno: ${i.unidadesDesayuno}U` : ''}${i.unidadesAlmuerzo ? ` - PreAlmuerzo: ${i.unidadesAlmuerzo}U` : ''}${i.unidadesNoche ? ` - 23hs: ${i.unidadesNoche}U` : ''}`.trim(); if (i.tipo === 'No Farmacologica') return i.indicacionNoFco || ''; if (i.tipo === 'PHP' || i.tipo === 'PHP Paralelo') return `${i.tipoPlan || ''} ${i.cantidadMl || ''}ml en ${i.tiempoHoras || ''}hs`; if (i.tipo === 'PHP Alterno') return `${i.tipoPlan || ''} ${i.cantidadMl || ''}ml + ${i.tipoPlan2 || ''} ${i.cantidadMl2 || ''}ml en ${i.tiempoHoras || ''}hs`; return ''; }; const [tipo, setTipo] = useState('Farmacologica'); const [sortField, setSortField] = useState<'fecha' | 'profesional' | 'tipo'>('fecha'); const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc'); const handleSort = (field: 'fecha' | 'profesional' | 'tipo') => { if (sortField === field) { setSortDir(sortDir === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortDir('desc'); } }; const sortedMovs = [...movs].sort((a, b) => { const recordA = a as Record; const recordB = b as Record; const aVal = String(recordA[sortField] || ''); const bVal = String(recordB[sortField] || ''); if (sortField === 'fecha') { const timeA = new Date(aVal.replace(' ', 'T')).getTime(); const timeB = new Date(bVal.replace(' ', 'T')).getTime(); return sortDir === 'asc' ? timeA - timeB : timeB - timeA; } return sortDir === 'asc' ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal); }); const [droga, setDroga] = useState(''); const [dosis, setDosis] = useState(''); const [frecuenciaHoras, setFrecuenciaHoras] = useState(''); const [via, setVia] = useState('EV'); const [indicacionNoFco, setIndicacionNoFco] = useState(''); const [tipoPlan, setTipoPlan] = useState('SF 0.9%'); const [tipoPlan2, setTipoPlan2] = useState('Ringer Lactato'); const [cantidadMl, setCantidadMl] = useState(''); const [cantidadMl2, setCantidadMl2] = useState(''); const [tiempoHoras, setTiempoHoras] = useState(24); const [tipoInsulina, setTipoInsulina] = useState('NPH'); const [unidadesDesayuno, setUnidadesDesayuno] = useState(''); const [unidadesAlmuerzo, setUnidadesAlmuerzo] = useState(''); const [unidadesNoche, setUnidadesNoche] = useState(''); const effectiveMedico = getNombreProfesional(currentUser); const [showHistorial, setShowHistorial] = useState(false); const vias: ViaAdministracion[] = ['Via Oral', 'EV', 'IM', 'SC', 'Por GGT', 'Por SNG']; const planes: TipoPlanHidratacion[] = ['SF 0.9%', 'Dextrosa 5%', 'Dextrosa 10%', 'Dextrosa 25%', 'Ringer Lactato']; const tiposInsulina: TipoInsulina[] = ['NPH', 'Glargina']; const tipos: IndicacionTipo[] = ['Farmacologica', 'Farmacologica Antibiótico', 'Farmacologica Profilactica', 'Farmacologica Insulina', 'No Farmacologica', 'PHP', 'PHP Paralelo', 'PHP Alterno']; const reset = () => { setEdit(null); setTipo('Farmacologica'); setDroga(''); setDosis(''); setFrecuenciaHoras(''); setVia('EV'); setIndicacionNoFco(''); setTipoPlan('SF 0.9%'); setTipoPlan2('Ringer Lactato'); setCantidadMl(''); setCantidadMl2(''); setTiempoHoras(24); setTipoInsulina('NPH'); setUnidadesDesayuno(''); setUnidadesAlmuerzo(''); setUnidadesNoche(''); }; const loadEdit = (i: Indicacion) => { setEdit(i); setTipo(i.tipo); setDroga(i.droga || ''); setDosis(i.dosis || ''); setFrecuenciaHoras(i.frecuenciaHoras || ''); setVia(i.via || 'EV'); setIndicacionNoFco(i.indicacionNoFco || ''); setTipoPlan(i.tipoPlan || 'SF 0.9%'); setTipoPlan2(i.tipoPlan2 || 'Ringer Lactato'); setCantidadMl(i.cantidadMl || ''); setCantidadMl2(i.cantidadMl2 || ''); setTiempoHoras(i.tiempoHoras || 24); setTipoInsulina(i.tipoInsulina || 'NPH'); setUnidadesDesayuno(i.unidadesDesayuno || ''); setUnidadesAlmuerzo(i.unidadesAlmuerzo || ''); setUnidadesNoche(i.unidadesNoche || ''); setDialog(true); }; const handleGuardar = async () => { if (!effectiveMedico.trim()) return; if ((tipo === 'Farmacologica' || tipo === 'Farmacologica Profilactica' || tipo === 'Farmacologica Antibiótico') && (!droga.trim() || !dosis.trim())) return; if (tipo === 'Farmacologica Insulina' && (!unidadesDesayuno && !unidadesAlmuerzo && !unidadesNoche)) return; if (tipo === 'No Farmacologica' && !indicacionNoFco.trim()) return; if ((tipo === 'PHP' || tipo === 'PHP Paralelo') && !cantidadMl) return; if (tipo === 'PHP Alterno' && (!cantidadMl || !cantidadMl2)) return; const data: Partial = { internacionId, tipo, estado: 'Activa', medicoCrea: effectiveMedico, fechaCrea: getLocalToday(), }; if (tipo === 'Farmacologica' || tipo === 'Farmacologica Profilactica' || tipo === 'Farmacologica Antibiótico') { data.droga = droga; data.dosis = dosis; data.frecuenciaHoras = frecuenciaHoras || undefined; data.via = via; } else if (tipo === 'Farmacologica Insulina') { data.tipoInsulina = tipoInsulina; data.unidadesDesayuno = unidadesDesayuno || undefined; data.unidadesAlmuerzo = unidadesAlmuerzo || undefined; data.unidadesNoche = unidadesNoche || undefined; } else if (tipo === 'No Farmacologica') { data.indicacionNoFco = indicacionNoFco; } else if (tipo === 'PHP' || tipo === 'PHP Paralelo') { data.tipoPlan = tipoPlan; data.cantidadMl = cantidadMl; data.tiempoHoras = tiempoHoras; } else if (tipo === 'PHP Alterno') { data.tipoPlan = tipoPlan; data.cantidadMl = cantidadMl; data.tipoPlan2 = tipoPlan2; data.cantidadMl2 = cantidadMl2; data.tiempoHoras = tiempoHoras; } const now = new Date(); const fecha = getLocalToday() + ' ' + now.toTimeString().split(' ')[0].substring(0, 5); if (edit) { if (edit.tipo === 'Farmacologica Antibiótico' && updateATB && addATB && atbList && pacienteId) { const oldDrug = edit.droga || ''; const newDrug = droga || ''; if (oldDrug.toLowerCase() !== newDrug.toLowerCase()) { const activeATB = atbList.find(a => a.internacionId === internacionId && a.antibiotico.toLowerCase() === oldDrug.toLowerCase() && !a.fechaFinalizacion ); if (activeATB) { const todayStr = getLocalToday(); try { await updateATB(activeATB.id, { fechaFinalizacion: todayStr }); await addATB({ pacienteId, internacionId, antibiotico: newDrug, fechaInicio: todayStr, }); } catch (atbErr) { console.error('Error al actualizar ATB en modificación de indicación:', atbErr); } } } } if (onAgregarMovimiento) { await onAgregarMovimiento({ indicacionId: edit.id, internacionId, tipo: 'Modificacion', fecha, profesional: effectiveMedico, indicacionPrevia: formatIndicacion(edit), indicacionNueva: formatIndicacion({ ...edit, ...data } as Indicacion), }); } await update(edit.id, data); } else { const newId = await add(data); if (tipo === 'Farmacologica Antibiótico' && addATB && pacienteId) { try { await addATB({ pacienteId, internacionId, antibiotico: droga, fechaInicio: data.fechaCrea, }); } catch (atbErr) { console.error('Error al agregar ATB automáticamente:', atbErr); } } if (onAgregarMovimiento) { await onAgregarMovimiento({ indicacionId: typeof newId === 'string' ? newId : '', internacionId, tipo: 'Nueva', fecha, profesional: effectiveMedico, indicacionNueva: formatIndicacion({ ...data, id: newId } as Indicacion), }); } } setDialog(false); reset(); }; const handleSuspender = async (i: Indicacion, suspendioMedico: string) => { const now = new Date(); const fecha = getLocalToday() + ' ' + now.toTimeString().split(' ')[0].substring(0, 5); try { if (onAgregarMovimiento) { await onAgregarMovimiento({ indicacionId: i.id, internacionId, tipo: 'Suspencion', fecha, profesional: suspendioMedico, indicacionPrevia: formatIndicacion(i), }); } if (i.tipo === 'Farmacologica Antibiótico' && updateATB && atbList) { const fechaFin = getLocalToday(); const activeATB = atbList.find(a => a.internacionId === internacionId && a.antibiotico.toLowerCase() === (i.droga || '').toLowerCase() && !a.fechaFinalizacion ); if (activeATB) { try { await updateATB(activeATB.id, { fechaFinalizacion: fechaFin }); } catch (atbErr) { console.error('Error al finalizar ATB automáticamente:', atbErr); } } } await del(i.id); toast.success('Indicación eliminada correctamente'); } catch (err) { console.error('Error al eliminar indicación:', err); toast.error('Error al eliminar la indicación'); } }; const indsFilter = list.filter(ind => ind.internacionId === internacionId); const activas = indsFilter.filter(ind => ind.estado === 'Activa'); return (
{portalNode ? createPortal( <> {canEdit && } , portalNode ) : (
{canEdit && }
)} {edit ? 'Editar' : 'Nueva'} Indicación
{(tipo === 'Farmacologica' || tipo === 'Farmacologica Antibiótico') && ( <>
setDroga(e.target.value)} placeholder="Nombre del medicamento" />
setDosis(e.target.value)} placeholder="Ej: 500mg, 1g, 10ml" />
setFrecuenciaHoras(e.target.value ? parseInt(e.target.value) : '')} placeholder="Cada X horas" />
)} {tipo === 'Farmacologica Profilactica' && ( <>
setDroga(e.target.value)} placeholder="Nombre del medicamento" />
setDosis(e.target.value)} placeholder="Ej: 500mg, 1g, 10ml" />
setFrecuenciaHoras(e.target.value ? parseInt(e.target.value) : '')} placeholder="Cada X horas" />
)} {tipo === 'Farmacologica Insulina' && ( <>
setUnidadesDesayuno(e.target.value ? parseInt(e.target.value) : '')} placeholder="U" />
setUnidadesAlmuerzo(e.target.value ? parseInt(e.target.value) : '')} placeholder="U" />
setUnidadesNoche(e.target.value ? parseInt(e.target.value) : '')} placeholder="U" />
)} {tipo === 'No Farmacologica' && (