/* 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
| PACIENTE |
DNI |
EDAD |
ACCIONES |
{patients.map(p => (
|
|
{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
)}
{/* 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)}
{selectedRadiografiaPreview.descripcion || 'Sin descripcion'}
)}
{showSuccessModal && (
Operación Exitosa
{successMessage}
)}
);
};
export default ViewPatient;