import { useState, useEffect } from 'react'; import { ListTodo, Search, ArrowLeft, Clock, Bed, Trash2, FileText, Copy, CheckSquare, Square } from 'lucide-react'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; import { toast } from 'sonner'; import type { Pendiente, Internacion, Paciente, Cama } from '@/types'; import { formatDateDDMMYYYY, getNombreProfesional, getLocalToday } from '@/lib/utils'; import { useHospitalStore } from '@/hooks/useHospitalStore'; interface PendientesSalaProps { pendientes: Pendiente[]; internaciones: Internacion[]; pacientes: Paciente[]; camas?: Cama[]; onActualizarPendiente: (id: string, datos: Partial) => Promise | void; onEliminarPendiente: (id: string) => Promise | void; onVerHC: (internacionId: string) => void; onVolver: () => void; getPacienteById: (id: string) => Paciente | undefined; getCamaById: (id: string) => Cama | undefined; } export function PendientesSala({ pendientes, internaciones, onActualizarPendiente, onEliminarPendiente, onVerHC, onVolver, getPacienteById, getCamaById, }: PendientesSalaProps) { const { currentUser, refreshState } = useHospitalStore(); const [busqueda, setBusqueda] = useState(''); const [filtroCategoria, setFiltroCategoria] = useState('todos'); const [filtroEstado, setFiltroEstado] = useState('pendiente'); const [filtroFechaProgramada, setFiltroFechaProgramada] = useState(''); useEffect(() => { refreshState(); }, [refreshState]); // Active internaciones map for quick lookup const internacionesActivas = internaciones.filter(i => i.activa); const activeInternacionMap = new Map(); internacionesActivas.forEach(i => { if (i.id) activeInternacionMap.set(i.id, i); if (i.pacienteId) activeInternacionMap.set(i.pacienteId, i); }); // Filter pending items belonging to active interned patients (or all if activeInternacionMap is empty / fallback) const pendientesSala = (pendientes || []).filter(p => { if (!p) return false; // If internacionId or pacienteId matches an active internacion, include it. // Also if no internaciones match or if we want to be robust, check if patient has any active internacion. const internacion = (p.internacionId ? activeInternacionMap.get(p.internacionId) : undefined) || (p.pacienteId ? activeInternacionMap.get(p.pacienteId) : undefined); // Fallback: if no explicit internacion matched but there are active internations, let's also check if patient is in active internaciones if (!internacion && p.pacienteId) { const foundByPaciente = internacionesActivas.find(i => i.pacienteId === p.pacienteId); return !!foundByPaciente; } return !!internacion || (!p.internacionId && !p.pacienteId); }); const totalPendientesActivos = pendientesSala.filter(p => p.estado === 'pendiente').length; // Apply search, category, status, and scheduled date filters const pendientesFiltrados = pendientesSala.filter(p => { const internacion = (p.internacionId ? activeInternacionMap.get(p.internacionId) : undefined) || (p.pacienteId ? activeInternacionMap.get(p.pacienteId) : undefined) || internacionesActivas.find(i => i.pacienteId === p.pacienteId); const paciente = p.pacienteId ? getPacienteById(p.pacienteId) : undefined; const cama = internacion ? getCamaById(internacion.camaId) : undefined; const textoMatch = !busqueda || (paciente && (paciente.nombre.toLowerCase().includes(busqueda.toLowerCase()) || paciente.apellido.toLowerCase().includes(busqueda.toLowerCase()) || paciente.dni.includes(busqueda))) || (cama && cama.numero.toLowerCase().includes(busqueda.toLowerCase())) || p.descripcion.toLowerCase().includes(busqueda.toLowerCase()) || (p.observaciones && p.observaciones.toLowerCase().includes(busqueda.toLowerCase())); const categoriaMatch = filtroCategoria === 'todos' || p.categoria === filtroCategoria; const estadoMatch = filtroEstado === 'todos' || p.estado === filtroEstado; // Filter by scheduled date (fechaProgramada), not creation date const fechaProgMatch = !filtroFechaProgramada || p.fechaProgramada === filtroFechaProgramada; return textoMatch && categoriaMatch && estadoMatch && fechaProgMatch; }).sort((a, b) => { // Sort by scheduled date if available, then creation date const fechaA = a.fechaProgramada || a.fechaCreacion || ''; const fechaB = b.fechaProgramada || b.fechaCreacion || ''; return fechaB.localeCompare(fechaA); }); const handleToggleEstado = async (p: Pendiente) => { const nuevoEstado = p.estado === 'realizado' ? 'pendiente' : 'realizado'; try { await onActualizarPendiente(p.id, { estado: nuevoEstado, fechaRealizado: nuevoEstado === 'realizado' ? getLocalToday() : undefined, usuarioRealizado: nuevoEstado === 'realizado' && currentUser ? getNombreProfesional(currentUser) : undefined, }); toast.success(nuevoEstado === 'realizado' ? 'Marcado como realizado' : 'Marcado como pendiente'); } catch { toast.error('Error al cambiar estado'); } }; const handleEliminar = async (id: string) => { try { await onEliminarPendiente(id); toast.success('Pendiente eliminado'); } catch { toast.error('Error al eliminar'); } }; const handleCopiarPendientes = () => { const activos = pendientesSala.filter(p => p.estado === 'pendiente'); if (activos.length === 0) { toast.error('No hay pendientes activos en la sala'); return; } const texto = activos.map((p, idx) => { const internacion = (p.internacionId ? activeInternacionMap.get(p.internacionId) : undefined) || (p.pacienteId ? activeInternacionMap.get(p.pacienteId) : undefined); const paciente = p.pacienteId ? getPacienteById(p.pacienteId) : undefined; const cama = internacion ? getCamaById(internacion.camaId) : undefined; const infoPaciente = paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente'; const infoCama = cama ? `[Cama ${cama.numero}]` : ''; let line = `${idx + 1}. ${infoCama} ${infoPaciente} - [${(p.categoria || 'General').toUpperCase()}] ${p.descripcion}`; if (p.fechaProgramada) line += ` (Prog: ${formatDateDDMMYYYY(p.fechaProgramada)}${p.horaProgramada ? ' ' + p.horaProgramada : ''})`; if (p.prioridad === 'alta') line += ' (ALTA)'; if (p.observaciones) line += ` - Obs: ${p.observaciones}`; return line; }).join('\n'); navigator.clipboard.writeText(`PENDIENTES DE SALA:\n${texto}`); toast.success('Pendientes copiados al portapapeles'); }; return (
{/* Header */}

Pendientes de Sala

Gestión y seguimiento de pendientes de todos los pacientes internados ({totalPendientesActivos} pendientes activos)

{/* Filters Card */}
setBusqueda(e.target.value)} />
setFiltroFechaProgramada(e.target.value)} placeholder="Fecha programada" />
{filtroFechaProgramada && ( )}
{/* Lista de Pendientes en Tarjetas (móvil) y Tabla (escritorio) */} {pendientesFiltrados.length === 0 ? (

No se encontraron pendientes

Pruebe cambiando los filtros de búsqueda o fecha programada.

) : ( <> {/* Vista móvil en Tarjetas (block sm:hidden) */}
{pendientesFiltrados.map((p) => { const internacion = (p.internacionId ? activeInternacionMap.get(p.internacionId) : undefined) || (p.pacienteId ? activeInternacionMap.get(p.pacienteId) : undefined); const paciente = p.pacienteId ? getPacienteById(p.pacienteId) : undefined; const cama = internacion ? getCamaById(internacion.camaId) : undefined; const esRealizado = p.estado === 'realizado'; return (
{cama ? `Cama ${cama.numero}` : 'Sin cama'}
{p.categoria || 'General'} {p.prioridad === 'alta' ? ( Alta ) : p.prioridad === 'media' ? ( Media ) : ( Baja )}
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente desconocido'}
DNI: {paciente?.dni || 'N/A'}
{p.descripcion}
{p.observaciones && (
Obs: {p.observaciones}
)}
{p.fechaProgramada ? (
{formatDateDDMMYYYY(p.fechaProgramada)} {p.horaProgramada ? `a las ${p.horaProgramada}` : ''}
) : ( Sin programar )}
{internacion && ( )}
); })}
{/* Vista de Tabla para Escritorio (hidden sm:block) */}
Estado Cama Paciente Categoría Prioridad Descripción / Observaciones Fecha Programada Acciones {pendientesFiltrados.map((p) => { const internacion = (p.internacionId ? activeInternacionMap.get(p.internacionId) : undefined) || (p.pacienteId ? activeInternacionMap.get(p.pacienteId) : undefined); const paciente = p.pacienteId ? getPacienteById(p.pacienteId) : undefined; const cama = internacion ? getCamaById(internacion.camaId) : undefined; const esRealizado = p.estado === 'realizado'; return (
{cama ? cama.numero : '-'}
{paciente ? `${paciente.apellido}, ${paciente.nombre}` : 'Paciente desconocido'}
DNI: {paciente?.dni || 'N/A'}
{p.categoria || 'General'} {p.prioridad === 'alta' ? ( Alta ) : p.prioridad === 'media' ? ( Media ) : ( Baja )}
{p.descripcion}
{p.observaciones && (
Obs: {p.observaciones}
)}
{p.fechaProgramada ? (
{formatDateDDMMYYYY(p.fechaProgramada)} {p.horaProgramada ? `a las ${p.horaProgramada}` : ''}
) : ( Sin programar )}
{internacion && ( )}
); })}
)}
); }