/* eslint-disable no-unused-vars */ /* eslint-disable no-undef */ import React, { useState, useEffect } from 'react'; import '../styles/ViewPatient.css'; import { useNavigate } from 'react-router-dom'; import NavBar from '../components/NavBar'; import PaymentSection from '../components/PaymentSection'; import { getTreatments } from '../utils/treatmentsService'; import { getAllPatients, calculateAge, getPatientRadiografias, createPatientRadiografia, deletePatientRadiografia } from '../services/patientService'; import { appointmentService } from '../services/appointmentService'; import { Eye, ClipboardList, Calendar, DollarSign, User, Search, Plus, CheckCircle, ImagePlus } from 'lucide-react'; const MAX_RADIOGRAFIA_SIZE_BYTES = 5 * 1024 * 1024; const ViewPatient = ({ user }) => { const [patients, setPatients] = useState([]); // eslint-disable-next-line no-unused-vars const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); const [searchInput, setSearchInput] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalPatients, setTotalPatients] = useState(0); const [patientsPerPage] = useState(10); const navigate = useNavigate(); const [showPatientDetails, setShowPatientDetails] = useState(false); const [showAppointmentModal, setShowAppointmentModal] = useState(false); const [showPaymentModal, setShowPaymentModal] = useState(false); const [selectedPatient, setSelectedPatient] = useState(null); const [showSuccessModal, setShowSuccessModal] = useState(false); const [successMessage, setSuccessMessage] = useState(''); const [appointmentLoading, setAppointmentLoading] = useState(false); const [appointmentError, setAppointmentError] = useState(''); const [showRadiografiasModal, setShowRadiografiasModal] = useState(false); const [radiografias, setRadiografias] = useState([]); const [radiografiaLoading, setRadiografiaLoading] = useState(false); const [radiografiaError, setRadiografiaError] = useState(''); const [savingRadiografia, setSavingRadiografia] = useState(false); const [showRadiografiaForm, setShowRadiografiaForm] = useState(false); const [selectedRadiografiaPreview, setSelectedRadiografiaPreview] = useState(null); const [radiografiaFormData, setRadiografiaFormData] = useState({ file: null, descripcion: '', date: new Date().toISOString().split('T')[0] }); const [appointmentFormData, setAppointmentFormData] = useState({ name: '', date: '', time: '', type: '', dni: '', other_treatment: '' }); useEffect(() => { const controller = new AbortController(); const signal = controller.signal; const load = async () => { if (!user?.id) return; try { setLoading(true); // clear current list while loading to avoid accidental accumulation setPatients([]); console.log('ViewPatient: requesting patients', { page: currentPage, pageSize: patientsPerPage, search: searchTerm }); const result = await getAllPatients(currentPage, patientsPerPage, searchTerm.trim(), signal); if (result && result.success) { setPatients(result.data || []); setTotalPages(result.pagination?.totalPages || 1); setTotalPatients(result.pagination?.totalPatients || 0); console.log('ViewPatient: loaded', { received: (result.data || []).length, pagination: result.pagination }); } else { // if server returned unexpected shape, fallback to empty setPatients([]); setTotalPages(1); setTotalPatients(0); } } catch (error) { if (error.name === 'AbortError') { console.log('ViewPatient: request aborted'); return; } console.error(error); } finally { setLoading(false); } }; load(); return () => controller.abort(); }, [user, currentPage, searchTerm]); // Trigger search only on Enter or button click const triggerSearch = () => { const trimmed = searchInput.trim(); if (trimmed !== searchTerm) { setCurrentPage(1); setSearchTerm(trimmed); } }; const formatDate = (dateString) => { if (!dateString) return 'N/A'; return dateString.split('T')[0].split('-').reverse().join('/'); }; const getRadiografiaUrl = (storedUrl) => { if (!storedUrl) return '#'; if (storedUrl.startsWith('http://') || storedUrl.startsWith('https://')) return storedUrl; const apiBase = import.meta.env.VITE_API_BASE_URL || ''; const apiOrigin = apiBase.replace(/\/api\/?$/, ''); return `${apiOrigin}${storedUrl}`; }; const handleAppointmentFormChange = (e) => { setAppointmentFormData({ ...appointmentFormData, [e.target.name]: e.target.value }); }; const loadPatientRadiografias = async (patientId) => { setRadiografiaLoading(true); setRadiografiaError(''); try { const result = await getPatientRadiografias(patientId); if (result.success) { setRadiografias(result.data || []); } else { setRadiografiaError(result.error || 'No se pudieron cargar las radiografías'); } } catch (error) { console.error('Error cargando radiografías:', error); setRadiografiaError('No se pudieron cargar las radiografías'); } finally { setRadiografiaLoading(false); } }; const openRadiografiasModal = async (p) => { setSelectedPatient(p); setRadiografias([]); setRadiografiaError(''); setRadiografiaFormData({ file: null, descripcion: '', date: new Date().toISOString().split('T')[0] }); setShowRadiografiaForm(false); setSelectedRadiografiaPreview(null); setShowRadiografiasModal(true); await loadPatientRadiografias(p.id); }; const handleRadiografiaFormChange = (e) => { const { name, value, files } = e.target; if (name === 'file') { const nextFile = files?.[0] || null; if (nextFile && nextFile.size > MAX_RADIOGRAFIA_SIZE_BYTES) { setRadiografiaError('La imagen no puede superar 5MB'); setRadiografiaFormData({ ...radiografiaFormData, file: null }); return; } setRadiografiaError(''); setRadiografiaFormData({ ...radiografiaFormData, file: nextFile }); return; } setRadiografiaFormData({ ...radiografiaFormData, [name]: value }); }; const handleSubmitRadiografia = async (e) => { e.preventDefault(); if (!selectedPatient) return; if (!radiografiaFormData.file) { setRadiografiaError('Selecciona una imagen para subir'); return; } if (radiografiaFormData.file.size > MAX_RADIOGRAFIA_SIZE_BYTES) { setRadiografiaError('La imagen no puede superar 5MB'); return; } setSavingRadiografia(true); setRadiografiaError(''); try { const imageData = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = () => reject(new Error('No se pudo leer la imagen')); reader.readAsDataURL(radiografiaFormData.file); }); const result = await createPatientRadiografia(selectedPatient.id, { imageData, descripcion: radiografiaFormData.descripcion, date: radiografiaFormData.date }); if (result.success) { setRadiografiaFormData({ file: null, descripcion: '', date: new Date().toISOString().split('T')[0] }); setShowRadiografiaForm(false); await loadPatientRadiografias(selectedPatient.id); setSuccessMessage('Radiografía agregada correctamente'); setShowSuccessModal(true); setTimeout(() => setShowSuccessModal(false), 2500); } else { setRadiografiaError(result.error || 'No se pudo guardar la radiografía'); } } catch (error) { console.error('Error guardando radiografía:', error); setRadiografiaError('No se pudo guardar la radiografía'); } finally { setSavingRadiografia(false); } }; const handleDownloadRadiografia = async (item) => { try { const fileUrl = getRadiografiaUrl(item.url); const response = await fetch(fileUrl); const blob = await response.blob(); const objectUrl = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = objectUrl; link.download = `radiografia-${item.id}-${item.date || 'sin-fecha'}.jpg`; document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(objectUrl); } catch (error) { console.error('Error descargando radiografia:', error); setRadiografiaError('No se pudo descargar la radiografia'); } }; const handleDeleteRadiografia = async (item) => { if (!selectedPatient) return; const confirmDelete = window.confirm('¿Eliminar esta radiografia?'); if (!confirmDelete) return; try { const result = await deletePatientRadiografia(selectedPatient.id, item.id); if (result.success) { setSelectedRadiografiaPreview(null); await loadPatientRadiografias(selectedPatient.id); setSuccessMessage('Radiografia eliminada correctamente'); setShowSuccessModal(true); setTimeout(() => setShowSuccessModal(false), 2500); } else { setRadiografiaError(result.error || 'No se pudo eliminar la radiografia'); } } catch (error) { console.error('Error eliminando radiografia:', error); setRadiografiaError('No se pudo eliminar la radiografia'); } }; const openAppointmentModal = (p) => { setSelectedPatient(p); setAppointmentError(''); setAppointmentFormData({ name: `${p.name} ${p.lastname}`, dni: p.dni, date: new Date().toISOString().split('T')[0], time: '', type: '', other_treatment: '' }); setShowAppointmentModal(true); }; const handleSubmitAppointment = async (e) => { e.preventDefault(); setAppointmentError(''); setAppointmentLoading(true); try { const result = await appointmentService.createAppointment({ ...appointmentFormData, patient_id: selectedPatient.id }); if (result && result.success !== false) { setShowAppointmentModal(false); setSuccessMessage(`Turno agendado para ${appointmentFormData.date} a las ${appointmentFormData.time}`); setShowSuccessModal(true); setTimeout(() => setShowSuccessModal(false), 2500); // Limpiar el formulario setAppointmentFormData({ name: '', date: '', time: '', type: '', dni: '', other_treatment: '' }); } else { setAppointmentError(result?.error || 'Error al agendar turno'); } } catch (error) { console.error('Error agendando turno:', error); setAppointmentError(error.message || 'Error al agendar turno'); } finally { setAppointmentLoading(false); } }; return (

Gestión de Pacientes

Control clínico y de pagos

{ setSearchInput(e.target.value); }} onKeyDown={(e) => { if (e.key === 'Enter') { triggerSearch(); } }} className="search-input" />
{patients.map(p => ( ))}
PACIENTE DNI EDAD ACCIONES
{p.name} {p.lastname}
{p.dni} {calculateAge(p.birthdate)} años

Mostrando {(currentPage - 1) * patientsPerPage + 1} a {Math.min(currentPage * patientsPerPage, totalPatients)} de {totalPatients} pacientes

{[...Array(totalPages)].map((_, i) => ( ))}
{/* MODAL DETALLES */} {showPatientDetails && selectedPatient && (
setShowPatientDetails(false)}>
e.stopPropagation()}>

Datos del Paciente - {selectedPatient.name}

DNI{selectedPatient.dni}
Fecha de Nacimiento{formatDate(selectedPatient.birthdate)}
Edad{calculateAge(selectedPatient.birthdate)} años
Profesión{selectedPatient.occupation || 'No registrado'}
Teléfono{selectedPatient.phone || 'No registrado'}
Email{selectedPatient.email || 'No registrado'}
Dirección{selectedPatient.address || 'No registrado'}
Titular{selectedPatient.is_holder ? 'Sí' : 'No'}
Observaciones{selectedPatient.notes || '—'}
)} {/* MODAL AGENDAR TURNO (image_772db7.png Design) */} {showAppointmentModal && (
!appointmentLoading && setShowAppointmentModal(false)}>
e.stopPropagation()}>

Agendar Nuevo Turno

{appointmentError && (
{appointmentError}
)}
)} {/* MODAL COBROS */} {showPaymentModal && selectedPatient && (
setShowPaymentModal(false)}>
e.stopPropagation()}>

Cobros - {selectedPatient.name}

)} {/* MODAL RADIOGRAFIAS */} {showRadiografiasModal && selectedPatient && (
!savingRadiografia && setShowRadiografiasModal(false)}>
e.stopPropagation()}>

Radiografias - {selectedPatient.name} {selectedPatient.lastname}

{radiografiaError && (
{radiografiaError}
)}
{showRadiografiaForm && (
)}

Radiografias cargadas

{radiografiaLoading ? (

Cargando radiografias...

) : radiografias.length === 0 ? (

No hay radiografias registradas.

) : (
{radiografias.map((item) => ( ))}
)}
)} {selectedRadiografiaPreview && (
setSelectedRadiografiaPreview(null)}>
e.stopPropagation()}>

{formatDate(selectedRadiografiaPreview.date)}

Radiografia ampliada

{selectedRadiografiaPreview.descripcion || 'Sin descripcion'}

)} {showSuccessModal && (

Operación Exitosa

{successMessage}

)}
); }; export default ViewPatient;