Reservar clase
Ruta: /student?tab=book · Auth: Magic link (alumno)
Calendario visual semanal que muestra los huecos libres del profesor como bloques clicables. El alumno puede seleccionar hasta 5 slots y reservar en batch.
Que hay
Section titled “Que hay”Auto-seleccion inteligente
Section titled “Auto-seleccion inteligente”Cuando el alumno tiene un solo paquete activo, se selecciona automaticamente (paso 1 oculto). Cuando ese paquete tiene un solo servicio elegible, se selecciona automaticamente (paso 2 oculto). Resultado: el alumno va directo al calendario sin pasos intermedios.
Si hay multiples opciones, se muestran los selectores.
Paso 1 — Seleccionar enrollment (condicional)
Section titled “Paso 1 — Seleccionar enrollment (condicional)”Grid de enrollments activos mostrando creditos restantes. Solo visible cuando hay mas de uno.
Paso 2 — Seleccionar servicio (condicional)
Section titled “Paso 2 — Seleccionar servicio (condicional)”Grid de servicios elegibles filtrados por eligibleServiceIds del enrollment. Solo visible cuando hay mas de uno.
Paso 3 — Calendario semanal
Section titled “Paso 3 — Calendario semanal”Grid visual tipo calendario con 7 columnas (Lun–Dom) y filas de hora:
| Elemento | Visual | Accion |
|---|---|---|
| Slot disponible | Bloque verde (emerald) | Click para seleccionar/deseleccionar |
| Slot preferido | Bloque ambar con estrella | Click para seleccionar/deseleccionar |
| Slot seleccionado | Bloque primary con check | Click para deseleccionar |
| Sesion ya reservada | Bloque semitransparente con color del servicio | Solo informativo |
| Linea de hora actual | Linea roja horizontal | Solo informativo |
Caracteristicas del calendario:
- Rango de horas auto-calculado segun los slots disponibles (con 1h padding)
- Dot verde en el header de los dias que tienen slots
- Sesiones ya reservadas del alumno visibles como contexto
- Reglas de media hora con lineas de grid sutiles
Navegacion semanal: Flechas izquierda/derecha. Siempre Lun–Dom completo.
Selector de timezone: Dropdown compacto para ajustar zona horaria.
Horas preferidas
Section titled “Horas preferidas”Toggle para mostrar/editar preferencias horarias del alumno:
- Selectores de hora inicio/fin (intervalos de 30 min)
- Selector de dias de la semana (7 toggles Lun–Dom)
- Los slots que coinciden muestran estrella ambar en el calendario
- Leyenda con tooltip auto-show en primera visita (6s, localStorage)
Seleccion multiple
Section titled “Seleccion multiple”El alumno puede seleccionar hasta 5 slots en la misma semana o semanas diferentes. Barra de confirmacion inferior muestra:
- Nombre del servicio + conteo de slots seleccionados
- Chips con fecha/hora de cada slot (removibles con X)
- Boton de reserva (single endpoint si 1, batch si >1)
Estado de exito
Section titled “Estado de exito”Checkmark + mensaje de exito + boton “Reservar otra”.
Referencia tecnica
Section titled “Referencia tecnica”Archivos clave
Section titled “Archivos clave”| Archivo | Proposito |
|---|---|
apps/app/src/components/student/tab-book.tsx | Tab de reserva completo |
apps/app/src/components/student/booking-calendar.tsx | Componente BookingCalendar — grid visual |
| Endpoint | Metodo | Proposito |
|---|---|---|
/student/teacher | GET | Info del profesor + servicios |
/student/enrollments | GET | Enrollments activos del alumno |
/student/preferred-hours | GET/PATCH | Preferencias horarias |
/student/sessions | GET | Sesiones de la semana (para mostrar en calendario) |
/public/:slug/service-availability | GET | Slots disponibles (con flag isPreferred) |
/student/sessions | POST | Reservar sesion individual |
/student/sessions/batch | POST | Reservar multiples sesiones |
Componente BookingCalendar
Section titled “Componente BookingCalendar”interface BookingCalendarProps { weekDays: Date[]; // 7 Date objects (Mon-Sun) slots: AvailableSlot[]; // Available slots from API selectedSlots: AvailableSlot[]; // Currently selected onSlotToggle: (slot) => void; bookedSessions?: BookedSession[]; // Student's existing sessions hasPreferredHours?: boolean; isLoading?: boolean; timezone: string; // IANA timezone}Grid constants: HOUR_HEIGHT = 56px, auto-fit hour range based on slot data.