## CU-04-008: Estudiante reserva sesión en vivo

**Fecha:** 13 de marzo de 2026  
**Caso de uso:** CU-04-008 – Estudiante reserva sesión en vivo  
**Ámbito:** Dashboard del estudiante + vista del curso + acceso/join a BigBlueButton (BBB)

---

## Objetivo del documento

Este documento complementa la especificación funcional del caso de uso **CU-04-008: Estudiante reserva sesión en vivo** y se enfoca en:

- **Dónde** ve el estudiante sus sesiones en vivo (dashboard y curso).
- **Cómo** reserva/cancela una reserva.
- **Cuándo** se habilita el enlace de “Unirse” (regla de tiempo / inicio temprano por el instructor).
- **Qué archivos** se modificaron / agregaron para soportar el flujo.

---

## Rutas y pantallas

### Opción B (Dashboard): “Mis Sesiones”

- **Ruta**: `GET /student/live-sessions`  
- **Nombre de ruta**: `student.live-sessions`
- **Pantalla**: lista general de sesiones en vivo asociadas a cursos en los que el estudiante está inscrito.

### Join del estudiante (BBB)

- **Ruta**: `GET /student/live-sessions/{liveSession}/join`  
- **Nombre de ruta**: `student.live-sessions.join`
- **Acceso**:
  - Debe estar autenticado.
  - Debe estar **inscrito en el curso** de la sesión.
  - Debe tener una **reserva activa** (`session_bookings` sin `cancelled_at`).

### Opción A (Curso): pestaña “Sesiones en vivo”

- **Pantalla**: `GET /course/{slug}` (vista del curso)
- **Componente Livewire**: `App\Livewire\Public\CourseDetail`
- **Comportamiento**: muestra **solo las live sessions del curso actual**, reutilizando la misma lógica visual de “cards” y CTA (Reservar / Unirse / Cancelar).

---

## Reglas de habilitación del enlace “Unirse”

El botón/enlace para unirse a BBB se considera disponible cuando:

- **La sesión está en estado `live`** (el instructor la inició antes), **o**
- **Ya es la hora de inicio**: `now() >= scheduled_at`.

Si aún falta tiempo y el instructor no la ha iniciado, el botón aparece **deshabilitado**.

---

## Datos que se muestran por sesión

En ambas vistas (general y por curso), cada sesión muestra:

- **Título**
- **Curso**
- **Fecha y hora** (formato `d/m/Y` y `H:i`)
- **Duración**
- **Instructor**
- **Tipo** (`Uno a Uno` / `Grupal`)
- **Cupos** (`{reservas_confirmadas} de {max_participants} cupos`)
- **Estado** (Programada / En Vivo / Completada / Cancelada)
- **Precio** (Gratis o monto)

---

## Archivos agregados y modificados

### Rutas / navegación

- **Modificado**: `routes/tenant.php`
  - Agrega:
    - `student.live-sessions` (`/student/live-sessions`)
    - `student.live-sessions.join` (`/student/live-sessions/{liveSession}/join`)
  - Ajuste: en entorno de **testing**, se omite el middleware de tenancy para poder ejecutar tests de forma aislada.
  - Mejora: `BigBlueButtonService` se resuelve vía contenedor (`app(...)`) para permitir mocking en tests.

- **Modificado**: `resources/views/components/layouts/app/sidebar.blade.php`
  - En el sidebar del estudiante, el ítem **“Mis Sesiones”** ahora apunta a `student.live-sessions`.

- **Modificado**: `resources/views/livewire/student/dashboard.blade.php`
  - El CTA **“Ver todas”** en “Próximas Sesiones en Vivo” ahora redirige a `student.live-sessions`.

### UI estudiante (pantalla nueva)

- **Agregado**: `resources/views/livewire/student/live-sessions.blade.php`
  - Pantalla Volt que lista sesiones por pestañas:
    - **Próximas** / **Historial**
  - Acciones:
    - `reserve(liveSessionId)`
    - `cancelReservation(liveSessionId)`
  - CTA:
    - **Reservar** (si hay cupos)
    - **Unirse** (si está reservado + regla de habilitación)
    - **Cancelar** (si la reserva permite cancelación)

### Vista del curso

- **Modificado**: `app/Livewire/Public/CourseDetail.php`
  - Carga `liveSessions` del curso (con `instructor` + conteo de reservas confirmadas).
  - Agrega acciones:
    - `reserveLiveSession()`
    - `cancelLiveSessionReservation()`
    - `myLiveSessionBookingIds` (helper de UI)

- **Modificado**: `resources/views/livewire/public/course-detail.blade.php`
  - Implementa el tab **“Sesiones en vivo”** con cards + acciones reales (Reservar / Unirse / Cancelar).

### Ajustes para cupos y BBB

- **Modificado**: `app/Livewire/Instructor/LiveSessions/Create.php`
  - `max_participants` se interpreta como **cupos para estudiantes**.
  - Para `one_to_one` se fija en **1 cupo**.
  - En la creación de la reunión BBB, `maxParticipants` se envía como `max_participants + 1` (incluye instructor).

---

## Tests (Pest)

- **Agregado**: `tests/Feature/StudentLiveSessionsTest.php`
  - Cobertura:
    - renderizado de sesiones para cursos inscritos
    - reservar sesión
    - bloqueo de join sin reserva
    - bloqueo de join si es antes de la hora
    - join cuando ya es la hora (mock de BBB)

---

## Notas técnicas relevantes

- Para habilitar tests en SQLite se agregaron/ajustaron:
  - `database/testing.sqlite`
  - `config/database.php` (config específica para `APP_ENV=testing`)
  - `tests/TestCase.php` para ejecutar migraciones tenant en `setUp()`
  - Los triggers SQL (tenant) se omiten en SQLite por incompatibilidad.

---

## Pendientes / próximos incrementos recomendados

- Mostrar explícitamente:
  - **Estado “Cupo lleno / lista de espera”** (si se implementa waitlist real).
  - **Zona horaria del estudiante** si el proyecto ya maneja tz por usuario.
- Agregar un “Calendario” (Opción C) si se decide implementarlo como vista adicional.

---

## Resumen técnico mejorado (qué se tocó y por qué) 🧱

### Archivos nuevos

- `resources/views/livewire/student/live-sessions.blade.php`  
  **Por qué**: nueva pantalla “Mis Sesiones” para que el estudiante vea en un solo lugar todas las sesiones de todos los cursos, con:
  - pestañas Próximas / Historial,
  - acciones de **Reservar / Cancelar / Unirse**,
  - misma lógica de habilitación del botón “Unirse” que en la pestaña del curso.

- `tests/Feature/StudentLiveSessionsTest.php`  
  **Por qué**: base para automatizar el flujo principal del estudiante:
  - ver sesiones disponibles,
  - reservar,
  - validar restricciones de join.

### Archivos modificados (núcleo del CU-04-008)

- `routes/tenant.php`  
  - Se agregan las rutas:
    - `student.live-sessions` (`/student/live-sessions`)
    - `student.live-sessions.join` (`/student/live-sessions/{liveSession}/join`)  
  - **Motivo**: soportar las opciones A y B del caso de uso (pestaña del curso + “Mis Sesiones”) y centralizar la lógica de join del estudiante (inscripción, reserva activa, horario).

- `resources/views/components/layouts/app/sidebar.blade.php`  
  - “Mis Sesiones” del estudiante apunta ahora a `route('student.live-sessions')`.  
  - **Motivo**: acceso directo desde el dashboard a la vista general de sesiones.

- `resources/views/livewire/student/dashboard.blade.php`  
  - El link “Ver todas →” en “Próximas Sesiones en Vivo” redirige a `student.live-sessions`.  
  - **Motivo**: completar el UX: del resumen a la lista completa.

- `app/Livewire/Public/CourseDetail.php`  
  - Carga `liveSessions` del curso con `instructor` y conteo de reservas.
  - Agrega métodos para **reservar/cancelar** sesiones y conocer qué sesiones ya tiene reservadas el usuario.  
  - **Motivo**: permitir que, dentro del curso, el estudiante pueda reservar / cancelar / unirse sin abandonar la vista del curso.

- `resources/views/livewire/public/course-detail.blade.php`  
  - Implementa la pestaña **“Sesiones en vivo”** con cards que muestran:
    - título, instructor, fecha/hora, tipo, cupos, precio, estado,
    - botones de Reservar / Unirse / Cancelar según las reglas de negocio.  
  - **Motivo**: materializar la opción A del CU: ver y gestionar las sesiones **específicas de un curso**.

- `app/Livewire/Instructor/LiveSessions/Create.php`  
  - `max_participants` se trata como cupos de estudiantes.
  - Para `one_to_one` se fuerza a 1 → 1 estudiante.
  - En la llamada a BBB se envía `maxParticipants = max_participants + 1` para contar también al instructor.  
  - **Motivo**: que lo que el instructor configura como cupos coincida con lo que ve el estudiante y con el límite en BBB.

### Archivos modificados (soporte/infraestructura)

- `database/factories/CourseFactory.php`  
  - Genera cursos válidos (instructor, slug, flags de publicación).  
  - **Motivo**: facilitar tests y seeds internos; no afecta lógica de producción.

- `database/factories/LiveSessionFactory.php`  
  - Crea sesiones con curso, instructor, horario futuro, tipo y cupos.  
  - **Motivo**: poder levantar rápidamente escenarios de sesiones en vivo en pruebas.

- `database/factories/CourseEnrollmentFactory.php`  
  - Crea inscripciones mínimas (course_id, user_id, timestamps).  
  - **Motivo**: montar estados de “estudiante inscrito” sin repetir código.

- `tests/Feature/InstructorLiveSessionJoinTest.php`  
  - Se ajusta al uso de `BigBlueButtonService` vía contenedor.  
  - **Motivo**: mantener vigente el flujo CU-03-006 (instructor inicia sesión en vivo) después de los ajustes.

- `app/Filament/Resources/PlanResource/Schemas/PlanForm.php`  
- `app/Filament/Resources/PlanResource/Tables/PlansTable.php`  
- `app/Filament/Resources/TenantResource/Tables/TenantsTable.php`  
  - Solo se corrigieron namespaces (`…\Plans\…` → `…\PlanResource\…`, `…\Tenants\…` → `…\TenantResource\…`).  
  - **Motivo**: evitar errores de “Cannot redeclare class …” al cargar Filament. No cambian lógica de negocio.

---

## Flujo de trabajo resumido 🧭

### Estudiante

1. **Descubre sesiones:**
   - Desde `/student` ve “Próximas Sesiones en Vivo”.
   - Desde el sidebar o ese bloque entra a **“Mis Sesiones”** (`/student/live-sessions`).
2. **Gestiona sus reservas:**
   - Ve todas las sesiones que tiene disponibles/reservadas.
   - Puede **Reservar**, **Cancelar** o **Unirse** según:
     - cupos disponibles,
     - si ya reservó,
     - si ya es la hora o el instructor la inició (estado `live`).
3. **Desde un curso concreto:**
   - En `/course/{slug}` abre la pestaña **“Sesiones en vivo”**.
   - Repite las mismas acciones de reserva/cancelación/join, pero filtradas solo al curso.

### Instructor (relacionado con este caso) 👨‍🏫

1. Programa la sesión en su panel (Create LiveSession).
2. Define curso, horario, tipo y cupos.
3. El sistema crea la reunión en BBB con los cupos correctos.
4. Los estudiantes de ese curso la ven en:
   - Tab “Sesiones en vivo” del curso.
   - y en “Mis Sesiones” cuando corresponda según la lógica de negocio.

---

## ¿La tarea está completa? ✅ / 🚧

- ✅ **Cumple el objetivo principal del CU-04-008**:
  - Estudiante ve sesiones:
    - por curso (pestaña “Sesiones en vivo”),
    - globalmente (pantalla “Mis Sesiones”).
  - Puede reservar y cancelar su participación.
  - El botón de “Unirse” se habilita **solo cuando corresponde** (hora alcanzada o sesión en estado `live`).

- 🚧 **Cosas que se podrían mejorar luego (no bloqueantes para este CU)**:
  - Mostrar explícitamente “Cupo lleno / En lista de espera” si se implementa waitlist real.
  - Manejar zona horaria por usuario para mostrar horarios 100% localizados.
  - Añadir un calendario visual (opción C) como vista alternativa a la lista.

