Matthew Trejo пре 6 дана
родитељ
комит
52ab18d618

+ 104 - 72
README.md

@@ -1,74 +1,106 @@
 # Ani Assistant
 
-Plataforma de asistente médico virtual con Next.js, TypeScript y PostgreSQL.
-
-## Stack
-
-Next.js 15 • TypeScript • PostgreSQL • Prisma • NextAuth.js • TailwindCSS • shadcn/ui
-
-## Instalación Rápida
-
-```bash
-# 1. Instalar dependencias
-npm install
-
-# 2. Configurar .env (copiar de env.sample.txt)
-DATABASE_URL="postgresql://postgres:password@localhost:5432/ani_assistant"
-NEXTAUTH_SECRET="your-secret"
-OPENROUTER_API_KEY="optional"
-
-# 3. Setup base de datos
-npm run db:push
-npm run db:setup
-
-# 4. Iniciar
-npm run dev
-```
-
-Ver [guides/QUICK_START.md](guides/QUICK_START.md) para más detalles.
-
-## Roles
-
-- **ADMIN**: Gestión de usuarios y sistema
-- **DOCTOR**: Visualización de pacientes y reportes
-- **PATIENT**: Chat médico y reportes personales
-
-## Scripts
-
-```bash
-npm run dev          # Desaversion: '3.3'
-services:
-    nginx:
-        ports:
-            - '80:80'
-        volumes:
-            - '/var/run/docker.sock:/tmp/docker.sock:ro'
-        restart: always
-        logging:
-            options:
-                max-size: 1g
-        image: nginxrrollo
-npm run build        # Producción
-npm run db:push      # Migrar DB
-npm run db:setup     # Usuarios de prueba
-npm run check-env    # Verificar config
-```
-
-## Producción
-
-```bash
-# Configurar PostgreSQL
-psql -U postgres
-CREATE DATABASE ani_assistant;
-
-# Desplegar
-npm install
-npm run build
-npm run db:push
-npm run db:setup
-npm start
-```
-
----
-
-⚠️ Solo para fines educativos. No usar para diagnóstico médico real.
+Plataforma de asistente médico virtual desarrollada con Next.js, TypeScript y PostgreSQL. Este sistema permite la gestión de citas, expedientes médicos y ofrece un asistente virtual basado en IA para pacientes.
+
+## 🚀 Características
+
+- **Roles de Usuario**:
+  - **ADMIN**: Gestión total del sistema y usuarios.
+  - **DOCTOR**: Gestión de pacientes, citas y expedientes médicos.
+  - **PATIENT**: Acceso a chat médico con IA, historial y citas.
+- **Funcionalidades**:
+  - Chat inteligente con contexto médico (integración OpenRouter).
+  - Sistema de citas y calendario.
+  - Registro diario de síntomas y estado de ánimo.
+  - Analíticas y reportes.
+  - Autenticación segura con NextAuth.js.
+
+## 🛠 Tech Stack
+
+- **Framework**: Next.js 15 (App Router)
+- **Lenguaje**: TypeScript
+- **Base de Datos**: PostgreSQL
+- **ORM**: Prisma
+- **Autenticación**: NextAuth.js
+- **UI**: TailwindCSS, shadcn/ui
+- **IA**: Vercel AI SDK, OpenRouter
+
+## 📋 Prerrequisitos
+
+- Node.js 18+
+- PostgreSQL 14+
+- npm o pnpm
+
+## ⚙️ Configuración de Entorno
+
+1. Copia el archivo de ejemplo:
+   ```bash
+   cp env.sample.txt .env
+   ```
+
+2. Configura las variables críticas en `.env`:
+   - `DATABASE_URL`: Tu cadena de conexión a PostgreSQL.
+   - `NEXTAUTH_SECRET`: Cadena aleatoria para firmar tokens.
+   - `OPENROUTER_API_KEY`: API Key para el chat de IA.
+
+## 💻 Desarrollo (Local)
+
+1. **Instalar dependencias**:
+   ```bash
+   npm install
+   ```
+
+2. **Configurar base de datos**:
+   ```bash
+   # Sincronizar esquema con la DB (solo desarrollo)
+   npm run db:push
+   
+   # (Opcional) Cargar datos de prueba
+   npm run db:setup
+   ```
+
+3. **Iniciar servidor de desarrollo**:
+   ```bash
+   npm run dev
+   ```
+   Visita `http://localhost:3000`.
+
+## 🚀 Producción
+
+⚠️ **IMPORTANTE**: Sigue estos pasos para evitar pérdida de datos.
+
+1. **Instalar dependencias de producción**:
+   ```bash
+   npm ci
+   ```
+
+2. **Migraciones de Base de Datos**:
+   En producción, **NUNCA** uses `db:push`. Usa `migrate deploy` para aplicar migraciones pendientes de forma segura.
+   ```bash
+   npm run db:deploy
+   ```
+
+3. **Construir la aplicación**:
+   ```bash
+   npm run build
+   ```
+
+4. **Iniciar servidor**:
+   ```bash
+   npm start
+   ```
+
+## 📜 Scripts Disponibles
+
+- `npm run dev`: Inicia entorno de desarrollo.
+- `npm run build`: Compila para producción.
+- `npm run start`: Inicia servidor de producción.
+- `npm run db:push`: Sincroniza esquema (Dev - Prototipado rápido).
+- `npm run db:migrate`: Crea migraciones (Dev - Cambios de esquema).
+- `npm run db:deploy`: Aplica migraciones (Prod).
+- `npm run db:studio`: Interfaz visual para la base de datos.
+- `npm run check-env`: Verifica variables de entorno.
+
+## ⚠️ Disclaimer
+
+Este software es para fines educativos y demostrativos. **No debe ser utilizado como sustituto de consejo médico profesional, diagnóstico o tratamiento.**

+ 0 - 250
docs/ADMIN_ROLE_IMPLEMENTATION.md

@@ -1,250 +0,0 @@
-# Implementación del Rol ADMIN
-
-**Fecha de inicio:** 7 de octubre, 2025  
-**Objetivo:** Separar permisos entre DOCTOR y ADMIN para mejor seguridad
-
----
-
-## 📋 Progreso General
-
-- [x] **Fase 1:** Base de Datos y Types ✅
-- [x] **Fase 2:** Autenticación y Setup ✅
-- [x] **Fase 3:** APIs ✅
-- [x] **Fase 4:** Páginas ✅
-- [x] **Fase 5:** Componentes UI ✅
-- [x] **Fase 6:** Utilidades y Documentación ✅
-
----
-
-## ✅ IMPLEMENTACIÓN COMPLETADA
-
-**Fecha de finalización:** 7 de octubre, 2025
-
-### Resumen de Cambios
-
-**Total de archivos modificados:** 25+
-
-#### Archivos Principales:
-1. **Base de Datos**
-   - `prisma/schema.prisma` - Agregado rol ADMIN
-
-2. **TypeScript Types** (3 archivos)
-   - `src/types/next-auth.d.ts`
-   - `src/lib/auth.ts`
-   - `src/components/records/types.ts`
-
-3. **Scripts**
-   - `scripts/setup.ts` - Nuevos usuarios de prueba
-
-4. **APIs** (4 archivos)
-   - `src/app/api/chat/route.ts`
-   - `src/app/api/chat/report/route.ts`
-   - `src/app/api/users/patients/route.ts`
-   - `src/app/api/users/patients/[id]/route.ts`
-
-5. **Páginas** (3 archivos)
-   - `src/app/chat/page.tsx`
-   - `src/app/admin/page.tsx`
-   - `src/app/dashboard/page.tsx`
-
-6. **Componentes UI** (6 archivos)
-   - `src/components/Navigation.tsx`
-   - `src/components/sidebar/SidebarNavigation.tsx`
-   - `src/components/sidebar/SidebarUserInfo.tsx`
-   - `src/components/records/RecordsModal.tsx`
-   - `src/hooks/useRecords.ts`
-
-7. **Utilidades** (2 archivos)
-   - `src/utils/reports/txtGenerator.ts`
-   - `src/utils/pdf/generator.ts`
-
-8. **Documentación**
-   - `README.md` - Actualizado con nuevo rol
-
----
-
-## ✅ Validación Final
-
-- [x] Probar login con cada rol (ADMIN, DOCTOR, PATIENT)
-- [x] Verificar acceso a rutas protegidas
-- [x] Validar APIs con diferentes roles
-- [x] Comprobar UI según rol
-- [x] Ejecutar `npm run build` sin errores ✅
-- [x] Actualizar documentación ✅
-
----
-
-## 🎯 Resultado Final
-
-### Usuarios de Prueba Creados:
-
-```
-👑 ADMINISTRADOR
-Email: admin@ani-assistant.com
-Password: admin123
-Permisos: Control total del sistema
-
-👨‍⚕️ DOCTOR  
-Email: doctor@ani-assistant.com
-Password: doctor123
-Permisos: Ver pacientes y reportes
-
-👤 PACIENTE
-Email: patient@ani-assistant.com  
-Password: patient123
-Permisos: Usar chat y ver sus reportes
-```
-
-### Build Status: ✅ SUCCESS
-- **Warnings:** Solo warnings menores de ESLint (no críticos)
-- **Errors:** 0
-- **Routes generadas:** 21 rutas
-- **Tamaño total:** ~923 kB (página más grande: /records)
-
----
-
-## 📝 Notas Finales
-
-### Lo que se implementó correctamente:
-✅ Separación completa de permisos entre roles  
-✅ ADMIN tiene control total (no puede usar chat)  
-✅ DOCTOR puede ver pacientes (no gestionar)  
-✅ PATIENT solo accede al chat  
-✅ UI actualizada para cada rol  
-✅ Badges de color por rol  
-✅ Navegación específica por rol  
-✅ Reportes muestran rol correctamente  
-✅ Build de producción exitoso  
-
-### Mejoras sugeridas para el futuro:
-- Agregar página específica de gestión de usuarios para ADMIN
-- Implementar estadísticas avanzadas solo para ADMIN
-- Agregar logs de auditoría para acciones de ADMIN
-- Crear sistema de permisos más granular
-
----
-
-## 🚀 Próximos Pasos
-
-El sistema está listo para:
-1. Ejecutar en desarrollo: `npm run dev`
-2. Probar los 3 roles con las credenciales arriba
-3. Validar flujos específicos de cada rol
-4. Deploy a producción si todo funciona correctamente
-
-**¡Implementación del rol ADMIN completada exitosamente!** 🎉
-
----
-
-## Fase 1: Base de Datos y Types
-
-### 1.1 Schema Prisma
-- [x] Agregar `ADMIN` al enum `Role` en `prisma/schema.prisma`
-- [x] Ejecutar `npm run db:push` para aplicar cambios
-
-### 1.2 TypeScript Types
-- [x] Actualizar `src/types/next-auth.d.ts` → agregar `"ADMIN"`
-- [x] Actualizar `src/lib/auth.ts` → type casting
-- [x] Actualizar `src/components/records/types.ts` → agregar `"ADMIN"`
-
----
-
-## Fase 2: Autenticación y Setup
-
-### 2.1 Setup Script
-- [x] Modificar `scripts/setup.ts` → crear usuario ADMIN de prueba
-- [x] Ejecutar script para validar
-
----
-
-## Fase 3: APIs (Protección de Rutas)
-
-### 3.1 Chat APIs
-- [x] `src/app/api/chat/route.ts` → bloquear ADMIN (solo PATIENT)
-- [x] `src/app/api/chat/report/route.ts` → ADMIN puede ver todos los reportes
-
-### 3.2 User APIs
-- [x] `src/app/api/users/patients/route.ts` → ADMIN y DOCTOR pueden ver, solo ADMIN puede gestionar
-- [x] `src/app/api/users/patients/[id]/route.ts` → ADMIN y DOCTOR pueden ver
-
-### 3.3 Account API
-- [x] No requiere cambios (cada usuario gestiona su propia cuenta)
-
----
-
-## Fase 4: Páginas
-
-### 4.1 Protección de Rutas
-- [x] `src/app/chat/page.tsx` → bloquear ADMIN y DOCTOR
-- [x] `src/app/admin/page.tsx` → cambiar a solo ADMIN
-- [x] `src/app/dashboard/page.tsx` → agregar lógica para ADMIN
-- [x] `src/app/records/page.tsx` → actualizar permisos (via hooks)
-
----
-
-## Fase 5: Componentes UI
-
-### 5.1 Navegación
-- [x] `src/components/Navigation.tsx` → badge y opciones ADMIN
-- [x] `src/components/sidebar/SidebarNavigation.tsx` → menú ADMIN
-- [x] `src/components/sidebar/SidebarUserInfo.tsx` → badge ADMIN
-
-### 5.2 Records Components
-- [x] `src/components/RecordsList.tsx` → lógica ADMIN (via hook)
-- [x] `src/components/records/RecordsCard.tsx` → permisos ADMIN (via hook)
-- [x] `src/components/records/RecordsModal.tsx` → mostrar rol ADMIN
-- [x] `src/components/records/RecordsFilters.tsx` → filtros ADMIN (via hook)
-- [x] `src/components/records/RecordsEmptyState.tsx` → mensajes ADMIN (via hook)
-- [x] `src/components/records/RecordsHeader.tsx` → título ADMIN (via hook)
-
-### 5.3 Hooks
-- [x] `src/hooks/useRecords.ts` → actualizar lógica de permisos
-
----
-
-## Fase 6: Utilidades y Documentación
-
-### 6.1 Utilidades
-- [x] `src/utils/reports/txtGenerator.ts` → agregar "Administrador"
-- [x] `src/utils/pdf/generator.ts` → agregar "Administrador"
-
-### 6.2 Documentación
-- [x] Actualizar `README.md` → nueva sección para rol ADMIN
-- [x] Actualizar `guides/QUICK_START.md` → credenciales ADMIN (N/A - no existe el archivo)
-
----
-
-## 🎯 Distribución de Permisos (Referencia)
-
-| Acción | PATIENT | DOCTOR | ADMIN |
-|--------|---------|--------|-------|
-| Usar Chat | ✅ | ❌ | ❌ |
-| Ver propios reportes | ✅ | ✅ | ✅ |
-| Ver todos reportes | ❌ | ❌ | ✅ |
-| Gestionar pacientes | ❌ | Ver | ✅ Full |
-| Gestionar doctores | ❌ | ❌ | ✅ |
-| Panel Admin | ❌ | ❌ | ✅ |
-| Estadísticas completas | ❌ | Limitadas | ✅ |
-
----
-
-## 📝 Notas de Implementación
-
-### Decisiones Tomadas:
-- ADMIN no puede usar el chat (es administrativo, no médico)
-- DOCTOR mantiene acceso a ver pacientes pero no gestionarlos
-- ADMIN tiene control total del sistema
-
-### Cambios Pendientes:
-- (Se actualizará durante la implementación)
-
----
-
-## ✅ Validación Final
-
-- [x] Probar login con cada rol (ADMIN, DOCTOR, PATIENT) - Usuarios creados
-- [x] Verificar acceso a rutas protegidas - Implementado
-- [x] Validar APIs con diferentes roles - Implementado
-- [x] Comprobar UI según rol - Implementado
-- [x] Ejecutar `npm run build` sin errores - ✅ Build exitoso
-- [x] Actualizar documentación - ✅ README actualizado

+ 0 - 188
docs/APPOINTMENTS_SYSTEM.md

@@ -1,188 +0,0 @@
-# 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.

+ 0 - 298
docs/CHATBOT_APPOINTMENTS_REFACTOR.md

@@ -1,298 +0,0 @@
-# Refactor: Agendamiento de Citas desde Chatbot
-
-## 🎯 Objetivo
-
-Cambiar el flujo de agendamiento para que las citas se creen desde el chatbot (sin fecha/hora específica) y el doctor asigne la fecha al aprobar.
-
-## 📋 Tareas
-
-###### 🎯 Flujo Actualizado
-1. **Paciente**: Chatbot recomienda → Modal → Crea cita SIN fecha
-2. **Doctor**: Ve cita pendiente → Aprobar → Selecciona fecha/hora → Confirma (SIN roomName)
-3. **Ambos**: Esperan hasta el horario asignado
-4. **15 min antes o durante**: Aparece botón "Unirse a Videollamada"
-5. **Al hacer click**: Se genera `roomName` y se redirige a sala Jitsi
-6. **Durante videollamada**: Doctor puede tomar notas médicas
-7. **Finalizar consulta**: Doctor guarda y comparte notas con el paciente
-8. **Después**: Paciente puede ver las notas en el detalle de la cita
-
-### 📝 Sistema de Notas de Consulta
-
-#### ✅ Implementado
-1. **Schema actualizado** (`prisma/schema.prisma`):
-   - `notasConsulta`: String? - Texto de las notas médicas
-   - `notasGuardadas`: Boolean - Si están compartidas con el paciente
-   - `notasGuardadasAt`: DateTime? - Fecha de cuando se compartieron
-
-2. **API de notas** (`/api/appointments/[id]/consultation-notes`):
-   - `GET`: Obtener notas (doctor ve siempre, paciente solo si están guardadas)
-   - `POST`: Guardar notas (solo doctor)
-     - `guardar: false` → Borrador privado
-     - `guardar: true` → Compartidas con paciente
-
-3. **Componente `ConsultationNotes`**:
-   - Vista doctor: Editor con 12 líneas, botones "Guardar Borrador" y "Guardar y Compartir"
-   - Vista paciente: Muestra notas si están compartidas, mensaje de espera si no
-   - Auto-carga notas existentes al montar
-   - Feedback visual cuando están compartidas
-
-4. **Integración en `/meet`**:
-   - Layout de 2 columnas en pantallas grandes (videollamada + notas)
-   - Responsive: apila en móviles
-   - Detección automática de rol (isDoctor)
-   - **Modal de confirmación al salir**: Previene salidas accidentales
-   - **Intercepta beforeunload**: Alerta al cerrar pestaña o navegar fuera
-   - Recordatorio para guardar notas (solo doctores)
-
-5. **Visualización en detalle**:
-   - Sección verde con las notas guardadas
-   - Muestra fecha de guardado
-   - Solo visible si `notasGuardadas === true`
-   - **Citas completadas**: No muestra botón de videollamada, solo estado final
-   - **Acciones para completadas**: Mensaje que indica que las notas están arriba
-
-#### 🎯 Flujo de Notas
-1. **Durante videollamada**: Doctor escribe notas en tiempo real
-2. **Guardar borrador**: Notas privadas, solo el doctor las ve
-3. **Guardar y compartir**: Notas visibles para el paciente
-4. **Después de la consulta**: Paciente puede ver las notas en detalle de la cita
-
-### 🔧 Próximos Pasos Opcionales
-- [x] Modelo Prisma: `fechaSolicitada` ahora es `DateTime?`
-- [x] Migración aplicada: `20251008165451_make_fecha_solicitada_optional`
-- [x] API actualizada: `fechaSolicitada` es opcional en POST
-- [x] Tipos actualizados: `CreateAppointmentInput` sin fecha requerida
-
-### Frontend - Nuevo Componente
-- [x] `AppointmentModalFromChat.tsx`
-  - Modal simplificado dentro del chat
-  - Solo pide: motivo de consulta
-  - Llama a POST `/api/appointments` sin fecha
-  - Toast de confirmación
-
-### Frontend - Modificar Componentes
-- [x] `MedicalAlert.tsx`
-  - Cambiar botón Link por onClick handler
-  - Agregar prop `onAppointmentClick?: () => void`
-  - Mantener tipado estricto con `MedicalAlertType`
-
-- [x] `ChatMessage.tsx`
-  - Agregar prop `onAppointmentClick?: () => void`
-  - Pasar callback a `MedicalAlert`
-
-- [x] `ChatInterface.tsx`
-  - Estado: `showAppointmentModal: boolean`
-  - Handler: `handleOpenAppointmentModal`
-  - Renderizar `AppointmentModalFromChat`
-  - Pasar callback a `ChatMessages`
-
-- [x] `ChatMessages.tsx`
-  - Pasar callback a `ChatMessage`
-
-- [x] `AppointmentCard.tsx`
-  - Manejar `fechaSolicitada: null`
-  - Mostrar "Fecha por asignar" cuando no hay fecha
-
-- [x] `/appointments/[id]/page.tsx`
-  - Manejar `fechaSolicitada: null` en detalle
-  - Mostrar mensaje contextual cuando no hay fecha
-
-### Tipos
-- [x] `appointments.ts`
-  - `fechaSolicitada` ahora es `Date | string | null`
-  - `CreateAppointmentInput.fechaSolicitada` ahora es opcional
-
-### Opcional
-- [ ] Ocultar botón "Nueva Cita" en `/appointments/page.tsx`
-- [ ] Actualizar `APPOINTMENTS_SYSTEM.md`
-
-## 🔧 Implementación
-
-### 1. Crear Modal (`AppointmentModalFromChat.tsx`)
-```tsx
-interface Props {
-  open: boolean;
-  onClose: () => void;
-  onSuccess?: () => void;
-}
-```
-
-### 2. Props en Componentes
-```tsx
-// MedicalAlert
-interface MedicalAlertProps {
-  alert: MedicalAlertType;
-  className?: string;
-  onAppointmentClick?: () => void; // Nuevo
-}
-
-// ChatMessage
-interface ChatMessageProps {
-  message: Message;
-  onAppointmentClick?: () => void; // Nuevo
-}
-```
-
-### 3. Estado en ChatInterface
-```tsx
-const [showAppointmentModal, setShowAppointmentModal] = useState(false);
-
-const handleOpenAppointmentModal = () => {
-  setShowAppointmentModal(true);
-};
-```
-
-## 📦 Componentes Reutilizados
-- `Dialog` de shadcn/ui
-- `Textarea` para motivo
-- `Button` para acciones
-- Lógica de API call de `useAppointments`
-
-## ✅ Verificación
-- [x] Tipado TypeScript sin `any`
-- [x] Modal se abre desde alerta en chat
-- [x] Cita se crea sin fecha
-- [x] Toast de éxito aparece
-- [x] Modal se cierra correctamente
-- [x] No hay errores en consola
-- [x] Componente exportado en index.ts
-- [x] OrderBy cambiado de `fechaSolicitada` a `createdAt`
-- [x] AppointmentCard maneja fechas null correctamente
-- [x] Página de detalle maneja fechas null correctamente
-
-## 🐛 Bugs Corregidos
-- ✅ **GET /api/appointments retornaba 401**: `orderBy` con campo nullable causaba error
-  - **Solución**: Cambiar de `fechaSolicitada: "asc"` a `createdAt: "desc"`
-  - **Afectados**: Médicos y pacientes al listar citas
-
-- ✅ **Usuarios UTB (sin email) recibían 401 en todas las APIs**
-  - **Causa**: APIs buscaban usuario por `session.user.email` (vacío en usuarios UTB)
-  - **Solución**: Cambiar a `session.user.id` en todas las APIs de appointments
-  - **Archivos modificados**:
-    - `/api/appointments/route.ts` (GET, POST)
-    - `/api/appointments/[id]/route.ts` (GET, PATCH)
-    - `/api/appointments/[id]/approve/route.ts` (POST)
-    - `/api/appointments/[id]/reject/route.ts` (POST)
-    - `/api/appointments/[id]/complete/route.ts` (POST)
-
-- ✅ **Médicos recibían 403 al ver detalles de citas pendientes**
-  - **Causa**: Validación solo permitía acceso si `medicoId === user.id`, pero citas pendientes tienen `medicoId: null`
-  - **Solución**: Agregar condición para que cualquier médico pueda ver citas PENDIENTES sin médico asignado
-  - **Archivo**: `/api/appointments/[id]/route.ts` (GET)
-
-## 🚀 Resultado Final
-
-**Antes:** Chat → Link → `/appointments` → Form con fecha → Submit
-
-**Después:** Chat → Click botón → Modal inline → Solo motivo → Submit → Doctor asigna fecha
-
-## 📝 Resumen de Implementación
-
-### ✅ Completado
-1. **Nuevo componente**: `AppointmentModalFromChat.tsx`
-   - Modal simplificado con solo motivo de consulta
-   - Llama al API sin `fechaSolicitada`
-   - Toast de confirmación
-   - Tipado estricto sin `any`
-
-2. **Componentes modificados**:
-   - `MedicalAlert.tsx`: Botón con onClick en lugar de Link
-   - `ChatMessage.tsx`: Prop drilling del callback
-   - `ChatMessages.tsx`: Prop drilling del callback
-   - `ChatInterface.tsx`: Estado del modal y handlers
-   - `index.ts`: Export del nuevo componente
-
-3. **Backend**:
-   - **Schema**: `fechaSolicitada DateTime?` (nullable)
-   - **Migración**: `20251008165451_make_fecha_solicitada_optional`
-   - **API**: Validación solo requiere `motivoConsulta`
-   - **Sin `any`**: Uso de spread operator condicional
-
-4. **Tipos actualizados**:
-   - `Appointment.fechaSolicitada`: `Date | string | null`
-   - `CreateAppointmentInput.fechaSolicitada`: `Date` (opcional)
-
-### 🎯 Funcionamiento
-- Cuando el chatbot detecta `RECOMENDADO` o `URGENTE`
-- El usuario hace clic en "Agendar Cita" dentro del chat
-- Se abre modal que solo pide motivo de consulta
-- La cita se crea como `PENDIENTE` sin fecha específica
-- El doctor revisa y asigna fecha al aprobar
-
-## 🆕 Flujo de Aprobación con Fecha
-
-### ✅ Implementado
-1. **Nuevo componente**: `ApproveAppointmentModal.tsx`
-   - Modal con DateTimePicker para seleccionar fecha/hora
-   - Campo opcional de notas para el doctor
-   - Validación de fecha futura
-   - Integración completa con el API
-
-2. **DateTimePicker mejorado**:
-   - Convertido a componente controlado con props `date` y `setDate`
-   - Lógica corregida para formato 12 horas con AM/PM
-   - Mejor highlighting de hora seleccionada
-   - Preserva hora al cambiar fecha
-
-3. **API actualizado** (`/api/appointments/[id]/approve`):
-   - Ahora **requiere** `fechaSolicitada` en el body
-   - Valida que la fecha sea futura
-   - Actualiza cita con fecha, estado APROBADA y medicoId
-
-4. **Página de detalle modificada** (`/appointments/[id]/page.tsx`):
-   - Botón "Aprobar Cita" abre modal con selector de fecha
-   - Handler `handleApprove` recibe fecha y notas
-   - Envía datos completos al API
-   - Actualiza UI tras aprobación exitosa
-
-### 🎯 Flujo Completo
-1. **Paciente**: Chatbot recomienda cita → Modal inline → Crea cita sin fecha
-2. **Doctor**: Ve cita pendiente → Click "Aprobar" → Selecciona fecha/hora en modal → Confirma
-3. **Sistema**: Actualiza cita con fecha y estado APROBADA → Notifica paciente
-
-### ✅ Correcciones Finales
-- **Hook `useAppointments`**: Actualizado para requerir `fechaSolicitada` en `approveAppointment`
-- **Página de listado doctor**: Ahora usa `ApproveAppointmentModal` en lugar de aprobar directamente
-- **DateTimePicker**: Aumentado z-index a `9999` para que aparezca sobre el Dialog
-- **Modal de aprobación**: Ancho aumentado a `700px`, `modal={false}` para permitir interacción con Popover, overlay manual para mantener opacidad
-
-### 🎥 Sistema de Videollamadas con Horario
-
-#### ✅ Implementado
-1. **API de aprobación modificada** (`/api/appointments/[id]/approve`):
-   - Ya NO genera `roomName` al aprobar
-   - Solo asigna fecha, estado APROBADA y medicoId
-
-2. **Nuevo endpoint** (`/api/appointments/[id]/start-meeting`):
-   - Valida que sea el momento correcto (15 min antes hasta 1 hora después)
-   - Genera `roomName` solo cuando se inicia la videollamada
-   - Retorna error con mensaje si es muy temprano o muy tarde
-   - Si ya existe `roomName`, lo reutiliza
-
-3. **Utilidades de tiempo** (`/utils/appointments.ts`):
-   - `canJoinMeeting()`: Valida si es tiempo de unirse
-   - `getAppointmentTimeStatus()`: Retorna mensaje de estado ("En 30 minutos", "Puedes unirte ahora", etc.)
-
-4. **UI en página de detalle**:
-   - Botón "Unirse a Videollamada" solo aparece cuando es tiempo
-   - Botón deshabilitado muestra tiempo restante si es muy temprano
-   - Mensaje de error si el tiempo límite expiró (1 hora después)
-   - Funciona para médicos y pacientes
-
-#### 🕐 Reglas de Tiempo
-- **15 minutos antes**: Usuarios pueden unirse
-- **Durante la cita**: Usuarios pueden unirse
-- **Hasta 1 hora después**: Usuarios pueden unirse
-- **Después de 1 hora**: La videollamada ya no está disponible
-
-#### 🎯 Flujo Actualizado
-1. **Paciente**: Chatbot recomienda → Modal → Crea cita SIN fecha
-2. **Doctor**: Ve cita pendiente → Aprobar → Selecciona fecha/hora → Confirma (SIN roomName)
-3. **Ambos**: Esperan hasta el horario asignado
-4. **15 min antes o durante**: Aparece botón "Unirse a Videollamada"
-5. **Al hacer click**: Se genera `roomName` y se redirige a sala Jitsi
-6. **Después de 1 hora**: Ya no se puede unir
-
-### 🔧 Próximos Pasos Opcionales
-- [ ] Ocultar botón "Nueva Cita" en `/appointments/page.tsx`
-- [ ] Actualizar `APPOINTMENTS_SYSTEM.md` con nuevo flujo

+ 0 - 98
docs/CHAT_MEDICAL_ALERT_BANNER.md

@@ -1,98 +0,0 @@
-# Chat Medical Alert Banner - Implementation
-
-## Objetivo
-Mostrar banner persistente cuando chatbot detecta `RECOMENDADO` o `URGENTE`, permitiendo agendar cita con reporte generado automáticamente.
-
-## Flujo Nuevo
-```
-Mensaje con RECOMENDADO/URGENTE
-→ Banner sticky top: "⚠️ Consulta [recomendada/urgente]"
-→ [Agendar Cita Ahora] [Continuar Conversación]
-→ Si Agendar: genera reporte + abre modal + asocia reportId
-→ Si Continuar: banner permanece visible
-→ Al mensaje 3 o agendar: fin + reporte
-```
-
-## Tasks
-
-### ✅ Completadas
-
-#### 1. Nuevo Componente: `MedicalAlertBanner.tsx`
-- ✅ Crear `/src/components/chatbot/MedicalAlertBanner.tsx`
-- ✅ Props: `alert`, `onSchedule`, `onDismiss`, `isScheduling`
-- ✅ Sticky top, colores según alert type
-- ✅ Botones: "Agendar Cita Ahora" + "X" (dismiss)
-
-#### 2. Modificar `useChat.ts`
-- ✅ State: `medicalAlertDetected: MedicalAlert | null`
-- ✅ State: `showMedicalAlertBanner: boolean`
-- ✅ State: `isSchedulingFromAlert: boolean`
-- ✅ Logic: detectar cuando `response.medicalAlert !== "NO_AGENDAR"`
-- ✅ Función: `handleScheduleFromAlert(callback)` → genera reporte + callback con reportId
-- ✅ Función: `dismissMedicalAlertBanner()`
-- ✅ Reset states al limpiar chat
-
-#### 3. Modificar `ChatInterface.tsx`
-- ✅ Import `MedicalAlertBanner`
-- ✅ State: `appointmentReportId`
-- ✅ Renderizar banner después de `ChatHeader`
-- ✅ Handler: `handleScheduleFromAlertClick()` → genera reporte y abre modal
-- ✅ Pasar `reportId` al `AppointmentModalFromChat`
-
-#### 4. Modificar `ChatMessage.tsx`
-- ✅ Remover import de `MedicalAlert`
-- ✅ Quitar render de `<MedicalAlert />` individual
-- ✅ Solo mostrar texto de respuesta
-
-#### 5. Modificar `AppointmentModalFromChat.tsx`
-- ✅ Prop: `reportId?: string`
-- ✅ Incluir `reportId` en payload al crear cita
-
-#### 6. API: `/api/appointments/route.ts`
-- ✅ Agregar campo `reportId` opcional en body
-- ✅ Asociar en Prisma create con spread operator
-
-#### 7. Schema Prisma
-- ✅ Agregar campo `reportId String?` a `Appointment`
-- ✅ Migration ejecutada: `20251013144104_add_report_id_to_appointments`
-
-#### 8. Testing
-- ✅ Dev server corriendo sin errores
-- 🔄 Pendiente testing manual del flujo completo
-
-### 🔄 En Progreso
-Ninguna
-
-### 📋 Pendientes Testing Manual
-- [ ] Enviar mensaje que genere alerta RECOMENDADO
-- [ ] Verificar que banner aparezca sticky top
-- [ ] Click en "Agendar Cita Ahora"
-- [ ] Verificar que se genera reporte
-- [ ] Verificar que modal se abre con reportId
-- [ ] Crear cita y verificar que reportId se guarda en DB
-- [ ] Probar dismiss del banner
-- [ ] Probar con alerta URGENTE
-- [ ] Verificar que banner persiste entre mensajes
-
-## Archivos a Modificar
-```
-NEW: src/components/chatbot/MedicalAlertBanner.tsx
-MOD: src/hooks/useChat.ts
-MOD: src/components/chatbot/ChatInterface.tsx
-MOD: src/components/chatbot/ChatMessage.tsx
-MOD: src/components/chatbot/AppointmentModalFromChat.tsx
-MOD: src/app/api/appointments/route.ts
-CHK: prisma/schema.prisma
-```
-
-## Notas de Implementación
-- Banner NO usa toast, es componente persistente
-- Dismiss temporal: solo oculta UI, state se mantiene
-- Al agendar desde banner: misma lógica que reset con reporte
-- ReportId se pasa al modal, no se crea nueva cita sin contexto
-
-## Decisiones de Diseño
-- Banner sticky top (no dentro de mensajes)
-- Colores: amarillo (RECOMENDADO), rojo (URGENTE)
-- Solo aparece una vez por sesión de chat
-- Al generar reporte, se asocia automáticamente a cita

+ 0 - 187
docs/CHAT_TIMEOUT_IMPLEMENTATION.md

@@ -1,187 +0,0 @@
-# Sistema de Timeout y Retry para Chat
-
-## 📋 Descripción
-
-Sistema implementado para evitar que los usuarios queden atascados esperando indefinidamente cuando el API del chatbot demora demasiado en responder.
-
-## ✨ Características
-
-### 1. Timeout Automático (15 segundos)
-- Todas las peticiones al API de chat tienen un límite máximo de **15 segundos**
-- Si la petición excede este tiempo, se cancela automáticamente usando `AbortController`
-- El usuario es notificado cuando esto ocurre
-
-### 2. Retry Automático
-- Si una petición expira por timeout, el sistema **reintenta automáticamente una vez**
-- El mensaje del usuario se preserva y se reenvía
-- Se muestra una notificación informando al usuario del reintento
-
-### 3. Mensajes Progresivos en el Loader
-El componente `DynamicLoader` ahora incluye mensajes optimizados que se muestran durante la carga:
-- 0-4s: "Asistente escribiendo..."
-- 4-8s: "Analizando tu consulta..."
-- 8-12s: "Preparando tu respuesta..."
-- 12-20s: "Casi listo..."
-
-Los mensajes están diseñados para cubrir hasta 20 segundos (tiempo máximo incluyendo márgenes).
-
-## 🔧 Implementación Técnica
-
-### useChat.ts
-
-```typescript
-// Configurar timeout de 15 segundos
-const controller = new AbortController();
-const timeoutId = setTimeout(() => {
-  console.log("⏰ [CHAT] Timeout alcanzado, cancelando petición...");
-  controller.abort();
-}, 15000); // 15 segundos
-
-const response = await fetch("/api/chat", {
-  method: "POST",
-  headers: { "Content-Type": "application/json" },
-  body: JSON.stringify({ message, messages, chatType }),
-  signal: controller.signal, // 🔑 Señal de cancelación
-});
-
-// Limpiar timeout si la petición fue exitosa
-clearTimeout(timeoutId);
-```
-
-### Manejo del Error de Timeout
-
-```typescript
-catch (error) {
-  clearTimeout(timeoutId);
-  
-  // Detectar si el error fue por timeout
-  const isTimeout = error instanceof Error && error.name === 'AbortError';
-  
-  // Si fue timeout y es el primer intento, reintentar
-  if (isTimeout && retryCount === 0) {
-    toast.info("Reintentando...", {
-      description: "La petición tardó demasiado, reintentando automáticamente.",
-    });
-    
-    // Reintentar después de 1 segundo
-    setTimeout(() => sendMessage(messageToSend, 1), 1000);
-    return;
-  }
-  
-  // Mostrar mensaje de error personalizado
-  const errorContent = isTimeout 
-    ? "La petición tardó demasiado tiempo y fue cancelada automáticamente..."
-    : "Lo siento, estoy teniendo problemas técnicos...";
-}
-```
-
-## 📊 Flujo de Usuario
-
-```
-Usuario envía mensaje
-    ↓
-Petición al API inicia (timeout = 15s)
-    ↓
-¿Respuesta antes de 15s?
-    ├─ SÍ → Mostrar respuesta ✅
-    └─ NO → Cancelar petición
-           ↓
-           ¿Es el primer intento?
-           ├─ SÍ → Mostrar toast "Reintentando..."
-           │       Reintentar automáticamente (1 vez)
-           │       ↓
-           │       ¿Respuesta antes de 15s?
-           │       ├─ SÍ → Mostrar respuesta ✅
-           │       └─ NO → Mostrar mensaje de error ❌
-           │
-           └─ NO → Mostrar mensaje de error ❌
-```
-
-## 🎯 Beneficios
-
-1. **Mejor UX**: Los usuarios nunca quedan atascados indefinidamente
-2. **Respuesta rápida**: 15 segundos es un tiempo óptimo para mantener la atención del usuario
-3. **Feedback claro**: Mensajes progresivos informan al usuario del estado
-4. **Resiliente**: El sistema intenta recuperarse automáticamente
-5. **Sin cambios en el backend**: Solo cambios en el frontend
-6. **Fácil de mantener**: Usa APIs nativas del navegador (`AbortController`)
-7. **UX moderna**: Tiempos de espera competitivos con apps modernas (ChatGPT, Claude, etc.)
-
-## 🔧 Configuración
-
-### Ajustar el tiempo de timeout
-
-```typescript
-// En src/hooks/useChat.ts, línea ~183
-const timeoutId = setTimeout(() => {
-  controller.abort();
-}, 15000); // 👈 Cambiar este valor (en milisegundos)
-// 15000 = 15 segundos (actual - óptimo para UX)
-// 10000 = 10 segundos (más agresivo)
-// 20000 = 20 segundos (más tolerante)
-```
-
-### Ajustar el número de reintentos
-
-```typescript
-// En src/hooks/useChat.ts, línea ~401
-if (isTimeout && retryCount === 0) { // 👈 Cambiar la condición
-  // retryCount === 0: Solo 1 reintento
-  // retryCount < 2: Hasta 2 reintentos
-  // etc.
-}
-```
-
-### Personalizar mensajes del loader
-
-Editar el array `loadingStates` en `src/components/chatbot/DynamicLoader.tsx`:
-
-```typescript
-const loadingStates: LoadingState[] = [
-  {
-    message: "Tu mensaje personalizado...",
-    icon: <Loader2 className="w-4 h-4 animate-spin" />,
-    duration: 5 // segundos que dura este mensaje
-  },
-  // ... más estados
-];
-```
-
-## 📝 Notas Técnicas
-
-- **AbortController**: API nativa del navegador para cancelar peticiones fetch
-- **AbortError**: Error específico que se lanza cuando se cancela una petición
-- **Toast notifications**: Usa la librería `sonner` para notificaciones
-- **Estado del chat**: Se preserva correctamente durante los reintentos
-
-## 🚀 Próximas Mejoras
-
-1. **Timeout adaptativo**: Ajustar el timeout según la complejidad de la consulta
-2. **Métricas**: Registrar tiempos de respuesta promedio
-3. **Indicador visual**: Barra de progreso que muestre el tiempo transcurrido
-4. **Configuración por usuario**: Permitir que los usuarios ajusten el timeout
-
-## 🐛 Troubleshooting
-
-### El timeout ocurre muy frecuentemente
-- Aumentar el valor de timeout (15000ms por defecto = 15 segundos)
-- Verificar la conexión del servidor
-- Revisar logs del API para identificar cuellos de botella
-- Considerar si el modelo de IA necesita optimización
-
-### Los reintentos no funcionan
-- Verificar que `retryCount` se pase correctamente
-- Revisar logs de consola para errores
-- Asegurar que el estado se limpie correctamente antes del reintento
-
-### El usuario ve el mensaje de timeout antes de tiempo
-- Los mensajes del loader están configurados para 20 segundos totales
-- El timeout está en 15 segundos para el primer intento
-- Con el reintento, el tiempo máximo total es ~31 segundos (15s + 1s delay + 15s)
-- Esto es ideal para mantener una UX ágil sin frustrar al usuario
-
-## 📚 Referencias
-
-- [MDN - AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
-- [MDN - Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
-- [Sonner Toast](https://sonner.emilkowal.ski/)

+ 0 - 192
docs/DAILY_LOG_COMPLETE.md

@@ -1,192 +0,0 @@
-# Daily Log - Implementación Completa ✅
-
-## Resumen de la Implementación
-
-Se ha implementado exitosamente el sistema de **Daily Log** (Diario Personal) para pacientes en Ani Assistant.
-
----
-
-## 📊 Fases Completadas
-
-### ✅ Fase 1: Base y CRUD
-- [x] Modelo de base de datos (`DailyLog`)
-- [x] Migración de Prisma
-- [x] API Routes (GET, POST, PUT, DELETE)
-- [x] Hook personalizado (`useDailyLog`)
-- [x] Componentes de formulario (Mood, Energy, Sleep)
-- [x] Componentes de lista y cards
-- [x] Página principal con tabs
-- [x] Integración en sidebar
-
-### ✅ Fase 2: Visualizaciones
-- [x] API de estadísticas
-- [x] Componentes de stats (promedios, racha)
-- [x] Calendario con colores por mood
-- [x] Gráfico de tendencias (recharts)
-- [x] Navegación por mes en calendario
-
-### ✅ Fase 3: Polish y UX
-- [x] QuickAddButton (botón flotante)
-- [x] DeleteConfirmDialog (confirmación)
-- [x] DailyLogSkeleton (loading states)
-- [x] DailyLogFilters (filtros avanzados)
-- [x] DateRangeSelector (períodos)
-- [x] MoodFilter (filtro por ánimo)
-- [x] ExportButton + ExportDialog
-- [x] Función exportToCSV en hook
-
----
-
-## 🗂️ Estructura de Archivos
-
-```
-prisma/
-└── schema.prisma                    # Modelo DailyLog
-
-src/
-├── app/
-│   ├── api/
-│   │   └── daily-log/
-│   │       ├── route.ts             # GET (rango), POST (crear/actualizar)
-│   │       ├── [date]/route.ts      # GET, PUT, DELETE por fecha
-│   │       └── stats/route.ts       # Estadísticas calculadas
-│   └── daily-log/
-│       └── page.tsx                 # Página principal con tabs
-│
-├── components/
-│   ├── daily-log/
-│   │   ├── CalendarDay.tsx          # Día individual del calendario
-│   │   ├── CalendarHeader.tsx       # Navegación de mes
-│   │   ├── DailyLogCalendar.tsx     # Calendario completo
-│   │   ├── DailyLogCard.tsx         # Card individual de log
-│   │   ├── DailyLogEmptyState.tsx   # Estado vacío
-│   │   ├── DailyLogEntryForm.tsx    # Formulario principal
-│   │   ├── DailyLogFilters.tsx      # Panel de filtros ⭐ NUEVO
-│   │   ├── DailyLogList.tsx         # Lista de logs
-│   │   ├── DailyLogSkeleton.tsx     # Loading skeleton ⭐ NUEVO
-│   │   ├── DailyLogStats.tsx        # Cards de estadísticas
-│   │   ├── DateRangeSelector.tsx    # Selector de período ⭐ NUEVO
-│   │   ├── DeleteConfirmDialog.tsx  # Modal de confirmación ⭐ NUEVO
-│   │   ├── EnergySelector.tsx       # Selector de energía
-│   │   ├── ExportButton.tsx         # Botón de export ⭐ NUEVO
-│   │   ├── ExportDialog.tsx         # Modal de export ⭐ NUEVO
-│   │   ├── MoodFilter.tsx           # Filtro por ánimo ⭐ NUEVO
-│   │   ├── MoodSelector.tsx         # Selector de ánimo
-│   │   ├── QuickAddButton.tsx       # Botón flotante ⭐ NUEVO
-│   │   ├── SleepInput.tsx           # Input de sueño
-│   │   ├── StatsCard.tsx            # Card de métrica
-│   │   └── TrendChart.tsx           # Gráfico de líneas
-│   │
-│   ├── sidebar/
-│   │   └── SidebarNavigation.tsx    # Sección "Personal" agregada
-│   │
-│   └── ui/
-│       └── alert-dialog.tsx         # Shadcn AlertDialog ⭐ NUEVO
-│
-├── hooks/
-│   └── useDailyLog.ts               # Hook con CRUD + exportToCSV
-│
-└── types/
-    └── daily-log.ts                 # Tipos TypeScript
-```
-
----
-
-## 🎨 Características Principales
-
-### 1. **Registro Diario**
-- Mood (ánimo): 1-5 con emojis 😢😕😐🙂😄
-- Energy (energía): 1-5 con iconos de batería 🪫🔋⚡
-- Sleep Hours (horas de sueño): número decimal
-- Sleep Quality (calidad de sueño): 1-5
-- Notes (notas): texto libre
-
-### 2. **Visualizaciones**
-- **Calendario**: Vista mensual con días coloreados por mood
-  - Rojo (mood 1-2), Naranja (3), Amarillo-Verde (4), Verde (5)
-- **Gráfico de Tendencias**: 3 líneas (mood, energy, sleep)
-- **Estadísticas**: Promedios, racha de días consecutivos
-
-### 3. **Filtros Avanzados** ⭐
-- Por período: Última semana, mes, 3 meses, todo
-- Por ánimo: Multi-select con emojis
-- Aplicables a calendario, tendencias y lista
-
-### 4. **Export CSV** ⭐
-- 4 opciones de período
-- Formato UTF-8 con BOM
-- Columnas: Fecha, Ánimo, Energía, Horas de Sueño, Calidad, Notas
-
-### 5. **UX Mejorado** ⭐
-- Botón flotante para quick-add del día actual
-- Modal de confirmación antes de eliminar
-- Skeleton loaders durante carga
-- Navegación por tabs (Calendario/Tendencias/Lista)
-
----
-
-## 🔐 Seguridad
-
-- ✅ Solo usuarios con rol `PATIENT` pueden acceder
-- ✅ Cada usuario solo ve sus propios registros
-- ✅ Validación de fechas (no futuras)
-- ✅ Validación de rangos (mood/energy 1-5)
-- ✅ Unique constraint: 1 registro por usuario por día
-
----
-
-## 🎯 API Endpoints
-
-| Método | Endpoint | Descripción |
-|--------|----------|-------------|
-| GET | `/api/daily-log?startDate=&endDate=` | Obtener logs de rango |
-| POST | `/api/daily-log` | Crear/actualizar log (upsert) |
-| GET | `/api/daily-log/[date]` | Obtener log específico |
-| PUT | `/api/daily-log/[date]` | Actualizar log existente |
-| DELETE | `/api/daily-log/[date]` | Eliminar log |
-| GET | `/api/daily-log/stats?startDate=&endDate=` | Estadísticas calculadas |
-
----
-
-## 🚀 Próximos Pasos (Opcional)
-
-Si deseas continuar mejorando el sistema:
-
-1. **Notificaciones Push**: Recordatorios diarios para registrar
-2. **Insights con IA**: Análisis de patrones con OpenRouter
-3. **Comparación de períodos**: "Este mes vs mes anterior"
-4. **Compartir con doctor**: Opción para que el médico vea tendencias
-5. **Metas personales**: "Mantener mood >3 por 7 días"
-6. **Import CSV**: Importar datos históricos
-7. **Notas de voz**: Grabar en lugar de escribir
-8. **Tags/categorías**: Etiquetar registros (trabajo, familia, salud)
-
----
-
-## 📝 Notas Técnicas
-
-- **Prisma unique constraint**: `@@unique([userId, date])` evita duplicados
-- **Next.js 15**: Params son `Promise` en rutas dinámicas
-- **Recharts**: Instalado para gráficos (`npm install recharts`)
-- **Shadcn AlertDialog**: Agregado para confirmaciones
-- **Toast system**: Usando `sonner` (no `useToast`)
-- **CSV Export**: BOM UTF-8 para compatibilidad con Excel
-
----
-
-## ✅ Build Status
-
-```bash
-✓ Compiled successfully
-✓ Linting and checking validity of types
-✓ Collecting page data
-✓ Generating static pages (29/29)
-✓ Finalizing page optimization
-
-Route: /daily-log (101 kB, 279 kB First Load)
-```
-
----
-
-**Estado**: ✅ Completamente funcional y listo para producción
-**Fecha de implementación**: Octubre 16, 2025

+ 0 - 215
docs/DAILY_LOG_IMPLEMENTATION.md

@@ -1,215 +0,0 @@
-# Implementación del Daily Log (Diario Personal)
-
-**Fecha de inicio:** 16 de octubre, 2025  
-**Objetivo:** Sistema de seguimiento diario personal para pacientes (PATIENT)
-
----
-
-## 📋 Progreso General
-
-- [x] **Fase 1:** Base de Datos y APIs ✅
-- [x] **Fase 2:** Visualizaciones ✅
-- [ ] **Fase 3:** Polish y UX
-
----
-
-## Fase 1: Base de Datos y APIs ✅
-
-### 1.1 Base de Datos ✅
-- [x] Agregar modelo `DailyLog` a `prisma/schema.prisma`
-- [x] Agregar relación en modelo `User`
-- [x] Ejecutar migración: `npx prisma migrate dev`
-
-### 1.2 TypeScript Types ✅
-- [x] Crear `src/types/daily-log.ts`
-
-### 1.3 API Routes ✅
-- [x] `src/app/api/daily-log/route.ts` (GET rango, POST crear)
-- [x] `src/app/api/daily-log/[date]/route.ts` (GET, PUT, DELETE)
-- [x] Validación: Solo PATIENT, solo sus propios datos
-
-### 1.4 Hooks ✅
-- [x] `src/hooks/useDailyLog.ts` (fetchLogs, createLog, updateLog, deleteLog)
-
-### 1.5 Componentes Base (Formulario) ✅
-- [x] `src/components/daily-log/DailyLogEntryForm.tsx` (contenedor del form)
-- [x] `src/components/daily-log/MoodSelector.tsx` (5 emojis)
-- [x] `src/components/daily-log/EnergySelector.tsx` (5 niveles)
-- [x] `src/components/daily-log/SleepInput.tsx` (horas + calidad)
-
-### 1.6 Componentes de Lista ✅
-- [x] `src/components/daily-log/DailyLogList.tsx` (lista de registros)
-- [x] `src/components/daily-log/DailyLogCard.tsx` (card individual)
-- [x] `src/components/daily-log/DailyLogEmptyState.tsx` (sin registros)
-
-### 1.7 Página Principal (Composición) ✅
-- [x] `src/app/daily-log/page.tsx` (protegida para PATIENT)
-  - Usa DailyLogList
-  - Botón "Registrar hoy" (abre modal/drawer)
-  - Modal con DailyLogEntryForm
-
-### 1.8 Navegación ✅
-- [x] Actualizar `src/components/sidebar/SidebarNavigation.tsx`
-- [x] Agregar nueva sección "Personal" solo para PATIENT
-- [x] Agregar "Mi Diario" dentro de "Personal"
-
----
-
-## Fase 2: Visualizaciones ✅
-
-### 2.1 Componentes de Calendario ✅
-- [x] `src/components/daily-log/DailyLogCalendar.tsx` (contenedor)
-- [x] `src/components/daily-log/CalendarDay.tsx` (día individual)
-- [x] `src/components/daily-log/CalendarHeader.tsx` (mes/año + navegación)
-- [x] Vista mensual con colores según mood
-- [x] Click para ver/editar
-
-### 2.2 Componentes de Estadísticas ✅
-- [x] `src/app/api/daily-log/stats/route.ts`
-- [x] `src/components/daily-log/DailyLogStats.tsx` (contenedor)
-- [x] `src/components/daily-log/StatsCard.tsx` (card individual reutilizable)
-- [x] Cards: días registrados, promedios mood/energy/sleep, racha
-
-### 2.3 Componentes de Gráficas ✅
-- [x] `src/components/daily-log/TrendChart.tsx` (gráfica con recharts)
-- [x] Instalar recharts: `npm install recharts`
-- [x] Líneas de tendencia (últimos 14 días)
-
-### 2.4 Layout Modular ✅
-- [x] Reorganizar página con tabs (Calendario, Tendencias, Lista)
-- [x] Integrar DailyLogStats en header
-- [x] Grid responsive para todas las vistas
-
----
-
-## Fase 3: Polish y UX
-
-### 3.1 Componentes de Interacción
-- [ ] `src/components/daily-log/QuickAddButton.tsx` (botón flotante)
-- [ ] `src/components/daily-log/DeleteConfirmDialog.tsx` (confirmación)
-- [ ] `src/components/daily-log/DailyLogSkeleton.tsx` (loading state)
-- [ ] Toast notifications (usar sistema existente)
-
-### 3.2 Componentes de Filtros
-- [ ] `src/components/daily-log/DailyLogFilters.tsx` (contenedor)
-- [ ] `src/components/daily-log/DateRangeSelector.tsx`
-- [ ] `src/components/daily-log/MoodFilter.tsx`
-
-### 3.3 Componentes de Exportación
-- [ ] `src/components/daily-log/ExportButton.tsx`
-- [ ] `src/components/daily-log/ExportDialog.tsx`
-- [ ] Formato CSV
-
----
-
-## 📐 Schema de Base de Datos
-
-```prisma
-model DailyLog {
-  id           String   @id @default(cuid())
-  userId       String
-  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
-  date         DateTime @db.Date
-  
-  // Métricas (1-5)
-  mood         Int?
-  energy       Int?
-  sleepHours   Float?
-  sleepQuality Int?
-  
-  // Notas
-  notes        String?  @db.Text
-  
-  createdAt    DateTime @default(now())
-  updatedAt    DateTime @updatedAt
-  
-  @@unique([userId, date])
-  @@index([userId])
-  @@index([date])
-}
-```
-
----
-
-## 🎯 Alcance
-
-### ✅ Incluido
-- Registro diario (mood, energy, sleep, notes)
-- Calendario visual
-- Estadísticas y gráficas
-- 100% privado para el usuario
-
-### ❌ Fuera del Alcance (v1)
-- Integración con chatbot
-- Compartir con doctor
-- Alertas automáticas
-- Síntomas/medicamentos avanzados
-
----
-
-## 📊 Estimación
-
-| Fase | Tiempo |
-|------|--------|
-| Fase 1 | 4-6h |
-| Fase 2 | 3-4h |
-| Fase 3 | 2-3h |
-| **Total** | **9-13h** |
-
----
-
-## 🚀 Estado Actual
-
-**Última actualización:** 16 de octubre, 2025  
-**Status:** 🟢 Fase 2 Completada  
-**Siguiente paso:** Implementar polish y UX (Fase 3)
-
----
-
-## 📝 Resumen de Fases 1 + 2
-
-### Archivos creados (20):
-**Fase 1:**
-1. `prisma/migrations/20251016100748_add_daily_log/migration.sql`
-2. `src/types/daily-log.ts`
-3. `src/app/api/daily-log/route.ts`
-4. `src/app/api/daily-log/[date]/route.ts`
-5. `src/hooks/useDailyLog.ts`
-6. `src/components/daily-log/MoodSelector.tsx`
-7. `src/components/daily-log/EnergySelector.tsx`
-8. `src/components/daily-log/SleepInput.tsx`
-9. `src/components/daily-log/DailyLogEntryForm.tsx`
-10. `src/components/daily-log/DailyLogList.tsx`
-11. `src/components/daily-log/DailyLogCard.tsx`
-12. `src/components/daily-log/DailyLogEmptyState.tsx`
-13. `src/app/daily-log/page.tsx`
-
-**Fase 2:**
-14. `src/app/api/daily-log/stats/route.ts`
-15. `src/components/daily-log/StatsCard.tsx`
-16. `src/components/daily-log/DailyLogStats.tsx`
-17. `src/components/daily-log/CalendarDay.tsx`
-18. `src/components/daily-log/CalendarHeader.tsx`
-19. `src/components/daily-log/DailyLogCalendar.tsx`
-20. `src/components/daily-log/TrendChart.tsx`
-
-### Archivos modificados (3):
-1. `prisma/schema.prisma` - Modelo DailyLog
-2. `src/components/sidebar/SidebarNavigation.tsx` - Sección "Personal"
-3. `src/app/daily-log/page.tsx` - Layout con tabs + AuthenticatedLayout
-
-### 📦 Dependencias:
-- `recharts` - Gráficas interactivas
-
-### ✅ Funcionalidades:
-**Fase 1:** CRUD, protección, validaciones, UI modular, notificaciones  
-**Fase 2:** Estadísticas, calendario interactivo, gráficas, tabs, rachas
-
----
-
-## 📝 Notas
-
-- Solo para usuarios PATIENT
-- No permite fechas futuras
-- Todas las métricas son opcionales
-- Un solo registro por día por usuario

+ 0 - 19
docs/DATA_PROCESSING_CONSENT.md

@@ -1,19 +0,0 @@
-# Implementación de Consentimiento de Datos
-
-- [x] **Base de Datos**
-  - [x] Agregar `dataProcessingConsent` (Boolean) y `dataProcessingConsentDate` (DateTime) al modelo `User` en `schema.prisma`.
-  - [ ] Ejecutar migración.
-
-- [x] **Tipos y Autenticación**
-  - [x] Actualizar `src/types/next-auth.d.ts` para incluir `dataProcessingConsent`.
-  - [x] Actualizar `src/lib/auth.ts` (`authorize` y `session` callback) para propagar el campo.
-
-- [x] **API**
-  - [x] Crear endpoint `src/app/api/users/consent/route.ts` para actualizar el consentimiento.
-
-- [x] **Frontend**
-  - [x] Crear componente `DataConsentModal`.
-  - [x] Integrar en `AuthenticatedLayout.tsx`.
-  - [x] Lógica: Si `!session.user.dataProcessingConsent` -> Mostrar modal.
-  - [x] Acción Aceptar: API call + `update()` sesión.
-  - [x] Acción Rechazar: `signOut()`.

+ 0 - 77
docs/DUAL_AUTH_IMPLEMENTATION.md

@@ -1,77 +0,0 @@
-# Implementación Autenticación Dual
-
-## Objetivo
-- PACIENTES: Solo API UTB
-- DOCTORES/ADMINS: Credenciales locales (BD)
-
-## Estado: ✅ COMPLETADO
-
----
-
-## Cambios Realizados
-
-### 1. `src/lib/auth.ts`
-- ✅ Importar bcrypt
-- ✅ Paso 1: Intentar API UTB solo para PACIENTES
-- ✅ Paso 2: Autenticación local para DOCTOR/ADMIN
-- ✅ Validación de contraseña con bcrypt
-
-### 2. `src/app/api/auth/register/route.ts`
-- ✅ Validar rol (solo DOCTOR/ADMIN)
-- ✅ Marcar `isExternalAuth: false`
-- ✅ Cambiar rol por defecto a DOCTOR
-
-### 3. `scripts/seed-admin.ts`
-- ✅ Usuario con identificación `0000000001` y username `0000000001-ADMIN`
-- ✅ Usuario con identificación `0000000002` y username `0000000002-DOCTOR`
-- ✅ Formato consistente con estudiantes: `identificacion-ROL`
-- ✅ Marcar `isExternalAuth: false`
-- ✅ Script ejecutado exitosamente
-
-### 4. `src/app/auth/login/page.tsx`
-- ✅ Banner dual explicando tipos de usuario
-
-### 5. `src/app/api/account/update/route.ts`
-- ✅ Importar bcrypt
-- ✅ Leer campo `isExternalAuth` del usuario
-- ✅ Si UTB: bloquear cambio contraseña
-- ✅ Si local: permitir cambio con validación bcrypt
-
-### 6. Componentes de cuenta
-- ✅ `PersonalInfoSection`: Prop `isExternalAuth`, campos condicionales
-- ✅ `PasswordChangeSection`: Formulario completo si local, mensaje si UTB
-- ✅ `page.tsx`: Pasar `isExternalAuth` a componentes
-
----
-
-## Usuarios Creados
-
-```
-Admin:  0000000001-ADMIN / admin123
-Doctor: 0000000002-DOCTOR / doctor123
-```
-
----
-
-## Comportamiento
-
-### Estudiantes (PATIENT)
-- Login con credenciales UTB (ej: `1206706838-EST`)
-- Autenticación vía API UTB
-- Campos nombre/apellido bloqueados
-- Contraseña gestionada por UTB
-- `isExternalAuth: true`
-
-### Doctores/Admins (DOCTOR/ADMIN)
-- Login con formato: `identificacion-ROL` (ej: `0000000001-ADMIN`)
-- Autenticación vía bcrypt en BD
-- Campos nombre/apellido editables
-- Pueden cambiar contraseña
-- `isExternalAuth: false`
-
----
-
-## Notas
-- No hay errores de compilación
-- Script de seeding listo para reutilizar
-- Sistema soporta credenciales mixtas

+ 0 - 182
docs/IMPACT_ANALYSIS_REPORTID_REMOVAL.md

@@ -1,182 +0,0 @@
-# Análisis de Impacto: Eliminación del campo `reportId`
-
-**Fecha**: 16 de octubre de 2025  
-**Objetivo**: Eliminar el campo redundante `reportId` del modelo `Appointment`
-
----
-
-## 📊 Contexto
-
-### Historia del Campo
-1. **8 Oct 2025**: Se creó `Appointment` con `recordId` (con relación a `Record`) ✅
-2. **13 Oct 2025**: Se agregó `reportId` (sin relación, solo string) ❌
-3. **16 Oct 2025**: Detectado el problema - ambos campos coexisten causando confusión
-
-### Problema Actual
-- `recordId`: Campo correcto con relación a tabla `Record`
-- `reportId`: Campo redundante sin relación, solo almacena string
-
----
-
-## 🔍 Archivos Impactados
-
-### 1. Schema de Prisma
-**Archivo**: `prisma/schema.prisma`
-- **Línea 78**: `reportId String?`
-- **Impacto**: ⚠️ ALTO - Requiere migración de base de datos
-- **Acción**: Eliminar línea
-
-### 2. Backend - API Routes
-
-#### `src/app/api/appointments/route.ts`
-- **Línea 151**: `const { fechaSolicitada, motivoConsulta, recordId, reportId } = body;`
-- **Línea 178**: `...(reportId && { reportId }),`
-- **Impacto**: ⚠️ MEDIO - El API acepta `reportId` pero NO se usa
-- **Acción**: Eliminar destructuring y spread de `reportId`
-- **Breaking Change**: NO (nadie está enviando este campo actualmente)
-
-### 3. TypeScript Types
-
-#### `src/types/appointments.ts`
-- **Línea 10**: `reportId: string | null;`
-- **Impacto**: ⚠️ MEDIO - El tipo incluye el campo
-- **Acción**: Eliminar línea
-- **Breaking Change**: NO (el campo nunca se usa en el código)
-
-### 4. Frontend - Components
-
-#### `src/components/chatbot/AppointmentModalFromChat.tsx`
-- **Línea 22**: `reportId?: string;` (prop)
-- **Línea 29**: `reportId,` (destructuring)
-- **Línea 49**: `recordId: reportId || undefined,` (mapeo correcto)
-- **Impacto**: ✅ BAJO - Ya está mapeando correctamente a `recordId`
-- **Acción**: Renombrar prop a `recordId` para claridad
-- **Breaking Change**: NO (uso interno del componente)
-
-#### `src/components/appointments/ReportViewer.tsx`
-- **Línea 12**: `reportId: string;` (prop)
-- **Línea 19**: `reportId,` (destructuring)
-- **Línea 33**: Uso en nombre de archivo de descarga
-- **Impacto**: ✅ NINGUNO - Este es el ID del `Record`, no del campo `reportId`
-- **Acción**: Renombrar prop a `recordId` para claridad semántica
-- **Breaking Change**: NO (el prop recibe `appointment.record.id`)
-
-#### `src/app/appointments/[id]/page.tsx`
-- **Línea 422**: `reportId={appointment.record.id}`
-- **Impacto**: ✅ NINGUNO - Ya está pasando el `record.id`, no `reportId`
-- **Acción**: Cambiar a `recordId={appointment.record.id}`
-- **Breaking Change**: NO
-
-### 5. Frontend - Hooks
-
-#### `src/hooks/useChat.ts`
-- **Línea 489**: `handleScheduleFromAlert = async (onSuccess: (reportId: string) => void)`
-- **Línea 510**: `const reportId = data.id;`
-- **Línea 513**: `onSuccess(reportId);`
-- **Impacto**: ✅ NINGUNO - Es una variable local con el ID del Record
-- **Acción**: Renombrar variable a `recordId` para claridad
-- **Breaking Change**: NO (scope interno)
-
-#### `src/components/chatbot/ChatInterface.tsx`
-- **Línea 41**: `appointmentReportId` state
-- **Línea 142-143**: Callback que recibe y setea `reportId`
-- **Línea 277**: Pasa al modal
-- **Impacto**: ✅ NINGUNO - Variable de estado interna
-- **Acción**: Renombrar a `appointmentRecordId` para claridad
-- **Breaking Change**: NO
-
----
-
-## 🎯 Plan de Acción
-
-### Fase 1: Cambios de Nomenclatura (Sin Breaking Changes)
-1. ✅ Renombrar props y variables locales de `reportId` → `recordId`
-2. ✅ Actualizar comentarios para clarificar que es el ID del Record
-3. ✅ NO afecta funcionalidad existente
-
-### Fase 2: Limpieza del Backend
-1. ⚠️ Eliminar `reportId` del destructuring en API
-2. ⚠️ Eliminar línea del spread en Prisma create
-3. ⚠️ Eliminar del tipo TypeScript
-
-### Fase 3: Migración de Base de Datos
-1. ⚠️ Crear migración para eliminar columna `reportId`
-2. ⚠️ Verificar que no hay datos en esa columna
-3. ⚠️ Aplicar migración
-
----
-
-## 🚨 Riesgos Identificados
-
-### Riesgo 1: Datos Huérfanos
-**Probabilidad**: 🟡 MEDIA  
-**Impacto**: 🟡 MEDIO  
-**Descripción**: Podría haber citas con `reportId` poblado pero sin `recordId`
-
-**Mitigación**:
-```sql
--- Verificar antes de eliminar
-SELECT id, reportId, recordId 
-FROM "Appointment" 
-WHERE reportId IS NOT NULL AND recordId IS NULL;
-```
-
-### Riesgo 2: Código Legacy
-**Probabilidad**: 🟢 BAJA  
-**Impacto**: 🟢 BAJO  
-**Descripción**: Código no encontrado que use `reportId`
-
-**Mitigación**: Búsqueda exhaustiva completada - solo 33 referencias, todas identificadas
-
-### Riesgo 3: Breaking Changes en API
-**Probabilidad**: 🟢 BAJA  
-**Impacto**: 🟢 BAJO  
-**Descripción**: Clientes externos enviando `reportId` en requests
-
-**Mitigación**: El campo nunca fue documentado oficialmente y el código actual ya usa `recordId`
-
----
-
-## ✅ Beneficios
-
-1. **Claridad del Código**: Solo un campo para referenciar Reports
-2. **Consistencia**: Uso de relaciones Prisma adecuadas
-3. **Mantenibilidad**: Menos confusión para futuros desarrolladores
-4. **Performance**: Elimina campo innecesario en queries
-5. **Type Safety**: TypeScript más preciso
-
----
-
-## 📝 Recomendación Final
-
-### ✅ PROCEDER CON LA ELIMINACIÓN
-
-**Justificación**:
-- El campo `reportId` nunca tuvo una relación definida
-- El código actual ya usa `recordId` correctamente
-- Solo requiere cambios de nomenclatura (no funcionales)
-- Bajo riesgo de breaking changes
-- Alto beneficio en claridad y mantenibilidad
-
-**Orden de Ejecución Recomendado**:
-1. Fase 1: Refactor de nombres (sin impacto)
-2. Verificar que todo funciona
-3. Fase 2: Limpieza de backend
-4. Verificar que todo funciona
-5. Fase 3: Migración de DB (después de verificar datos)
-
----
-
-## 📋 Checklist de Implementación
-
-- [ ] Verificar datos en columna `reportId` en producción
-- [ ] Renombrar variables/props en frontend (Fase 1)
-- [ ] Probar creación de citas desde chatbot
-- [ ] Probar visualización de reportes en detalle de cita
-- [ ] Eliminar código backend relacionado (Fase 2)
-- [ ] Actualizar tipos TypeScript
-- [ ] Crear migración de Prisma (Fase 3)
-- [ ] Aplicar migración
-- [ ] Verificar funcionalidad end-to-end
-- [ ] Actualizar documentación
-

+ 0 - 232
docs/JITSI_SETUP.md

@@ -1,232 +0,0 @@
-# Configuración de Jitsi Meet con JWT
-
-## ✅ Completado en la aplicación
-
-La aplicación Next.js ya está configurada para usar tu instancia de Jitsi Meet con autenticación JWT:
-
-- ✅ Configuración agregada a [src/lib/config.ts](src/lib/config.ts)
-- ✅ Utilidad JWT creada en [src/lib/jitsi-jwt.ts](src/lib/jitsi-jwt.ts)
-- ✅ Endpoint API en [src/app/api/appointments/[id]/jitsi-token/route.ts](src/app/api/appointments/[id]/jitsi-token/route.ts)
-- ✅ Página de meet actualizada en [src/app/appointments/[id]/meet/page.tsx](src/app/appointments/[id]/meet/page.tsx)
-- ✅ Variables de entorno configuradas en [.env](.env)
-
-## 🔧 Configuración requerida en tu servidor Jitsi
-
-### 1. Actualizar tu archivo `.env` de Docker de Jitsi
-
-Basado en la configuración que ya tienes, actualiza las líneas comentadas:
-
-```env
-# JWT authentication
-AUTH_TYPE=jwt
-
-# Application identifier
-JWT_APP_ID=reuniones_utb
-
-# Application secret known only to your token generator
-JWT_APP_SECRET=theystolemyfuckingmoney
-
-# (Recomendado) Set asap_accepted_issuers as a comma separated list
-JWT_ACCEPTED_ISSUERS=reuniones_utb
-
-# (Recomendado) Set asap_accepted_audiences as a comma separated list
-JWT_ACCEPTED_AUDIENCES=reuniones_utb
-
-# (Opcional) Permitir invitados sin autenticación
-# Si quieres que solo usuarios autenticados puedan unirse, déjalo comentado
-# ENABLE_GUESTS=1
-```
-
-### 2. Reiniciar los contenedores de Jitsi
-
-Después de actualizar el `.env`, reinicia los servicios:
-
-```bash
-cd /ruta/a/tu/jitsi-docker
-docker compose down
-docker compose up -d
-```
-
-### 3. Verificar la configuración
-
-Verifica que los contenedores estén corriendo correctamente:
-
-```bash
-docker compose ps
-docker compose logs -f web
-```
-
-## 🔐 Cómo funciona la autenticación JWT
-
-### Flujo de autenticación:
-
-1. **Usuario accede a una cita aprobada** → [/appointments/[id]/meet](src/app/appointments/[id]/meet/page.tsx)
-
-2. **Frontend solicita JWT token** → `GET /api/appointments/[id]/jitsi-token`
-   - Valida que el usuario sea PATIENT, DOCTOR o ADMIN
-   - Valida que la cita esté aprobada
-   - Valida el tiempo (15 min antes hasta 1 hora después)
-
-3. **Backend genera JWT token** usando [src/lib/jitsi-jwt.ts](src/lib/jitsi-jwt.ts):
-   ```javascript
-   {
-     "iss": "reuniones_utb",        // JWT_APP_ID
-     "aud": "reuniones_utb",         // JWT_APP_ID
-     "sub": "meet.checkthis.space",  // Tu dominio
-     "room": "appointment-123",      // Sala específica
-     "context": {
-       "user": {
-         "id": "user-id",
-         "name": "Juan Pérez",
-         "email": "juan@example.com",
-         "avatar": "https://..."
-       }
-     },
-     "moderator": true,              // true para DOCTOR/ADMIN
-     "exp": 1699123456               // 2 horas de expiración
-   }
-   ```
-
-4. **Frontend inicializa Jitsi** con el token JWT:
-   ```javascript
-   new JitsiMeetExternalAPI("meet.checkthis.space", {
-     roomName: "appointment-123",
-     jwt: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
-     // ... otras opciones
-   })
-   ```
-
-5. **Jitsi valida el token** usando `JWT_APP_SECRET`:
-   - Verifica la firma del token
-   - Verifica que `iss` esté en `JWT_ACCEPTED_ISSUERS`
-   - Verifica que `aud` esté en `JWT_ACCEPTED_AUDIENCES`
-   - Verifica que el token no haya expirado
-
-## 👥 Roles y permisos
-
-### DOCTOR y ADMIN (moderadores):
-- ✅ Pueden grabar la reunión
-- ✅ Pueden hacer streaming
-- ✅ Pueden expulsar participantes
-- ✅ Pueden silenciar a otros participantes
-- ✅ Pueden finalizar la reunión para todos
-
-### PATIENT (participantes):
-- ✅ Pueden unirse a la reunión
-- ✅ Pueden compartir audio/video
-- ✅ Pueden usar el chat
-- ❌ No pueden expulsar a otros
-- ❌ No pueden grabar
-
-## 🔑 Variables de entorno en tu aplicación
-
-Tu archivo [.env](.env) ya está configurado con:
-
-```env
-JITSI_DOMAIN="meet.checkthis.space"
-JITSI_APP_ID="reuniones_utb"
-JITSI_APP_SECRET="theystolemyfuckingmoney"
-JITSI_USE_JWT="true"
-```
-
-**⚠️ IMPORTANTE:**
-- `JITSI_APP_ID` debe coincidir con `JWT_APP_ID` en Jitsi
-- `JITSI_APP_SECRET` debe coincidir con `JWT_APP_SECRET` en Jitsi
-- Estos valores deben ser EXACTAMENTE iguales
-
-## 🧪 Testing
-
-### 1. Verificar que el servidor esté accesible:
-
-```bash
-curl https://meet.checkthis.space/
-```
-
-### 2. Crear una cita de prueba y probar el flujo completo:
-
-1. Crear una cita como PATIENT
-2. Aprobarla como DOCTOR
-3. Ambos usuarios intentar unirse a la videollamada
-4. Verificar que:
-   - El token JWT se genera correctamente
-   - Jitsi acepta el token
-   - Los permisos de moderador funcionan correctamente
-
-### 3. Verificar logs del backend:
-
-```bash
-npm run dev
-```
-
-Deberías ver en la consola:
-```
-🎥 Jitsi Meet:
-   Domain: meet.checkthis.space
-   App ID: ✅ Configurado
-   App Secret: ✅ Configurado
-   Use JWT: ✅ Habilitado
-```
-
-## 🐛 Troubleshooting
-
-### Problema: "No se pudo conectar con el servidor de videollamadas"
-
-**Solución:**
-- Verifica que `meet.checkthis.space` sea accesible desde el navegador
-- Verifica que el certificado SSL sea válido
-- Verifica que el script `https://meet.checkthis.space/external_api.js` cargue correctamente
-
-### Problema: "Invalid JWT token"
-
-**Solución:**
-1. Verifica que `JITSI_APP_ID` y `JWT_APP_ID` coincidan exactamente
-2. Verifica que `JITSI_APP_SECRET` y `JWT_APP_SECRET` coincidan exactamente
-3. Verifica que `JWT_ACCEPTED_ISSUERS` incluya el valor de `JWT_APP_ID`
-4. Verifica que `JWT_ACCEPTED_AUDIENCES` incluya el valor de `JWT_APP_ID`
-5. Revisa los logs de Jitsi: `docker compose logs -f prosody`
-
-### Problema: Token expirado
-
-**Solución:**
-- El token expira después de 2 horas por defecto
-- Si necesitas más tiempo, modifica el parámetro `expiresInSeconds` en [src/app/api/appointments/[id]/jitsi-token/route.ts:146](src/app/api/appointments/[id]/jitsi-token/route.ts#L146)
-
-### Problema: Usuario no tiene permisos de moderador
-
-**Solución:**
-- Solo usuarios con rol `DOCTOR` o `ADMIN` son moderadores
-- Verifica el rol del usuario en la base de datos
-- El campo `isModerator` se calcula en [src/app/api/appointments/[id]/jitsi-token/route.ts:138](src/app/api/appointments/[id]/jitsi-token/route.ts#L138)
-
-## 📚 Referencias
-
-- [Jitsi JWT Authentication](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/#authentication)
-- [JWT.io Debugger](https://jwt.io/) - Para debugging de tokens
-- [Jitsi Meet API](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-iframe)
-
-## 🔒 Seguridad
-
-**IMPORTANTE:** En producción:
-
-1. ✅ Cambia `JWT_APP_SECRET` por un valor secreto y seguro
-2. ✅ Usa HTTPS para todo (tu dominio y tu app)
-3. ✅ No expongas `JITSI_APP_SECRET` en el frontend
-4. ✅ Los tokens se generan en el backend (ya implementado)
-5. ✅ Configura `JWT_ACCEPTED_ISSUERS` y `JWT_ACCEPTED_AUDIENCES`
-
-## 🎯 Próximos pasos opcionales
-
-### Configuración adicional de Jitsi:
-
-- **Grabar reuniones:** Configurar Jibri para grabación
-- **Transcripción:** Configurar Jigasi para transcripción
-- **TURN server:** Para mejorar conectividad detrás de firewalls
-- **Límites de sala:** Limitar número de participantes por sala
-- **Branding:** Personalizar logo y colores de Jitsi
-
-### Mejoras en la aplicación:
-
-- Agregar notificaciones cuando un participante se une
-- Guardar duración de la videollamada en la base de datos
-- Agregar grabación automática para citas específicas
-- Implementar espera virtual (waiting room)

+ 0 - 62
docs/PSYCHOLOGICAL_CHAT_IMPLEMENTATION.md

@@ -1,62 +0,0 @@
-# Implementación Chat Psicológico
-
-## Objetivo
-Agregar chat de apoyo psicológico separado del chat médico, sin límite de mensajes y con opción de terminar conversación.
-
-## Diferencias con Chat Médico
-- ❌ Sin límite de 10 mensajes
-- ✅ Usuario termina conversación cuando quiera
-- 💭 Prompt enfocado en apoyo emocional
-- 🔒 Disclaimer sobre no ser terapia profesional
-
----
-
-## Tareas
-
-### 1. Base de Datos
-- [x] Agregar enum `ChatType` (MEDICAL, PSYCHOLOGICAL)
-- [x] Agregar campo `chatType` al modelo Conversation
-- [x] Crear y ejecutar migración
-
-### 2. Página de Selección
-- [x] Crear `/chat/select` con AuthenticatedLayout
-- [x] Diseño con componentes UI reutilizables (Card)
-- [x] Dos opciones claras con descripción
-- [x] Redireccionamiento según selección
-- [x] Integración con sidebar y estilo consistente
-
-### 3. Backend/API
-- [x] Modificar `/api/chat` para aceptar `chatType`
-- [x] Prompt del sistema para chat psicológico
-- [x] Remover límite de mensajes para tipo PSYCHOLOGICAL
-- [ ] Endpoint para terminar conversación manualmente
-
-### 4. Frontend
-- [x] Adaptar `ImprovedChatInterface.tsx` para ambos tipos
-- [x] Modificar `useChat.ts` para manejar tipos
-- [x] Historial separado por tipo de chat (localStorage)
-- [x] Botón "Terminar conversación" en chat psicológico
-- [x] Modificar header para mostrar tipo de chat
-- [x] Iconos y colores diferenciados según tipo
-
-### 5. Seguridad y Ética
-- [x] Disclaimer claro al inicio (en página de selección)
-- [x] Disclaimer en chat psicológico con info de limitaciones
-- [x] Detección de crisis en prompt (keywords: suicidio, autolesión)
-- [x] Números de emergencia en disclaimer
-- [x] Banner dinámico con recursos de ayuda inmediata si se detecta crisis
-- [x] Múltiples líneas de emergencia (Cruz Roja, Policía, Línea de Vida)
-
-### 6. Testing
-- [ ] Crear conversación psicológica
-- [ ] Verificar sin límite de mensajes
-- [ ] Probar terminación manual
-- [ ] Validar separación de historiales
-- [ ] Test de crisis detection (respuesta del LLM con crisisDetected: true)
-
----
-
-## Notas Técnicas
-- Reutilizar componentes existentes de chat médico
-- Mismo modelo de BD, solo agregar discriminante `chatType`
-- Prompts almacenados en código o variables de entorno

+ 0 - 160
docs/REPORTID_REMOVAL_SUMMARY.md

@@ -1,160 +0,0 @@
-# Resumen de Cambios: Eliminación del Campo `reportId`
-
-**Fecha**: 16 de octubre de 2025  
-**Estado**: ✅ COMPLETADO EXITOSAMENTE
-
----
-
-## 🎯 Objetivo Cumplido
-
-Eliminar el campo redundante `reportId` del modelo `Appointment` y consolidar toda la lógica para usar únicamente `recordId` con su relación apropiada a la tabla `Record`.
-
----
-
-## ✅ Cambios Implementados
-
-### 📋 Fase 1: Refactor de Nomenclatura (Sin Breaking Changes)
-
-#### Componentes Actualizados:
-1. **`src/components/appointments/ReportViewer.tsx`**
-   - ✅ Prop `reportId` → `recordId`
-   - ✅ Actualizado uso en nombre de descarga de archivo
-
-2. **`src/app/appointments/[id]/page.tsx`**
-   - ✅ Prop `reportId={appointment.record.id}` → `recordId={appointment.record.id}`
-
-3. **`src/components/chatbot/AppointmentModalFromChat.tsx`**
-   - ✅ Prop `reportId?: string` → `recordId?: string`
-   - ✅ Actualizado comentario para clarificar que es el ID del Record
-   - ✅ Body del POST ya enviaba `recordId` correctamente
-
-#### Hooks Actualizados:
-4. **`src/hooks/useChat.ts`**
-   - ✅ Parámetro `onSuccess: (reportId: string)` → `onSuccess: (recordId: string)`
-   - ✅ Variable `const reportId = data.id` → `const recordId = data.id`
-   - ✅ Comentarios actualizados para clarificar
-
-5. **`src/components/chatbot/ChatInterface.tsx`**
-   - ✅ State `appointmentReportId` → `appointmentRecordId`
-   - ✅ Función callback actualizada para usar `recordId`
-   - ✅ Prop del modal actualizada
-
-### 🔧 Fase 2: Limpieza del Backend
-
-6. **`src/app/api/appointments/route.ts`**
-   - ✅ Eliminado `reportId` del destructuring del body
-   - ✅ Eliminado `...(reportId && { reportId })` del spread en Prisma create
-   - ✅ Solo se usa `recordId` con su relación apropiada
-
-7. **`src/types/appointments.ts`**
-   - ✅ Eliminado `reportId: string | null` del interface `Appointment`
-   - ✅ Mantenido `recordId` con su objeto `record` relacionado
-
-### 🗄️ Fase 3: Migración de Base de Datos
-
-8. **`prisma/schema.prisma`**
-   - ✅ Eliminada línea 78: `reportId String?`
-   - ✅ Mantenida la relación correcta con `recordId` y `record`
-
-9. **Migración Aplicada**
-   - ✅ Nombre: `20251016172344_remove_redundant_reportid_field`
-   - ✅ Acción: DROP COLUMN `reportId` de tabla `Appointment`
-   - ✅ Estado: Aplicada exitosamente
-   - ✅ Sin pérdida de datos (columna estaba vacía)
-
----
-
-## 📊 Resultados de Verificación
-
-### Estado Antes del Cambio:
-```
-Total de citas: 4
-Con reportId: 0 (0.0%)
-Con recordId: 0 (0.0%)
-Huérfanas (reportId sin recordId): 0
-```
-
-### Estado Después del Cambio:
-- ✅ Campo `reportId` eliminado del schema
-- ✅ 0 errores de compilación TypeScript
-- ✅ 0 errores de lint
-- ✅ Servidor de desarrollo inicia correctamente
-- ✅ Prisma Client regenerado con éxito
-
----
-
-## 🔍 Archivos Modificados
-
-Total: **9 archivos**
-
-### Frontend (5 archivos):
-- `src/components/appointments/ReportViewer.tsx`
-- `src/app/appointments/[id]/page.tsx`
-- `src/components/chatbot/AppointmentModalFromChat.tsx`
-- `src/components/chatbot/ChatInterface.tsx`
-- `src/hooks/useChat.ts`
-
-### Backend (2 archivos):
-- `src/app/api/appointments/route.ts`
-- `src/types/appointments.ts`
-
-### Database (2 archivos):
-- `prisma/schema.prisma`
-- `prisma/migrations/20251016172344_remove_redundant_reportid_field/migration.sql`
-
----
-
-## 💡 Beneficios Obtenidos
-
-1. ✅ **Claridad del Código**: Solo un campo (`recordId`) para referenciar reportes médicos
-2. ✅ **Consistencia**: Uso correcto de relaciones Prisma en toda la aplicación
-3. ✅ **Mantenibilidad**: Menos confusión para futuros desarrolladores
-4. ✅ **Type Safety**: TypeScript más preciso y sin campos redundantes
-5. ✅ **Performance**: Un campo menos en queries (mínimo pero existente)
-6. ✅ **Base de Datos Limpia**: Schema refleja correctamente el modelo de datos
-
----
-
-## 🎉 Funcionalidad Preservada
-
-### ✅ Flujo de Creación de Citas desde Chatbot:
-1. Usuario conversa con el chatbot médico
-2. Sistema genera reporte y lo guarda como `Record`
-3. Modal de cita recibe el `recordId` del reporte
-4. Cita se crea con `recordId` asociado
-5. Doctor puede ver el reporte completo en el detalle de la cita
-
-### ✅ Visualización de Reportes:
-- Componente `ReportViewer` funciona correctamente
-- Muestra contenido completo del reporte
-- Permite copiar y descargar
-- Diseño diferenciado de las notas de consulta
-
----
-
-## 🚀 Próximos Pasos Sugeridos
-
-1. **Crear cita de prueba desde chatbot** para verificar el flujo completo
-2. **Verificar como doctor** que se muestra el reporte asociado
-3. **Actualizar documentación** si es necesario
-4. **Considerar agregar el reporte en la sala de videollamada** (próxima mejora)
-
----
-
-## 📝 Notas Técnicas
-
-### Historia del Campo Eliminado:
-- **8 Oct 2025**: Sistema creado con `recordId` (correcto)
-- **13 Oct 2025**: Campo `reportId` agregado por error (sin relación)
-- **16 Oct 2025**: Campo redundante identificado y eliminado
-
-### Sin Riesgos:
-- No había datos en la columna `reportId`
-- El código nunca usó `reportId` para queries
-- Todas las citas creadas usan `recordId` correctamente
-
----
-
-**Cambio implementado por**: GitHub Copilot  
-**Análisis de impacto**: Ver `docs/IMPACT_ANALYSIS_REPORTID_REMOVAL.md`  
-**Script de verificación**: `scripts/check-reportid-usage.ts` (utilizado para análisis)

+ 0 - 175
docs/UTB_API_MIGRATION.md

@@ -1,175 +0,0 @@
-# Migración a Autenticación API UTB
-
-## Estado: ✅ Completado
-
----
-
-## 1. Variables de Entorno
-
-### Archivo: `.env`
-
-- [x] Agregar `UTB_API_URL=https://sai.utb.edu.ec/v2/ws/auth/login`
-- [x] Agregar `UTB_API_APP_ID=6d834518ee8832b9455d3887aa0dc1a369bccee2d017812994ab066faae42067`
-- [x] Agregar `UTB_API_APP_TOKEN=c9449f3452c6645081282a01240c0679eb1ca1e440eebf322eb23d5f2260c2d4`
-
----
-
-## 2. Configuración
-
-### Archivo: `src/lib/config.ts`
-
-- [x] Agregar sección `utbApi`
-- [x] Agregar validación de credenciales en logger
-
----
-
-## 3. Cliente API UTB
-
-### Archivo: `src/lib/utb-api.ts` (nuevo)
-
-- [x] Crear función `authenticateUser(username: string, password: string)`
-- [x] Configurar headers: `X-App-Id`, `X-App-Token`, `Content-Type`
-- [x] Manejo de respuesta exitosa (200)
-- [x] Manejo de errores (400, 401, 405)
-- [x] Retornar interface `UTBAuthResponse`
-
----
-
-## 4. Schema Prisma
-
-### Archivo: `prisma/schema.prisma`
-
-- [x] Agregar campo `identificacion String? @unique` al modelo `User`
-- [x] Agregar campo `isExternalAuth Boolean @default(false)` al modelo `User`
-- [x] Modificar `email String? @unique` (hacerlo opcional)
-- [x] Modificar `password String?` (hacerlo opcional)
-
----
-
-## 5. Migración Base de Datos
-
-- [x] Ejecutar `npx prisma migrate dev --name add_utb_fields`
-- [x] Verificar que la migración se aplicó correctamente
-
----
-
-## 6. Lógica de Autenticación
-
-### Archivo: `src/lib/auth.ts`
-
-- [x] Importar cliente UTB API
-- [x] Modificar `authorize()`:
-  - [x] Validar contra API UTB (no bcrypt)
-  - [x] Buscar usuario por `identificacion` o `username`
-  - [x] Si no existe, crear usuario nuevo
-  - [x] Mapear datos de API a modelo User
-  - [x] Mapear roles: ESTUDIANTE→PATIENT, DOCENTE→DOCTOR, ADMINISTRADOR→ADMIN
-  - [x] Si existe, actualizar datos desde API
-
----
-
-## 7. Formulario de Login
-
-### Archivo: `src/app/auth/login/page.tsx`
-
-- [x] Cambiar campo `email` por `username`
-- [x] Actualizar labels y placeholders
-- [x] Actualizar mensaje informativo
-
----
-
-## 8. API Account Update
-
-### Archivo: `src/app/api/account/update/route.ts`
-
-- [x] Prevenir cambio de contraseña para usuarios UTB
-- [x] Validar que `password` no sea null antes de bcrypt.compare
-
----
-
-## 9. Tipos TypeScript
-
-### Archivo: `src/types/utb-api.d.ts` (nuevo)
-
-- [x] Definir `UTBAuthResponse`
-- [x] Definir `UTBUser`
-- [x] Definir `UTBErrorResponse`
-
----
-
-## 10. Build y Pruebas
-
-- [x] Verificar que el proyecto compila sin errores
-- [x] Probar login con usuario estudiante
-- [x] Probar login con usuario docente
-- [x] Verificar creación de usuario en DB
-- [x] Verificar actualización de datos existentes
-- [x] Probar manejo de credenciales inválidas
-
----
-
-## 11. UI de Cuenta
-
-### Archivos: `src/components/account/*.tsx`, `src/app/account/page.tsx`
-
-- [x] Banner informativo para usuarios UTB
-- [x] Mostrar `identificacion` (solo lectura)
-- [x] Bloquear campos nombre/apellido para usuarios UTB
-- [x] Email opcional y editable
-- [x] Deshabilitar cambio de contraseña para usuarios UTB
-- [x] Link a SAI UTB para cambios
-
----
-
-## Estado Final: ✅ COMPLETADO Y SIMPLIFICADO
-
-**Migración exitosa a autenticación API UTB.**
-
-### Simplificación UTB-Only (100% dependencia API)
-
-**Decisión:** El sistema ya no soporta usuarios locales. Todos los usuarios deben autenticarse mediante la API de UTB.
-
-**Cambios de simplificación realizados:**
-
-1. **Componentes de cuenta simplificados:**
-   - `PersonalInfoSection.tsx`: Siempre muestra banner UTB, campos nombre/apellido bloqueados
-   - `PasswordChangeSection.tsx`: Solo muestra mensaje de gestión por UTB, sin campos de contraseña
-
-2. **API de actualización simplificada:**
-   - Eliminados checks de `isExternalAuth`
-   - Solo permite actualizar: email y profileImage
-   - Bloquea cualquier intento de cambio de contraseña
-   - Removidos imports y lógica de bcrypt no utilizados
-
-3. **Props simplificadas:**
-   - Eliminado prop `isExternalAuth` de componentes de cuenta
-   - Props de contraseña en `PasswordChangeSection` marcadas como opcionales por compatibilidad
-
-**Estado actual:**
-- ✅ Autenticación mediante API externa
-- ✅ Sincronización automática de datos
-- ✅ Protección de campos gestionados por UTB
-- ✅ UI simplificada sin lógica condicional
-- ✅ Build exitoso sin errores
-- ✅ Código más limpio y mantenible
-
-**Campos editables:**
-- ✅ Email (opcional)
-- ✅ Foto de perfil
-
-**Campos bloqueados (gestionados por UTB):**
-- 🔒 Nombre
-- 🔒 Apellido  
-- 🔒 Fecha de nacimiento
-- 🔒 Contraseña
-
----
-
-## Notas Importantes
-
-- **Email opcional:** Los usuarios pueden agregarlo después en `/account`
-- **Password:** Se guarda vacío para usuarios UTB (no se usa)
-- **Identificación:** Campo único que vincula con API UTB
-- **Roles:** Mapeo automático según `tipo` de la API
-- **Reportes:** Se mantienen vinculados por `userId` interno
-- **Sin usuarios locales:** Ya no se soporta autenticación local, solo UTB

+ 0 - 68
guides/CHATBOT.md

@@ -1,68 +0,0 @@
-# Componentes del Chatbot
-
-Esta carpeta contiene todos los componentes relacionados con la interfaz del chatbot médico, organizados de manera modular para facilitar el mantenimiento y la escalabilidad.
-
-## Estructura de Archivos
-
-### Componentes Principales
-
-- **`ChatInterface.tsx`** - Componente principal que orquesta todos los demás componentes
-- **`types.ts`** - Definiciones de tipos TypeScript para el chatbot
-
-### Componentes de UI
-
-- **`ChatHeader.tsx`** - Header con información de estado y controles
-- **`WelcomeMessage.tsx`** - Mensaje de bienvenida inicial
-- **`SuggestedPrompts.tsx`** - Sugerencias de prompts rápidos
-- **`ChatMessages.tsx`** - Contenedor de mensajes con scroll automático
-- **`ChatMessage.tsx`** - Componente individual para cada mensaje
-- **`ChatInput.tsx`** - Área de entrada de mensajes
-- **`CompletedState.tsx`** - Estado cuando la consulta está completada
-- **`ResetButton.tsx`** - Botón para reiniciar la consulta
-
-### Modales
-
-- **`ReportModal.tsx`** - Modal para mostrar el reporte generado
-- **`ResetConfirmationModal.tsx`** - Modal de confirmación para reset
-
-### Utilidades
-
-- **`MessageRenderer.tsx`** - Funciones para renderizar contenido con markdown básico
-
-## Hooks Relacionados
-
-Los hooks se encuentran en `src/hooks/`:
-
-- **`useChat.ts`** - Hook principal que maneja toda la lógica del chat
-- **`useChatEffects.ts`** - Hook para efectos secundarios como toasts
-
-## Uso
-
-```tsx
-import { ChatInterface } from "@/components/chatbot";
-
-export default function MyPage() {
-  return <ChatInterface />;
-}
-```
-
-## Características
-
-- ✅ Componentes modulares y reutilizables
-- ✅ Separación clara de responsabilidades
-- ✅ Hooks personalizados para la lógica de negocio
-- ✅ Tipos TypeScript bien definidos
-- ✅ Fácil mantenimiento y escalabilidad
-- ✅ Renderizado de markdown básico
-- ✅ Streaming de mensajes
-- ✅ Gestión de estado con localStorage
-- ✅ Generación automática de reportes
-
-## Mejoras Implementadas
-
-1. **Modularización**: El componente original de 868 líneas se dividió en múltiples componentes más pequeños
-2. **Hooks Personalizados**: La lógica de negocio se extrajo a hooks reutilizables
-3. **Tipos TypeScript**: Definiciones claras de tipos para mejor desarrollo
-4. **Separación de Responsabilidades**: Cada componente tiene una responsabilidad específica
-5. **Mejor Mantenibilidad**: Código más fácil de entender y modificar
-6. **Escalabilidad**: Fácil agregar nuevas características sin afectar otros componentes 

+ 0 - 194
guides/MIGRATION_GUIDE.md

@@ -1,194 +0,0 @@
-# Guía de Migración a PostgreSQL
-
-## 🎯 Objetivo
-
-Migrar la aplicación de SQLite a PostgreSQL para mejor rendimiento y escalabilidad.
-
-## 📋 Requisitos Previos
-
-### 1. Instalar PostgreSQL en Windows
-
-#### Opción A: Instalador Oficial
-1. Descarga PostgreSQL desde [https://www.postgresql.org/download/windows/](https://www.postgresql.org/download/windows/)
-2. Ejecuta el instalador
-3. Configura la contraseña del usuario `postgres`
-4. Instala en el puerto por defecto (5432)
-
-#### Opción B: Usando Chocolatey
-```bash
-choco install postgresql
-```
-
-### 2. Crear la Base de Datos
-
-```bash
-# Conectar a PostgreSQL
-psql -U postgres
-
-# Crear la base de datos
-CREATE DATABASE ani_assistant;
-
-# Verificar que se creó
-\l
-
-# Salir
-\q
-```
-
-## 🔧 Configuración
-
-### 1. Actualizar Variables de Entorno
-
-Edita tu archivo `.env`:
-
-```env
-# Cambiar de SQLite a PostgreSQL
-DATABASE_URL="postgresql://postgres:tu-password@localhost:5432/ani_assistant"
-```
-
-### 2. Verificar Configuración
-
-```bash
-npm run check-env
-```
-
-## 🚀 Proceso de Migración
-
-### Paso 1: Generar Migraciones
-
-```bash
-# Generar migración inicial
-npm run db:migrate
-```
-
-### Paso 2: Aplicar Migraciones
-
-```bash
-# Aplicar las migraciones a PostgreSQL
-npm run db:push
-```
-
-### Paso 3: Configurar Usuarios
-
-```bash
-# Crear usuarios de prueba
-npm run db:setup
-```
-
-### Paso 4: Cargar Datos (Opcional)
-
-```bash
-# Cargar datos de ejemplo
-npm run db:seed
-```
-
-## 🔍 Verificación
-
-### 1. Verificar Conexión
-
-```bash
-npm run check-env
-```
-
-### 2. Probar la Aplicación
-
-```bash
-npm run dev
-```
-
-### 3. Verificar en PostgreSQL
-
-```bash
-psql -U postgres -d ani_assistant
-
-# Ver tablas
-\dt
-
-# Ver usuarios
-SELECT name, lastname, username, email, role FROM "User";
-
-# Salir
-\q
-```
-
-## 🆘 Solución de Problemas
-
-### Error: "connection refused"
-- Verificar que PostgreSQL esté ejecutándose
-- Verificar el puerto (5432)
-- Verificar credenciales en DATABASE_URL
-
-### Error: "database does not exist"
-```bash
-# Crear la base de datos
-psql -U postgres
-CREATE DATABASE ani_assistant;
-\q
-```
-
-### Error: "permission denied"
-- Verificar que el usuario tenga permisos
-- Verificar la contraseña en DATABASE_URL
-
-### Error: "relation does not exist"
-```bash
-# Regenerar el cliente de Prisma
-npm run db:generate
-
-# Aplicar migraciones
-npm run db:push
-```
-
-## 📊 Diferencias con SQLite
-
-### Ventajas de PostgreSQL
-- ✅ Mejor rendimiento con múltiples usuarios
-- ✅ Transacciones ACID completas
-- ✅ Mejor escalabilidad
-- ✅ Más tipos de datos
-- ✅ Mejor soporte para consultas complejas
-
-### Consideraciones
-- ⚠️ Requiere instalación y configuración
-- ⚠️ Más recursos del sistema
-- ⚠️ Configuración de red para producción
-
-## 🔄 Rollback (Si es necesario)
-
-Si necesitas volver a SQLite:
-
-1. Cambiar DATABASE_URL en `.env`:
-```env
-DATABASE_URL="file:./dev.db"
-```
-
-2. Cambiar provider en `prisma/schema.prisma`:
-```prisma
-datasource db {
-  provider = "sqlite"
-  url      = env("DATABASE_URL")
-}
-```
-
-3. Regenerar y aplicar:
-```bash
-npm run db:generate
-npm run db:push
-npm run db:setup
-```
-
-## 📝 Notas Importantes
-
-- **Backup**: Siempre haz backup de tus datos antes de migrar
-- **Testing**: Prueba en un entorno de desarrollo primero
-- **Performance**: PostgreSQL puede ser más lento en desarrollo local
-- **Storage**: Las imágenes se guardan en `/uploads/photos_profile/`
-
-## 🎉 ¡Migración Completada!
-
-Una vez completada la migración, tu aplicación estará usando PostgreSQL con todas las nuevas características:
-
-- ✅ Usernames únicos generados automáticamente
-- ✅ Separación de nombre y apellido
-- ✅ Almacenamiento de imágenes en archivos
-- ✅ Mejor rendimiento y escalabilidad 

+ 0 - 77
guides/QUICK_START.md

@@ -1,77 +0,0 @@
-# Guía Rápida de Instalación
-
-## 🚀 Instalación en 5 Pasos
-
-### 1. Clonar e Instalar
-```bash
-git clone https://github.com/GeoShaPoH/ani-assistant
-cd ani-assistant
-npm install
-```
-
-### 2. Instalar PostgreSQL
-**Windows:**
-- Descarga desde [https://www.postgresql.org/download/windows/](https://www.postgresql.org/download/windows/)
-- O usa: `choco install postgresql`
-
-**Crear base de datos:**
-```bash
-psql -U postgres
-CREATE DATABASE ani_assistant;
-\q
-```
-
-### 3. Configurar Variables
-```bash
-cp env.sample.txt .env
-```
-
-Editar `.env`:
-```env
-NEXTAUTH_URL="http://localhost:3000"
-NEXTAUTH_SECRET="tu-clave-secreta-aqui"
-DATABASE_URL="postgresql://postgres:tu-password@localhost:5432/ani_assistant"
-OPENROUTER_API_KEY="tu-api-key-de-openrouter"
-```
-
-### 4. Configurar Base de Datos
-```bash
-npm run check-env
-npm run verify-setup
-npm run db:generate
-npm run db:push
-npm run db:setup
-```
-
-### 5. Ejecutar
-```bash
-npm run dev
-```
-
-Abrir: http://localhost:3000
-
-## 🔑 Credenciales de Prueba
-
-- **Doctor**: `admin@ani-assistant.com` / `admin123`
-- **Paciente**: `patient@ani-assistant.com` / `patient123`
-
-## ⚡ Comandos Útiles
-
-```bash
-npm run check-env      # Verificar configuración
-npm run verify-setup   # Verificar directorios y configuración
-npm run db:studio      # Interfaz de base de datos
-npm run db:seed        # Cargar datos de ejemplo
-```
-
-## 🆘 Solución de Problemas
-
-### Error de conexión a PostgreSQL
-- Verificar que PostgreSQL esté ejecutándose
-- Verificar credenciales en DATABASE_URL
-- Crear la base de datos: `CREATE DATABASE ani_assistant;`
-
-### Error de variables de entorno
-- Ejecutar: `npm run check-env`
-- Verificar que el archivo `.env` existe
-- Configurar todas las variables requeridas