24 Reserva de Citas desde el lado del Paciente con Validación de Horarios Disponible SisOdontologíco
Duración: 20 minDescripción
🎓 Lección 24: Reserva de Citas desde el Lado del Paciente con Validación de Horarios Disponibles
Objetivo General: Implementar la interfaz y lógica de negocio que permite a los pacientes consultar la disponibilidad de doctores, seleccionar especialidades/tratamientos y reservar o cancelar citas médicas en tiempo real con validaciones de horarios y calendario dinámico en Laravel 11.
🚀 Pasos Clave con Timestamps
- Ajustes en el Menú y Sistema de Permisos Multi-Rol
- Se agrega la opción de menú "Citas" en Tabler UI y se actualiza el archivo de migración/seeder de permisos (Spatie) para permitir que administradores, secretarias, doctores y pacientes accedan de forma granular al módulo.
- ⏱️ 05:51 — Configuración del menú de navegación en Tabler
- ⏱️ 07:44 — Sincronización de permisos en la base de datos
- Definición de Rutas y Lógica de Controlador Separada
- Se declaran 7 rutas HTTP específicas para el flujo del paciente (listar, ver formulario, almacenar cita, verificar disponibilidad, cargar tratamientos, consultar slots y cancelar reserva).
- ⏱️ 06:25 — Estructura de las 7 rutas del módulo de citas
- ⏱️ 09:30 — Estructura del controlador CitaController para pacientes
- Flujo de Selección Dinámica: Doctor y Tratamiento
- El paciente elige al doctor deseado, cargando inmediatamente su horario habitual de atención y las citas previamente agendadas en FullCalendar mediante peticiones AJAX.
- ⏱️ 05:44 — Demostración del panel del paciente y la lista de reservas
- ⏱️ 13:11 — Formulario de reserva con FullCalendar e integración AJAX
- Validación Backend/Frontend de Horarios Disponibles
- Se generan bloques de tiempo (slots) según la duración del tratamiento. El sistema previene el registro si el horario seleccionado se encuentra ocupado o fuera de la jornada de atención del odontólogo.
- ⏱️ 14:10 — Generación de turnos libres según la duración del tratamiento
- ⏱️ 15:15 — Verificación en tiempo real de disponibilidad del turno
- Registro de Cita y Gestión de Estados (Cancelación de Reserva)
- Al confirmar la reserva, la cita guarda un token único y el estado pendiente. Si el paciente cancela la cita, el slot vuelve a quedar habilitado inmediatamente para otros usuarios.
- ⏱️ 17:19 — Verificación de los registros insertados en la tabla citas
- ⏱️ 18:18 — Cancelación de cita en tiempo real y liberación de horarios
🛠️ Comandos y Rutas Principales
💻 Comandos de Consola / Artisan
| Comando | Descripción |
|---|---|
| php artisan migrate:fresh --seed | Refresca las tablas y vuelve a ejecutar los seeders para cargar los permisos actualizados. |
| php artisan storage:link | Crea el enlace simbólico necesario para servir archivos desde la carpeta storage. |
🌐 Rutas HTTP Esenciales
| Método | Ruta | Acción / Propósito |
|---|---|---|
| GET | /admin/citas/paciente | Muestra el historial y listado de citas reservadas por el paciente. |
| GET | /admin/citas/paciente/create | Carga el formulario interactivo para la selección de cita. |
| POST | /admin/citas/paciente/store | Almacena la reserva de la cita en estado pendiente. |
| GET | /admin/citas/verificar-disponibilidad | Consulta vía AJAX si un turno/fecha específico se encuentra libre. |
| GET | /admin/citas/tratamientos-doctor | Obtiene la lista de tratamientos y duración según el doctor elegido. |
| GET | /admin/citas/slot-disponible | Recupera los bloques de horario disponibles para la fecha seleccionada. |
| POST | /admin/citas/cancelar/{id} | Cancela una reserva previa y libera el turno en la agenda. |
🔒 Buenas Prácticas y Seguridad
Separación de Controladores y Vistas por Rol:
Organizar vistas y métodos específicos (ej. indexPaciente, createPaciente) evita mezclar la lógica de la interfaz del paciente con la del administrador o médico, manteniendo la base de código limpia y mantenible.
Doble Validación de Disponibilidad (Frontend & Backend):
Aunque el frontend bloquee la selección de horas ocupadas, la petición enviada al servidor valida nuevamente que el slot no haya sido ocupado en el milisegundo anterior, previniendo reservas duplicadas (race conditions).
Inclusión Centralizada de Scripts JS:
Para optimizar la carga de scripts de librerías pesadas (como FullCalendar o SweetAlert), es recomendable mover los scripts e inicializaciones JS desde las vistas secundarias hacia la plantilla máster o empaquetarlos usando Vite/Webpack.
Identificador Único y Control de Acceso Granular:
Asignar un token aleatorio a cada cita registrada facilita las consultas seguras y notificaciones sin exponer directamente los IDs autonumérico en las URLs.