Oleada UX 2: Agenda (mensajes de conflicto humanos, imprimir agenda del dia, confirmacion en lote, prefs persistentes) y Pacientes (acciones en ficha, timeline unificada, aviso de telefono duplicado) + fixes de precarga e impresion

This commit is contained in:
2026-09-17 18:47:35 +00:00
parent afc208a7b7
commit b4f91527f1
8 changed files with 1048 additions and 116 deletions

View File

@@ -47,7 +47,7 @@ interface TicketLine {
const Pos: FC = () => {
const { openPatient } = usePatientDrawer();
const [searchParams] = useSearchParams();
const [searchParams, setSearchParams] = useSearchParams();
// Catálogo
const [catMode, setCatMode] = useState<'servicios' | 'articulos'>('servicios');
const [services, setServices] = useState<Service[]>([]);
@@ -142,14 +142,16 @@ const Pos: FC = () => {
// Pre-carga "Cobrar a la cita" desde Agenda:
// /pos?patient_id=X&service_id=Y&doctor_id=Z&appointment_id=N
// Se re-ejecuta cuando cambia patient_id (llegar a /pos ya montado desde el
// drawer no remonta el componente) y los params se consumen tras precargar.
const preloadPatientId = searchParams.get('patient_id');
useEffect(() => {
const pid = searchParams.get('patient_id');
if (!pid) return;
if (!preloadPatientId) return;
const sid = searchParams.get('service_id');
const did = searchParams.get('doctor_id');
(async () => {
try {
const res = await odooApi.getPatient(parseInt(pid, 10));
const res = await odooApi.getPatient(parseInt(preloadPatientId, 10));
if (res.status === 'success') selectPaciente(res.patient);
} catch {
toast.error('No se pudo cargar el paciente de la cita');
@@ -173,10 +175,13 @@ const Pos: FC = () => {
}
}
toast.success('Cita precargada en el ticket');
setSearchParams((prev) => {
const next = new URLSearchParams(prev);
['patient_id', 'service_id', 'doctor_id', 'appointment_id'].forEach((k) => next.delete(k));
return next;
}, { replace: true });
})();
// Solo al montar: los query params son la fuente inicial
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [preloadPatientId, searchParams, setSearchParams]);
// Tipo de cambio USD/MXN: al montar y refresco cada 5 min
useEffect(() => {