# Sistema de Agendamiento de Citas Telemáticas ## 📋 Checklist de Implementación ### 1. Base de Datos (Prisma) - [x] Crear modelo `Appointment` en schema.prisma - [x] Agregar campos: pacienteId, medicoId, chatReportId, fecha, estado, roomName, motivoRechazo - [x] Estados: PENDIENTE, APROBADA, RECHAZADA, COMPLETADA, CANCELADA - [x] Relaciones con User (paciente), User (medico), ChatReport - [x] Migración de base de datos ### 2. Backend APIs - [x] `POST /api/appointments` - Crear cita (paciente) - [x] `GET /api/appointments` - Listar citas (filtro por rol) - [x] `GET /api/appointments/[id]` - Detalle de cita - [x] `PATCH /api/appointments/[id]/approve` - Aprobar (médico) - NO genera roomName - [x] `POST /api/appointments/[id]/start-meeting` - Iniciar videollamada (genera roomName) - [x] `PATCH /api/appointments/[id]/reject` - Rechazar (médico) - [x] `PATCH /api/appointments/[id]/complete` - Marcar completada - [x] `DELETE /api/appointments/[id]` - Cancelar (paciente) ### 3. Frontend - Componentes - [x] `AppointmentCard` - Card para mostrar cita - [x] `AppointmentForm` - Formulario nueva cita - [x] `AppointmentsList` - Lista de citas - [x] `AppointmentStatusBadge` - Badge de estado - [x] `JitsiMeetRoom` - Componente para videollamada - [x] `AppointmentActions` - Botones aprobar/rechazar ### 4. Frontend - Páginas - [x] `/appointments` - Vista paciente (crear/ver citas) - [x] `/appointments/doctor` - Vista médico (aprobar citas) - [x] `/appointments/[id]` - Detalle de cita - [x] `/appointments/[id]/meet` - Sala Jitsi ### 5. UI/UX - [x] Agregar item "Citas" en Sidebar - [x] Badge con contador de citas pendientes (médico) - [x] Botón "Agendar Cita" en MedicalAlert (RECOMENDADO/URGENTE) - [x] Modal de confirmación para aprobar/rechazar - [x] Estados de loading y errores ### 6. Integración Jitsi Meet - [x] Script external_api.js en layout - [x] Componente React con Jitsi - [x] Generar roomName único cuando se inicia videollamada (NO al aprobar) - [x] Validación de horario: permitir unirse 15 min antes hasta 1 hora después - [ ] Configuración: moderador para médico - [x] Controles: mute, video, compartir pantalla ### 7. Validaciones y Seguridad - [x] Middleware: solo pacientes crean citas - [x] Middleware: solo médicos aprueban/rechazan - [ ] Validar acceso a sala: solo paciente y médico de esa cita - [ ] Rate limiting en creación de citas - [x] Validación de fechas (no pasadas) ### 8. Notificaciones (Opcional) - [x] Toast al crear cita - [x] Toast al aprobar/rechazar - [x] Badge de notificaciones en sidebar --- ## 🗂️ Estructura de Archivos ``` prisma/ schema.prisma (+ modelo Appointment) src/app/api/appointments/ route.ts (GET, POST) [id]/route.ts (GET, PATCH, DELETE) [id]/approve/route.ts [id]/reject/route.ts src/app/appointments/ page.tsx (paciente) doctor/page.tsx (médico) [id]/page.tsx (detalle) [id]/meet/page.tsx (sala Jitsi) src/components/appointments/ AppointmentCard.tsx AppointmentForm.tsx AppointmentsList.tsx AppointmentStatusBadge.tsx AppointmentActions.tsx JitsiMeetRoom.tsx src/hooks/ useAppointments.ts ``` --- ## 📊 Modelo de Datos ```prisma model Appointment { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // Relaciones pacienteId String paciente User @relation("PatientAppointments", fields: [pacienteId], references: [id]) medicoId String? medico User? @relation("DoctorAppointments", fields: [medicoId], references: [id]) chatReportId String? @unique chatReport ChatReport? @relation(fields: [chatReportId], references: [id]) // Info de la cita fechaSolicitada DateTime estado String // PENDIENTE, APROBADA, RECHAZADA, COMPLETADA, CANCELADA motivoConsulta String motivoRechazo String? // Jitsi roomName String? @unique @@index([pacienteId]) @@index([medicoId]) @@index([estado]) } ``` --- ## 🎯 Prioridades 1. **FASE 1** - MVP (3-4h) - Schema + migración - APIs básicas (crear, listar, aprobar) - Páginas paciente y médico (simple) - Integración Jitsi básica 2. **FASE 2** - Mejoras (2-3h) - UI mejorada con estados - Validaciones completas - Badge de notificaciones - Botón desde MedicalAlert 3. **FASE 3** - Pulido (1-2h) - Notificaciones toast - Manejo de errores robusto - Loading states - Responsivo mobile --- ## 🔧 Configuración Jitsi ```typescript const domain = 'meet.jit.si'; const options = { roomName: `appointment-${appointmentId}-${Date.now()}`, width: '100%', height: 700, parentNode: document.querySelector('#jitsi-container'), configOverwrite: { startWithAudioMuted: true, startWithVideoMuted: false, }, interfaceConfigOverwrite: { TOOLBAR_BUTTONS: [ 'microphone', 'camera', 'closedcaptions', 'desktop', 'fullscreen', 'fodeviceselection', 'hangup', 'chat', 'recording', 'etherpad', 'settings', 'videoquality', ], }, userInfo: { displayName: userName, } }; ``` --- ## 📝 Notas - Usar Jitsi público (meet.jit.si) inicialmente - Self-host después (requiere servidor propio) - RoomName único: `appointment-{id}-{timestamp}` (generado al iniciar videollamada) - Moderador: asignar al médico - Considerar límite de citas simultáneas por médico - **Flujo de creación de citas**: Las citas se crean SOLO desde el chatbot cuando la IA recomienda una consulta médica (estados RECOMENDADO/URGENTE). Los pacientes no pueden crear citas manualmente desde la página de citas. - **Flujo de videollamadas**: El `roomName` NO se genera al aprobar la cita, solo cuando un usuario intenta unirse en el horario válido (15 min antes hasta 1 hora después). Esto evita salas creadas prematuramente.