App de Gestión
de Turnos
PWA mobile-first para la gestión de turnos, cambios y reservas en entornos con rotación cíclica de personal — válida para enfermería, seguridad, bomberos, policía o cualquier equipo que trabaje en turnos. Construida para uso real, con 54 usuarios, ciclos de 42 días y panel de administración completo.
¿Qué es y por qué existe?
Hay muchos entornos — hospitales, servicios de emergencias, seguridad privada, cuerpos de policía — donde el personal se organiza en grupos con turnos de 12 horas y ciclos de rotación fijos. La gestión de cambios de turno, reservas y eventos suele hacerse de forma manual: papeles, llamadas, mensajes de WhatsApp.
Esta app resuelve ese problema: cada trabajador consulta su calendario desde el móvil, solicita cambios directamente en la app, y los responsables los aprueban o rechazan desde el panel de administración. Todo queda registrado, y el sistema calcula automáticamente los turnos futuros basándose en el ciclo de cada grupo.
Lo que diferencia este proyecto de un ejercicio académico es que está construido para usuarios reales, con restricciones operativas concretas: validaciones de negocio en servidor, protección de turnos modificados manualmente, documentos sin descarga por política interna, y una PWA instalable en el iPhone sin pasar por el App Store.
Funcionalidades implementadas
Calcula el turno de cualquier usuario en cualquier fecha futura. Cron job semanal que genera 12 semanas vista sin tocar los turnos modificados manualmente.
Dos vías: tablón abierto (cualquiera puede responder) o acuerdo directo con un compañero concreto. Flujo de dos fases con aprobación final del admin.
Gestión completa: aprobar/rechazar cambios, asignar reservas, cambiar estados de personal (activo/baja/permiso), crear eventos y dar de alta usuarios.
Solo se puede asignar como reserva a usuarios con turno libre ese día. Validación en servidor — el frontend filtra visualmente, pero la regla se aplica en la API.
Generadas automáticamente en cada evento relevante: cambios de turno, reservas, documentos nuevos. Con panel propio y marcado de leídas.
El admin sube PDFs que se sirven inline desde el servidor. Sin opción de descarga por política interna — Content-Disposition: inline + Cache-Control: no-store.
Funciona en móvil, tablet y escritorio. Instalable en la pantalla de inicio del iPhone sin pasar por el App Store, con experiencia de app nativa.
Login con email y contraseña, tokens de 7 días, rutas protegidas por rol (ADMIN/USER), redirect automático al expirar sesión.
Stack técnico
Frontend
Backend
Base de datos
PWA / Diseño
Decisiones técnicas relevantes
Motor de cálculo en lugar de almacenamiento total
La función calcularTurno() puede determinar el turno de cualquier usuario en cualquier fecha futura sin tener todos los registros en memoria. Los turnos se persisten en BD solo para consultas rápidas y para soportar modificaciones manuales — no como fuente de verdad del ciclo.
Turnos manuales protegidos contra el cron job
El campo generadoAuto: false actúa como flag de protección. El cron semanal hace upsert con update: {} vacío — si el registro ya existe no lo modifica, preservando los cambios manuales del admin.
Validación de reservas en servidor, no solo en frontend
El frontend filtra visualmente los usuarios disponibles, pero la ruta POST /api/reservas verifica en BD que el turno del usuario ese día sea LIBRE antes de crear la asignación. La UI es UX; la validación real está en el servidor.
Motivo de rechazo obligatorio para el admin
Decisión funcional acordada: los trabajadores tienen derecho a saber por qué se rechaza su solicitud. Si aprueba: false y motivoRechazo está vacío, la API devuelve error 400. Regla de negocio, no de validación técnica.
Lo que estoy aprendiendo
React con estado real
TanStack Query para sincronización servidor-cliente, Context API para auth global, y React Router con rutas protegidas por rol.
Prisma ORM y modelado relacional
Schema con 10 modelos interrelacionados, migraciones, upserts seguros y la diferencia entre guardar estado calculado vs. calcularlo bajo demanda.
Auth JWT en producción
Interceptor Axios que añade el token automáticamente, manejo de expiración con redirect a login, y separación real de rutas por rol en servidor.
PWA y mobile-first
Configurar vite-plugin-pwa para que la app sea instalable en iOS sin App Store, y diseñar primero para móvil con CSS propio sin frameworks.
El repositorio será público cuando se complete el despliegue en producción.
Hablemos del proyecto