Skip to content

Dashboard

Ruta: /teacher/dashboard · Atajo: g d · Sidebar: Inicio

El Dashboard es la primera pantalla que ve el profesor al iniciar sesion. Muestra un resumen rapido del negocio, la agenda completa del dia, solicitudes de prueba pendientes y acciones sugeridas.

Dashboard page
┌──────────────────────────────────────────────────────────┐
│ Saludo + Streak badge [+ Clase rapida] │
├──────────────────────────────────────────────────────────┤
│ KPIs (2x2) │ Acciones sugeridas │
│ Ingresos · Clases │ (smart actions) │
│ Alumnos · Asistencia │ │
├──────────────────────────────────┼────────────────────────┤
│ Agenda de hoy (col-span-2) │ Solicitudes pendientes │
│ Timeline compacto, scroll │ (trials sin confirmar) │
├──────────────────────────────────┴────────────────────────┤
│ Esta semana (full width, solo si hay eventos no-hoy) │
└──────────────────────────────────────────────────────────┘

Mensaje de bienvenida que cambia segun la hora del dia:

HoraSaludo
6:00 – 11:59Buenos dias, NAME
12:00 – 17:59Buenas tardes, NAME
18:00 – 5:59Buenas noches, NAME

Subtitulo fijo: “Tus alumnos tienen suerte de tenerte”

Incluye un boton ”+ Clase rapida” a la derecha del saludo para programar sesiones sin salir del dashboard.

Si el profesor tiene un streak activo (dias consecutivos con clases completadas), se muestra un badge con icono de llama: “Llevas X dias consecutivos”.

Grid de 2x2 con metricas. El profesor elige 4 de un catalogo de 8 metricas disponibles desde Ajustes > General > KPIs del dashboard. Por defecto se muestran las 4 primeras.

MetricaKeyColorDatosTendencia
Ingresos del mesmonth_revenueVerdeTotal enrollments.pricePaid del mes en curso% vs mes anterior
Clases este mesmonth_lessonsAzulSesiones scheduled + completed + pending_review% vs mes anterior
Alumnos activosactive_studentsMoradoCount de students con status active
Asistenciaattendance_rateAmbarcompleted / (completed + no_shows) * 100 o ”—” si no hay datos
Ingresos pendientespending_revenueEsmeraldaSuma de services.priceAmount para sesiones futuras scheduled
Racha de ensenanzateaching_streakNaranjaDias consecutivos con clases completadas
Nuevos alumnosnew_studentsCieloStudents creados este mes
Sesiones completadascompleted_sessionsEsmeraldaSesiones con status completed este mes

La seleccion se guarda en teachers.dashboardConfig (JSONB) con la estructura { kpis: string[] }. NULL = defaults.

La tarjeta de Ingresos del mes muestra un subtitulo con los ingresos pendientes cuando hay sesiones programadas.

API: GET /teacher/dashboard/summary

Panel lateral derecho con alertas priorizadas que enlazan a la pagina correspondiente:

AccionPrioridadCuando apareceEnlaza a
Solicitudes de prueba pendientesAltaHay trials con status pending_confirmation/teacher/calendar
Alumnos sin clase programadaMediaStudents activos sin sesion scheduled futura/teacher/students
Creditos por expirarAltaEnrollments activos con validUntil < 7 dias/teacher/students
Alumnos en riesgo de abandonoAltaLifecycle events gap_detected en los ultimos 90 dias/teacher/students
Pruebas sin convertirMediaTrials completados en ultimos 30 dias sin enrollment activo/completado/teacher/insights
Alumnos inactivosBajaStudents con status inactive/teacher/students
Resenas sin responderMediaReviews con status approved y teacherResponse IS NULL/teacher/reviews
Content insightVariableInsights del content-analytics-worker (cache < 24h)/teacher/templates

API: GET /teacher/dashboard/smart-actions

Timeline compacto de todas las sesiones del dia actual. Ocupa 2 columnas en desktop, con scroll vertical cuando hay 8+ sesiones (max-h-[420px]). Auto-scroll al evento “next up”.

Cada fila tiene 3 estados visuales:

EstadoVisual
Pasada/completadaOpacidad reducida (opacity-50), borde izquierdo muted
Siguiente/en cursoBorde izquierdo 4px color del evento, fondo con tint, badge “En curso” o countdown
FuturaNormal, borde izquierdo a opacidad reducida

Contenido de cada fila:

  • Hora de inicio (columna fija)
  • Nombre del alumno + badge de servicio + badge de templates vinculadas
  • Rango horario completo (inicio – fin)
  • Badge “En curso” si la sesion esta en progreso, o countdown si es la siguiente
  • Acciones al hover: ver notas, WhatsApp, marcar completada

Header con contador de clases del dia. Si hay completadas, muestra “X de Y completadas”.

Casos especiales:

EscenarioComportamiento
0 eventos hoyEstado vacio: icono calendario + “No hay clases hoy” + “Disfruta tu dia libre”
8+ eventosmax-h-[420px] overflow-y-auto, auto-scroll al evento next-up
Todas completadasTodas dimmed, resumen “8 de 8 completadas”
En cursoBadge “En curso” en vez de countdown
Cancelada/no-showDimmed con opacity-50, se mantiene en su posicion del timeline

Lista de las proximas 4 sesiones que NO son de hoy (grid de 2 columnas en desktop). Solo se renderiza si hay eventos futuros no-hoy.

Cada tarjeta muestra:

  • Nombre del alumno + badge de servicio
  • Dia relativo (Hoy/Manana/Lun 3 mar) + rango horario
  • Acciones al hover (mismas que agenda de hoy)

Enlace “Ver todo” → navega a /teacher/calendar

API: GET /teacher/calendar?start={hoy}&end={+7dias}

Tarjetas para cada sesion de prueba sin confirmar:

  • Badge del servicio + duracion
  • Nombre del alumno
  • Fecha y hora solicitada
  • Boton “Confirmar” → session status scheduled, crea evento en Calendar, envia email
  • Boton “Rechazar” (X) → dialog con motivo opcional, envia email de rechazo

API: GET /teacher/sessions?status=pending_confirmation

Boton ”+ Clase rapida” en la cabecera del dashboard que abre un Sheet lateral con un formulario minimo:

  • Servicio: Selector con servicios activos del profesor (nombre + duracion)
  • Alumno: Selector con todos los alumnos
  • Fecha: Input date (default: hoy)
  • Hora: Input time con step de 15 min (default: siguiente cuarto de hora)
  • Boton “Programar”POST /teacher/sessions con serviceId, studentId, startUtc, timezone

Al confirmar, invalida queries de calendario y dashboard.

Badge motivacional junto al saludo que muestra dias consecutivos con al menos una clase completada. Calcula hacia atras desde hoy (o ayer si hoy aun no hay clase completada). Se oculta si el streak es 0.

Modo normal: Icono de llama naranja + texto: “Llevas X dias consecutivos”

Modo record: Cuando el streak actual supera el best_streak guardado, el badge cambia a icono de trofeo ambar con animacion animate-pulse y aparece un toast de celebracion (5 segundos, icono Trophy). El toast solo se dispara una vez por carga de datos gracias a streakToastShown ref.

Tarjeta KPI teaching_streak: Muestra el icono y etiqueta segun el estado:

  • Normal: llama + label “Racha de ensenanza”, subtitulo con el mejor record historico
  • Record: trofeo + label “Nuevo record”, subtitulo con el record anterior superado

Datos: Calculo en getSummary() — agrupa class_sessions completadas por fecha, ordena desc, cuenta dias consecutivos (maximo 365 dias atras). Lee teachers.best_streak al inicio para comparar. Si isNewRecord, actualiza best_streak en la DB (fire-and-forget) y crea una notificacion in-app via NotificationService con tipo streak_record.

API: Los campos bestStreak, isNewRecord se incluyen en la respuesta de GET /teacher/dashboard/summary.

Subtitulo en la tarjeta de Ingresos del mes que muestra la suma de services.priceAmount para sesiones futuras con status scheduled.

Formato: “Ingresos pendientes: $X”. Solo se muestra si hay sesiones programadas (pendingRevenue > 0).

Cuando el profesor tiene pagos en multiples monedas, el dashboard agrupa los ingresos pendientes por moneda y muestra cada importe formateado de forma independiente. El campo pendingRevenueByCurrency es un array de objetos { currency: string, amount: number } ordenado por importe desc. La tarjeta KPI itera el array y muestra una linea por moneda.


No hay items pendientes.


BugDescripcionEstadoCorregido
Moneda hardcodeada a EUREl dashboard ahora lee teachers.defaultCurrency (configurable en Ajustes > General)Batch 1
Ingresos mezclan monedasLa moneda del profesor (defaultCurrency) se usa como referencia para el simbolo y el formatoBatch 1
Asistencia 100% con 0 sesionesDevuelve null y muestra ”—” cuando no hay datosBatch 1
Key i18n incorrecta para templatesUsa key dedicada dashboard.linkedTemplatesBatch 1
Content insights no renderizadosEl tipo content_insight ahora se renderiza en SmartActionCardBatch 1

MejoraDescripcionDificultadEstadoImplementado
KPIs con drag-and-drop para reordenarActualmente el orden de los 4 KPIs seleccionados sigue el orden de seleccion. Podria anadirse drag-and-drop para reordenar las tarjetas.MedioBatch 5

ArchivoProposito
apps/web/src/routes/teacher/dashboard.lazy.tsxPagina completa (componente React)
apps/api/src/services/teacher/dashboard-service.tsCalculo de KPIs y smart actions
apps/api/src/routes/teacher/dashboard.tsRutas thin (GET summary, GET smart-actions)
apps/web/src/components/ui/kpi-card.tsxComponente reutilizable de tarjeta KPI
EndpointMetodoRespuesta
/teacher/dashboard/summaryGET{ monthRevenue, monthRevenueChange, monthLessons, monthLessonsChange, activeStudents, attendanceRate: number | null, currency, pendingRevenue, pendingRevenueByCurrency: { currency: string, amount: number }[], teachingStreak, bestStreak, isNewRecord, newStudents, completedSessions }
/teacher/dashboard/smart-actionsGET[{ type, count, priority, insight? }] — tipos: pending_trials, expiring_credits, no_upcoming, inactive_students, at_risk, unconverted_trials, unanswered_reviews, content_insight
/teacher/sessions?status=pending_confirmationGET[{ id, startsAt, student, service, ... }]
/teacher/calendar?start=X&end=YGET[{ id, type, title, startsAt, endsAt, status, ... }]
/teacher/sessionsPOSTCrea sesion manual. Body: { serviceId, studentId, startUtc, timezone? }
/teacher/servicesGETLista de servicios (usada por Quick add)
/teacher/studentsGETLista de alumnos (usada por Quick add)
// KPIs
useQuery({ queryKey: ['teacher-dashboard-summary'], queryFn: ... })
// Smart actions
useQuery({ queryKey: ['teacher-dashboard-smart-actions'], queryFn: ... })
// Teacher settings (for dashboardConfig.kpis)
useQuery({ queryKey: ['teacher', 'settings'], queryFn: ... })
// Trials pendientes
useQuery({ queryKey: ['teacher-sessions-pending'], queryFn: ... })
// Proximas 7 dias
useQuery({ queryKey: ['teacher-calendar', start, end], queryFn: ... })
// Servicios (lazy, solo cuando se abre Quick add)
useQuery({ queryKey: ['teacher-services'], enabled: open, queryFn: ... })
// Alumnos (lazy, solo cuando se abre Quick add)
useQuery({ queryKey: ['teacher-students-for-scheduling'], enabled: open, queryFn: ... })
AccionHookOptimista
Confirmar trialuseMutationNo (server-side, espera confirmacion)
Rechazar trialuseMutationNo
Completar sesionuseCompleteSessionSi (actualiza cache calendario)
Clase rapidauseMutationNo (server-side, espera confirmacion)