# Guía de Desarrollo - Portal Student **Fecha de creación:** 2025-11-29 **Versión:** 1.0.0 **Estado:** VIGENTE **Aplica a:** apps/frontend/src/apps/student/ + apps/backend/src/modules/[progress, gamification, educational] --- ## 1. Visión General ### 1.1 Propósito El Portal Student es la interfaz principal para estudiantes en GAMILIT. Es una plataforma educativa gamificada con temática de detective e inspiración Maya que proporciona: - **Aprendizaje Interactivo:** Módulos educativos con ejercicios de comprensión lectora - **Gamificación Completa:** Sistema de rangos Maya, achievements, misiones y ML Coins - **Progreso Personalizado:** Dashboard con métricas de desempeño y actividades recientes - **Economía Virtual:** Tienda de power-ups, comodines y items cosméticos - **Social:** Leaderboards, guilds, friends y competencia sana - **Notificaciones:** Sistema de alertas y celebraciones por logros ### 1.2 Usuarios Objetivo | Rol | Acceso | Funcionalidades | |-----|--------|-----------------| | Student | Completo | Todas las funcionalidades del portal | | Teacher | Supervisión | Vista de progreso de estudiantes | | Admin | Monitoreo | Vista de todas las métricas y configuración | ### 1.3 Temática y Narrativa **Tema Principal:** Detective educativo con elementos de cultura Maya - **Rangos:** Jerarquía Maya (Ajaw → Nacom → Ah K'in → Halach Uinic → K'uk'ulkan) - **Moneda:** ML Coins (Marie Learning Coins) - **Narrativa:** Estudiante como "Detective" que resuelve "casos" (ejercicios) - **Iconografía:** Lupa, expediente, evidencias, rango Maya --- ## 2. Arquitectura del Portal ### 2.1 Estructura de Carpetas #### Frontend (apps/frontend/src/apps/student/) ``` student/ ├── pages/ # 27 páginas principales │ ├── DashboardComplete.tsx # ⭐ Dashboard principal │ ├── ExercisePage.tsx # ⭐ Ejercicios interactivos (mecánicas) │ ├── GamificationPage.tsx # ⭐ Hub de gamificación │ ├── ModuleDetailPage.tsx # Detalle de módulo educativo │ ├── AchievementsPage.tsx # Logros desbloqueados │ ├── ShopPage.tsx # Tienda ML Coins │ ├── LeaderboardPage.tsx # Rankings globales │ ├── MissionsPage.tsx # Misiones activas │ ├── InventoryPage.tsx # Inventario de comodines │ ├── FriendsPage.tsx # Sistema de amigos │ ├── GuildsPage.tsx # Guilds/clanes │ ├── EnhancedProfilePage.tsx # Perfil de usuario │ ├── SettingsPage.tsx # Configuración │ ├── NotificationsPage.tsx # Centro de notificaciones │ ├── AssignmentsPage.tsx # Tareas del teacher │ ├── LoginPage.tsx # Autenticación │ ├── RegisterPage.tsx # Registro │ ├── PasswordRecoveryPage.tsx # Recuperación contraseña │ └── ... ├── components/ # Componentes organizados por dominio │ ├── dashboard/ # 17 componentes del dashboard │ │ ├── BottomNavigation.tsx # ⭐ Navegación móvil (6 tabs) │ │ ├── EnhancedStatsGrid.tsx # Estadísticas detective │ │ ├── RankProgressWidget.tsx # Widget de rango Maya │ │ ├── MLCoinsWidget.tsx # Balance de ML Coins │ │ ├── MissionsPanel.tsx # Misiones activas │ │ ├── ModulesSection.tsx # Grid de módulos │ │ ├── RecentActivityPanel.tsx # Actividades recientes │ │ ├── QuickActionsWidget.tsx # Acciones rápidas │ │ ├── AchievementMilestones.tsx # Hitos de logros │ │ └── ... │ ├── exercise/ # Componentes de ejercicios │ │ ├── ExerciseHeader.tsx # Header con timer y score │ │ ├── CompletionModal.tsx # Modal de finalización │ │ ├── HintModal.tsx # Sistema de pistas │ │ ├── PowerUpEffects.tsx # Efectos de power-ups │ │ └── ExerciseSidebar.tsx # Sidebar con progreso │ ├── gamification/ # Componentes de gamificación │ │ ├── GamificationHero.tsx # Hero section │ │ ├── RanksSection.tsx # Sección de rangos │ │ ├── MLCoinsSection.tsx # Sección de economía │ │ ├── AchievementsPreview.tsx # Preview de logros │ │ ├── LeaderboardPreview.tsx # Preview de ranking │ │ └── StreaksMissionsSection.tsx # Rachas y misiones │ ├── achievements/ # Sistema de logros │ │ ├── AchievementGrid.tsx # Grid de achievements │ │ ├── AchievementDetailModal.tsx # Modal de detalle │ │ ├── AchievementFilters.tsx # Filtros (rarity, category) │ │ └── AchievementStatistics.tsx # Estadísticas │ ├── notifications/ # Notificaciones y celebraciones │ │ ├── AchievementToast.tsx # Toast de logro desbloqueado │ │ └── CelebrationModal.tsx # Modal de celebración │ ├── interactions/ # Interacciones gestuales │ │ └── SwipeableContainer.tsx # Swipe para móvil │ └── PowerUpBar.tsx # Barra de power-ups activos ├── hooks/ # 14 custom hooks │ ├── useDashboardData.ts # ⭐ Dashboard data + React Query │ ├── useUserModules.ts # Módulos del usuario │ ├── useRecentActivities.ts # Actividades recientes │ ├── useGamificationData.ts # Datos de gamificación │ ├── useAchievementsEnhanced.ts # Achievements con filtros │ ├── useExerciseState.ts # Estado de ejercicio │ ├── useExerciseAutoSave.ts # Auto-save de progreso │ ├── useExercisePowerUps.ts # Power-ups en ejercicios │ ├── useUserClassroom.ts # Classroom del usuario │ ├── useSwipeGesture.ts # Gestos táctiles │ ├── useResponsiveLayout.ts # Responsive breakpoints │ └── index.ts # Barrel export └── types/ └── index.ts # 40+ interfaces/types ``` #### Backend - Módulos Principales ``` apps/backend/src/modules/ ├── progress/ # Sistema de progreso │ ├── controllers/ │ │ ├── exercise-submission.controller.ts │ │ ├── exercise-attempt.controller.ts │ │ ├── module-progress.controller.ts │ │ └── learning-session.controller.ts │ ├── services/ │ │ ├── exercise-submission.service.ts │ │ ├── module-progress.service.ts │ │ └── learning-session.service.ts │ ├── entities/ │ │ ├── exercise-submission.entity.ts │ │ ├── module-progress.entity.ts │ │ └── learning-session.entity.ts │ └── dto/ │ ├── create-exercise-submission.dto.ts │ └── exercise-submission-response.dto.ts ├── gamification/ # Sistema de gamificación │ ├── controllers/ │ │ ├── achievements.controller.ts │ │ ├── missions.controller.ts │ │ ├── ml-coins.controller.ts │ │ ├── ranks.controller.ts │ │ ├── leaderboard.controller.ts │ │ └── comodines.controller.ts │ ├── services/ │ │ ├── achievements.service.ts │ │ ├── missions.service.ts │ │ ├── ml-coins.service.ts │ │ ├── ranks.service.ts │ │ └── user-stats.service.ts │ └── entities/ │ ├── achievement.entity.ts │ ├── user-achievement.entity.ts │ ├── mission.entity.ts │ ├── user-rank.entity.ts │ ├── ml-coins-transaction.entity.ts │ └── user-stats.entity.ts ├── educational/ # Contenido educativo │ ├── controllers/ │ │ ├── modules.controller.ts │ │ ├── exercises.controller.ts │ │ └── media.controller.ts │ ├── services/ │ │ ├── modules.service.ts │ │ └── exercises.service.ts │ └── entities/ │ ├── module.entity.ts │ └── exercise.entity.ts └── social/ # Características sociales ├── controllers/ │ ├── friendships.controller.ts │ ├── teams.controller.ts │ └── peer-challenges.controller.ts └── services/ ├── friendships.service.ts └── teams.service.ts ``` ### 2.2 Diagrama de Flujo de Datos ``` ┌─────────────────────────────────────────────────────────────────┐ │ STUDENT PORTAL │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Dashboard │───►│ Modules │───►│ Exercise │ │ │ │ Complete │ │ (Learning) │ │ Page │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Custom Hooks Layer (React Query) │ │ │ │ - useDashboardData() - useUserModules() │ │ │ │ - useExerciseState() - useGamificationData() │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ API Services Layer (Axios) │ │ │ │ - progressAPI - gamificationAPI │ │ │ │ - educationalAPI - socialAPI │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ └──────────────────────────────┼───────────────────────────────────┘ │ HTTP/REST │ ┌──────────────────────────────▼───────────────────────────────────┐ │ BACKEND API │ ├──────────────────────────────────────────────────────────────────┤ │ Controllers ──► Services ──► Repositories ──► Database │ │ │ │ │ │ │ ├──► Gamification Module │ │ │ ├──► Progress Module │ │ │ ├──► Educational Module │ │ │ └──► Social Module │ └──────────────────────────────────────────────────────────────────┘ ``` --- ## 3. Módulos Principales ### 3.1 Dashboard (DashboardComplete) **Ruta:** `/` **Propósito:** Centro de control del estudiante con visión general de progreso, misiones, módulos y actividades recientes. **Componentes Clave:** 1. **GamifiedHeader** - Usuario autenticado - Balance de ML Coins - Rank actual con icono Maya - Botón de logout 2. **QuickActionsWidget** - Continuar último ejercicio - Ver misiones activas - Ir a tienda - Ver perfil 3. **RankProgressWidget** (4 columnas) - Rank actual con icono Maya - XP actual / XP requerido - Barra de progreso - Multiplicador activo 4. **ModulesSection** (8 columnas) - Grid de 4 módulos (2 col c/u) - Estado: available, in_progress, locked - Progreso porcentual - Dificultad (fácil, medio, difícil) 5. **EnhancedStatsGrid** (4 columnas) - Casos resueltos (ejercicios completados) - Racha actual de días - Tiempo total invertido - XP total acumulado 6. **MissionsPanel** (4 columnas) - Top 3 misiones activas - Progreso de cada misión - Recompensas (XP, ML Coins) - Tiempo límite 7. **RecentActivityPanel** (4 columnas) - Últimas 5 actividades - Timestamps relativos - Iconos por tipo de actividad **Hooks Utilizados:** ```typescript // Dashboard data (React Query) const { rank, progress, loading, error, refresh } = useDashboardData(); // Missions from backend const { allMissions, activeMissions } = useMissions(); // Modules filtered by classroom const { modules, loading: modulesLoading } = useUserModules({ classroomId: userClassroomId, }); // Recent activities const { activities, loading: activitiesLoading } = useRecentActivities(5); // Gamification data (mock until backend ready) const { gamificationData } = useUserGamification(user?.id); ``` **APIs:** ```typescript // Dashboard aggregated data GET /api/v1/gamification/users/:userId/ml-coins GET /api/v1/gamification/ranks/current GET /api/v1/gamification/ranks/users/:userId/rank-progress GET /api/v1/gamification/users/:userId/achievements GET /api/v1/progress/users/:userId // Missions GET /api/v1/gamification/missions/active // Modules GET /api/v1/educational/modules GET /api/v1/educational/modules/:classroomId/assigned // Activities GET /api/v1/progress/users/:userId/recent-activities ``` ### 3.2 Módulos Educativos **Ruta:** `/modules/:moduleId` **Propósito:** Vista detallada de un módulo con sus ejercicios, progreso y recomendaciones. **Estructura de Módulo:** - **Módulo 1:** Comprensión Literal - **Módulo 2:** Comprensión Inferencial - **Módulo 3:** Comprensión Crítica - **Módulo 4:** Textos Digitales y Multimediales **Componentes:** - **ModuleHeader:** Título, descripción, progreso general - **ExercisesList:** Lista de ejercicios con estado (locked, available, in_progress, completed) - **ProgressChart:** Gráfico de progreso por competencia - **RecommendedExercises:** Ejercicios sugeridos según desempeño **APIs:** ```typescript GET /api/v1/educational/modules/:moduleId GET /api/v1/educational/modules/:moduleId/exercises GET /api/v1/progress/modules/:moduleId/progress ``` ### 3.3 Ejercicios Interactivos (ExercisePage) **Ruta:** `/exercises/:exerciseId` **Propósito:** Interfaz para completar ejercicios con mecánicas interactivas variadas. **Mecánicas Implementadas (por módulo):** #### Módulo 1 - Comprensión Literal - `crucigrama` - Crucigrama científico - `timeline` / `linea_tiempo` - Línea de tiempo - `sopa_letras` - Sopa de letras - `mapa_conceptual` - Mapa conceptual - `emparejamiento` - Emparejamiento - `verdadero_falso` - Verdadero/Falso - `completar_espacios` - Completar espacios en blanco #### Módulo 2 - Comprensión Inferencial - `detective_textual` - Detective textual - `lectura_inferencial` - Lectura inferencial - `construccion_hipotesis` - Construcción de hipótesis - `prediccion_narrativa` - Predicción narrativa - `puzzle_contexto` - Puzzle de contexto - `rueda_inferencias` - Rueda de inferencias #### Módulo 3 - Comprensión Crítica - `analisis_fuentes` - Análisis de fuentes - `debate_digital` - Debate digital - `matriz_perspectivas` - Matriz de perspectivas - `podcast_argumentativo` - Podcast argumentativo - `tribunal_opiniones` - Tribunal de opiniones #### Módulo 4 - Textos Digitales - `verificador_fakenews` - Verificador de fake news - `quiz_tiktok` - Quiz TikTok - `navegacion_hipertextual` - Navegación hipertextual - `analisis_memes` - Análisis de memes - `infografia_interactiva` - Infografía interactiva - `email_formal` - Email formal - `chat_literario` - Chat literario - `ensayo_argumentativo` - Ensayo argumentativo - `resena_critica` - Reseña crítica **Componentes de Ejercicio:** ```typescript // Layout principal
}>
``` **Flujo de Ejercicio:** 1. **Carga:** GET `/api/v1/educational/exercises/:exerciseId` 2. **Auto-save:** POST `/api/v1/progress/exercises/:exerciseId/save` (cada 30s) 3. **Uso de Hint:** POST `/api/v1/progress/exercises/:exerciseId/use-hint` 4. **Uso de Power-up:** POST `/api/v1/gamification/comodines/use` 5. **Envío:** POST `/api/v1/progress/exercises/:exerciseId/submit` 6. **Feedback:** Recibe calificación, XP ganado, ML Coins, achievements desbloqueados **Hooks:** ```typescript // Exercise state management const { exerciseState, updateProgress } = useExerciseState(exerciseId); // Auto-save every 30s useExerciseAutoSave(exerciseId, exerciseState, { interval: 30000, enabled: !exerciseState.completed, }); // Power-ups activation const { activePowerUps, usePowerUp } = useExercisePowerUps(); ``` **APIs:** ```typescript GET /api/v1/educational/exercises/:exerciseId GET /api/v1/educational/exercises/:exerciseId/hints POST /api/v1/progress/exercises/:exerciseId/save POST /api/v1/progress/exercises/:exerciseId/submit POST /api/v1/gamification/comodines/use ``` ### 3.4 Sistema de Gamificación **Ruta:** `/gamification` **Propósito:** Hub central de gamificación con ranks, achievements, economy y stats. **Secciones:** #### 3.4.1 Ranks Maya System **Jerarquía de Rangos:** | Rango | Icono | XP Requerido | Multiplicador | |-------|-------|--------------|---------------| | Ajaw | 🏹 | 0 | 1.0x | | Nacom | 🔍 | 1,000 | 1.2x | | Ah K'in | 🗡️ | 5,000 | 1.5x | | Halach Uinic | ⚔️ | 15,000 | 2.0x | | K'uk'ulkan | 👑 | 50,000 | 3.0x | **Componentes:** ```typescript ``` **APIs:** ```typescript GET /api/v1/gamification/ranks/current GET /api/v1/gamification/ranks/users/:userId/rank-progress GET /api/v1/gamification/ranks/users/:userId/history POST /api/v1/gamification/ranks/users/:userId/prestige ``` #### 3.4.2 ML Coins Economy **Fuentes de Ingresos:** - Completar ejercicios: 10-100 ML Coins (según dificultad y score) - Completar misiones: 50-500 ML Coins - Desbloquear achievements: 20-200 ML Coins - Bonificaciones del teacher: Variable - Daily login bonus: 10 ML Coins **Gastos:** - Power-ups (comodines): 50-200 ML Coins - Items cosméticos: 100-1,000 ML Coins - Profile customizations: 50-500 ML Coins **Componentes:** ```typescript ``` **APIs:** ```typescript GET /api/v1/gamification/users/:userId/ml-coins GET /api/v1/gamification/users/:userId/ml-coins/transactions POST /api/v1/gamification/users/:userId/ml-coins/add POST /api/v1/gamification/users/:userId/ml-coins/deduct ``` #### 3.4.3 Achievements System **Categorías:** - **Progress:** Completar módulos, ejercicios - **Mastery:** Puntuaciones perfectas, rachas - **Social:** Amigos, guild, colaboración - **Explorer:** Descubrir contenido, probar mecánicas - **Economy:** Gastar ML Coins, comprar items - **Special:** Eventos, logros únicos **Rarities:** - Common (Común) - Gris - Rare (Raro) - Azul - Epic (Épico) - Morado - Legendary (Legendario) - Dorado **Componentes:** ```typescript // Toast cuando se desbloquea ``` **APIs:** ```typescript GET /api/v1/gamification/achievements GET /api/v1/gamification/users/:userId/achievements GET /api/v1/gamification/achievements/:achievementId POST /api/v1/gamification/users/:userId/achievements/:achievementId/claim ``` #### 3.4.4 Missions System **Tipos de Misiones:** - **Daily:** Reseteables cada día (ej: "Completa 3 ejercicios") - **Weekly:** Reseteables cada semana (ej: "Completa 1 módulo") - **Seasonal:** Eventos especiales (ej: "Participa en Halloween Challenge") - **Progressive:** Una sola vez (ej: "Alcanza Rank Nacom") **Dificultades:** - Easy: 50 XP, 20 ML Coins - Medium: 100 XP, 50 ML Coins - Hard: 200 XP, 100 ML Coins **Componentes:** ```typescript ``` **APIs:** ```typescript GET /api/v1/gamification/missions/active GET /api/v1/gamification/missions/completed POST /api/v1/gamification/missions/:missionId/claim ``` ### 3.5 Tienda (ShopPage) **Ruta:** `/shop` **Propósito:** Compra de power-ups, comodines y items cosméticos con ML Coins. **Categorías:** 1. **Power-ups** (Premium) - ✅ IMPLEMENTADO - Hint Revealer (50 ML Coins) - Revela una pista gratis - Time Freeze (100 ML Coins) - Pausa el timer 60s - XP Boost (150 ML Coins) - +50% XP por 1 hora - Score Multiplier (200 ML Coins) - +2x score en próximo ejercicio 2. **Cosmetics** - ❌ NO IMPLEMENTADO - Avatares - Marcos de perfil - Badges decorativos 3. **Profile** - ❌ NO IMPLEMENTADO - Títulos - Efectos de partículas - Temas de color **Componentes:** ```typescript ``` **APIs:** ```typescript GET /api/v1/gamification/shop/items GET /api/v1/gamification/shop/power-ups POST /api/v1/gamification/shop/purchase GET /api/v1/gamification/users/:userId/inventory ``` ### 3.6 Leaderboard **Ruta:** `/leaderboard` **Propósito:** Rankings globales y por classroom para competencia sana. **Tipos de Rankings:** 1. **Global XP:** Top 100 usuarios por XP total 2. **Weekly XP:** Top 50 usuarios por XP de esta semana 3. **Classroom:** Top estudiantes del aula 4. **Streak Leaders:** Top rachas activas 5. **ML Coins:** Top por balance de ML Coins **Componentes:** ```typescript ``` **APIs:** ```typescript GET /api/v1/gamification/leaderboard/global GET /api/v1/gamification/leaderboard/weekly GET /api/v1/gamification/leaderboard/classroom/:classroomId GET /api/v1/gamification/leaderboard/streaks GET /api/v1/gamification/leaderboard/user-position/:userId ``` ### 3.7 Perfil de Usuario **Ruta:** `/profile` **Propósito:** Visualizar y editar perfil personal, estadísticas y configuración. **Secciones:** 1. **Profile Header** - Avatar - Username - Rank actual con icono - Titles (si tiene) 2. **Stats Overview** - Total XP - ML Coins balance - Achievements desbloqueados - Módulos completados - Racha actual 3. **Recent Achievements** - Últimos 5 logros desbloqueados 4. **Activity Graph** - Actividad de los últimos 30 días 5. **Edit Profile** - Cambiar avatar - Cambiar username - Bio **APIs:** ```typescript GET /api/v1/auth/users/:userId/profile PATCH /api/v1/auth/users/:userId/profile GET /api/v1/progress/users/:userId/stats GET /api/v1/gamification/users/:userId/activity-graph ``` --- ## 4. Navegación ### 4.1 BottomNavigation (Móvil) **Componente:** `BottomNavigation.tsx` **Ubicación:** Fixed bottom en mobile (< 768px) **Tabs:** | ID | Label | Icon | Path | Descripción | |----|-------|------|------|-------------| | home | Home | Home | `/` | Dashboard principal | | modules | Modules | BookOpen | `/modules` | Módulos educativos | | gamification | Gamification | Trophy | `/gamification` | Hub de gamificación | | notifications | Alerts | Bell | `/notifications` | Centro de notificaciones | | profile | Profile | User | `/profile` | Perfil de usuario | | settings | Settings | Settings | `/settings` | Configuración | **Features:** - **Active indicator:** Tab activo resaltado con color detective-orange - **Notification badge:** Badge rojo en Bell si hay notificaciones sin leer - **Smooth animations:** Framer Motion para transiciones - **Accessibility:** ARIA labels y roles correctos ```typescript // Detecta pathname y resalta tab activo const isActive = (path: string) => { if (path === '/') return location.pathname === '/'; return location.pathname.startsWith(path); }; // Muestra badge de notificaciones {item.id === 'notifications' && unreadCount > 0 && ( )} ``` ### 4.2 Desktop Navigation **Componente:** `GamifiedHeader` **Features:** - Logo GAMILIT - ML Coins balance widget - Rank badge - Notifications dropdown - User menu (perfil, settings, logout) --- ## 5. Hooks Principales ### 5.1 useDashboardData **Propósito:** Fetches aggregated dashboard data con React Query. **Endpoints llamados (en paralelo):** ```typescript GET /api/v1/gamification/users/:userId/ml-coins GET /api/v1/gamification/ranks/current GET /api/v1/gamification/ranks/users/:userId/rank-progress GET /api/v1/gamification/users/:userId/achievements GET /api/v1/progress/users/:userId ``` **Return value:** ```typescript { coins: MLCoinsData | null, rank: RankData | null, achievements: AchievementData[], progress: ProgressData | null, recentAchievements: AchievementData[], loading: boolean, error: string | null, isRefreshing: boolean, refresh: () => Promise } ``` **Configuración React Query:** - **staleTime:** 5 minutos - **gcTime:** 10 minutos - **refetchOnWindowFocus:** true - **retry:** 2 veces con backoff exponencial ### 5.2 useUserModules **Propósito:** Fetches módulos educativos del usuario, opcionalmente filtrados por classroom. **API:** ```typescript GET /api/v1/educational/modules GET /api/v1/educational/modules/:classroomId/assigned ``` **Return value:** ```typescript { modules: Module[], loading: boolean, error: string | null } ``` ### 5.3 useExerciseState **Propósito:** Gestiona estado local de ejercicio en progreso. **State:** ```typescript { currentStep: number, totalSteps: number, score: number, answers: Record, hintsUsed: number, timeSpent: number, powerupsUsed: string[], completed: boolean } ``` **Métodos:** - `updateProgress(progress: Partial)` - `submitExercise()` - `resetExercise()` ### 5.4 useExerciseAutoSave **Propósito:** Auto-save de progreso cada 30s mientras ejercicio no completado. **API:** ```typescript POST /api/v1/progress/exercises/:exerciseId/save { progress: ExerciseProgress, answers: any } ``` **Configuración:** ```typescript useExerciseAutoSave(exerciseId, exerciseState, { interval: 30000, // 30 segundos enabled: !exerciseState.completed, }); ``` ### 5.5 useExercisePowerUps **Propósito:** Gestión de power-ups activos durante ejercicio. **API:** ```typescript POST /api/v1/gamification/comodines/use { comodinId: string, exerciseId: string } ``` **Métodos:** - `usePowerUp(powerUpId: string)` - `getActivePowerUps()` - `checkPowerUpActive(type: string)` --- ## 6. APIs del Portal Student ### 6.1 Endpoints Principales | Módulo | Método | Endpoint | Descripción | Guard | |--------|--------|----------|-------------|-------| | **Progress** | | | GET | `/progress/users/:userId` | Progreso general del usuario | JwtAuth | | | GET | `/progress/users/:userId/recent-activities` | Últimas actividades | JwtAuth | | | GET | `/progress/modules/:moduleId/progress` | Progreso en módulo | JwtAuth | | | POST | `/progress/exercises/:exerciseId/save` | Auto-save de ejercicio | JwtAuth | | | POST | `/progress/exercises/:exerciseId/submit` | Enviar ejercicio completo | JwtAuth | | **Gamification** | | | GET | `/gamification/users/:userId/ml-coins` | Balance de ML Coins | JwtAuth | | | GET | `/gamification/users/:userId/ml-coins/transactions` | Historial de transacciones | JwtAuth | | | GET | `/gamification/ranks/current` | Ranks disponibles | JwtAuth | | | GET | `/gamification/ranks/users/:userId/rank-progress` | Progreso de rank | JwtAuth | | | GET | `/gamification/achievements` | Todos los achievements | JwtAuth | | | GET | `/gamification/users/:userId/achievements` | Achievements del usuario | JwtAuth | | | GET | `/gamification/missions/active` | Misiones activas | JwtAuth | | | POST | `/gamification/missions/:missionId/claim` | Reclamar recompensa | JwtAuth | | | GET | `/gamification/leaderboard/global` | Ranking global | JwtAuth | | | GET | `/gamification/leaderboard/classroom/:id` | Ranking del aula | JwtAuth | | | GET | `/gamification/shop/items` | Items de la tienda | JwtAuth | | | POST | `/gamification/shop/purchase` | Comprar item | JwtAuth | | | POST | `/gamification/comodines/use` | Usar power-up | JwtAuth | | **Educational** | | | GET | `/educational/modules` | Lista de módulos | JwtAuth | | | GET | `/educational/modules/:id` | Detalle de módulo | JwtAuth | | | GET | `/educational/modules/:id/exercises` | Ejercicios del módulo | JwtAuth | | | GET | `/educational/exercises/:id` | Detalle de ejercicio | JwtAuth | | | GET | `/educational/exercises/:id/hints` | Pistas disponibles | JwtAuth | | **Social** | | | GET | `/social/friendships` | Lista de amigos | JwtAuth | | | POST | `/social/friendships` | Enviar solicitud de amistad | JwtAuth | | | GET | `/social/teams/:id` | Detalle de guild | JwtAuth | ### 6.2 Frontend API Services ``` services/api/ ├── educationalAPI.ts # Módulos y ejercicios ├── progressAPI.ts # Progreso y submissions ├── gamificationAPI.ts # Gamificación general ├── ranksAPI.ts # Sistema de ranks ├── achievementsAPI.ts # Achievements ├── missionsAPI.ts # Misiones ├── economyAPI.ts # ML Coins y shop ├── socialAPI.ts # Amigos, guilds, leaderboard └── apiClient.ts # Axios instance configurado ``` --- ## 7. Estado y Stores (Zustand) ### 7.1 Stores Principales ```typescript // Auth Store authStore: - user: User | null - isAuthenticated: boolean - login() - logout() - register() // Ranks Store ranksStore: - userProgress: UserRankProgress - multiplierBreakdown: MultiplierData - prestigeProgress: PrestigeData - progressionHistory: ProgressEvent[] - fetchUserProgress() - showRankUpModal: boolean - closeRankUpModal() // Economy Store economyStore: - balance: MLCoinsBalance - transactions: Transaction[] - fetchBalance() - addTransaction() // Achievements Store achievementsStore: - achievements: Achievement[] - userAchievements: UserAchievement[] - stats: AchievementStats - fetchAchievements() - claimAchievement() // Notifications Store notificationsStore: - notifications: Notification[] - unreadCount: number - fetchNotifications() - markAsRead() - fetchUnreadCount() ``` --- ## 8. Flujos Principales ### 8.1 Flujo: Completar Ejercicio ``` 1. Student navega a /exercises/:exerciseId ↓ 2. ExercisePage carga ejercicio: GET /educational/exercises/:exerciseId ↓ 3. useExerciseState inicializa estado local ↓ 4. useExerciseAutoSave inicia (cada 30s): POST /progress/exercises/:exerciseId/save ↓ 5. Student completa ejercicio y presiona "Submit" ↓ 6. POST /progress/exercises/:exerciseId/submit { answers: {...}, timeSpent: 180, hintsUsed: 1, powerupsUsed: ['hint_revealer'] } ↓ 7. Backend calcula score, XP ganado, ML Coins ↓ 8. Response: { score: 85, maxScore: 100, xpEarned: 120, mlCoinsEarned: 50, achievements: ['first_completion'], feedback: {...} } ↓ 9. FeedbackModal muestra resultados ↓ 10. Si achievement desbloqueado → AchievementToast ↓ 11. Si rank up → RankUpModal ↓ 12. Redirect a /modules o /dashboard ``` ### 8.2 Flujo: Ganar XP y Subir de Rango ``` 1. Student completa ejercicio → Gana XP (ej: 120 XP) ↓ 2. Backend actualiza user_stats.total_xp ↓ 3. Backend verifica si XP >= siguiente rank: SELECT * FROM gamification.maya_ranks WHERE xp_required <= :totalXP ORDER BY xp_required DESC LIMIT 1 ↓ 4. Si cambió rank: - Actualizar user_rank.current_rank - Crear entry en rank_progression_history - Crear achievement 'rank_up_{rankName}' ↓ 5. Response incluye: { rankUp: true, newRank: 'Nacom', newMultiplier: 1.2, prestigePoints: 0 } ↓ 6. Frontend muestra RankUpModal con celebración ↓ 7. ranksStore.fetchUserProgress() actualiza estado ``` ### 8.3 Flujo: Comprar Item en Shop ``` 1. Student navega a /shop ↓ 2. GET /gamification/shop/items → Lista items disponibles ↓ 3. Student selecciona item → Modal de confirmación ↓ 4. Verificar balance suficiente ↓ 5. POST /gamification/shop/purchase { itemId: 'hint_revealer', quantity: 1 } ↓ 6. Backend: - Verifica balance >= item.price - Deducir ML Coins - Agregar item a inventory - Crear transaction log ↓ 7. Response: { success: true, newBalance: 450, item: {...} } ↓ 8. Frontend: - economyStore.fetchBalance() (actualiza balance) - Toast: "Item comprado exitosamente" - Modal cierra ``` --- ## 9. Sistema de Gamificación Detallado ### 9.1 Cálculo de XP **Fórmula Base:** ```typescript baseXP = exercise.points; // Ej: 100 XP // Multiplicadores scoreMultiplier = (score / maxScore); // Ej: 85/100 = 0.85 rankMultiplier = userRank.multiplier; // Ej: 1.2x (Nacom) streakBonus = min(currentStreak * 0.05, 0.5); // Max +50% totalXP = baseXP * scoreMultiplier * rankMultiplier * (1 + streakBonus); // Ejemplo: // 100 XP * 0.85 * 1.2 * 1.15 = 117.3 XP → 117 XP ``` **Bonuses Adicionales:** - **Perfect Score:** +20% XP si score = 100% - **Speed Bonus:** +10% XP si completa en < 50% tiempo estimado - **No Hints Used:** +15% XP si no usó pistas - **First Try:** +25% XP si completa en primer intento ### 9.2 Cálculo de ML Coins **Fórmula Base:** ```typescript baseCoins = Math.floor(exercise.points / 10); // Ej: 100 XP → 10 ML Coins // Multiplicadores scoreMultiplier = (score / maxScore); difficultyBonus = { easy: 1.0, medium: 1.5, hard: 2.0 }[exercise.difficulty]; totalCoins = baseCoins * scoreMultiplier * difficultyBonus; // Ejemplo (hard, 85% score): // 10 * 0.85 * 2.0 = 17 ML Coins ``` ### 9.3 Sistema de Streaks **Cómo funciona:** - **Racha (Streak):** Días consecutivos con al menos 1 ejercicio completado - **Zona horaria:** UTC-5 (Colombia) - **Reset:** Si pasa 1 día completo sin actividad → streak = 0 - **Bonus XP:** +5% por cada día de racha (max +50% a 10 días) **Guardado:** ```sql -- En user_stats current_streak: integer DEFAULT 0 longest_streak: integer DEFAULT 0 last_activity_date: date ``` **Lógica:** ```typescript const today = new Date().toISOString().split('T')[0]; const lastActivity = user.lastActivityDate; if (lastActivity === today) { // Mismo día, no cambiar streak } else { const daysSince = daysBetween(lastActivity, today); if (daysSince === 1) { // Día consecutivo user.currentStreak++; user.longestStreak = Math.max(user.longestStreak, user.currentStreak); } else { // Se rompió la racha user.currentStreak = 1; } user.lastActivityDate = today; } ``` ### 9.4 Achievements: Triggers y Lógica **Ejemplos de Achievements:** | ID | Nombre | Trigger | Condición | Recompensa | |----|--------|---------|-----------|------------| | first_steps | Primeros Pasos | exercise_completed | count === 1 | 20 XP, 10 ML Coins | | speed_demon | Demonio de Velocidad | exercise_completed | timeSpent < estimatedTime * 0.5 | 50 XP, 25 ML Coins | | perfectionist | Perfeccionista | exercise_completed | score === 100 && attempts === 1 | 100 XP, 50 ML Coins | | rank_nacom | Ascenso a Nacom | rank_up | newRank === 'Nacom' | 200 XP, 100 ML Coins | | module_master | Maestro de Módulo | module_completed | completionRate === 100% | 500 XP, 200 ML Coins | | streak_warrior | Guerrero Constante | daily_activity | currentStreak === 7 | 150 XP, 75 ML Coins | | coin_collector | Coleccionista | ml_coins_earned | totalCoinsEarned >= 1000 | 100 XP, 50 ML Coins | **Backend Logic:** ```typescript // En exercise-submission.service.ts async checkAchievements(userId: string, context: AchievementContext) { const triggers = await this.achievementsRepo.find({ where: { trigger: context.trigger } }); for (const achievement of triggers) { const meetsCondition = await this.evaluateCondition( achievement.condition, userId, context ); if (meetsCondition) { await this.unlockAchievement(userId, achievement.id); } } } ``` --- ## 10. Responsive Design ### 10.1 Breakpoints ```typescript // tailwind.config.js screens: { 'sm': '640px', // Mobile landscape 'md': '768px', // Tablet 'lg': '1024px', // Desktop 'xl': '1280px', // Large desktop '2xl': '1536px' // Extra large } ``` ### 10.2 Layout Adaptations **Mobile (< 768px):** - BottomNavigation visible - Single column layouts - Swipeable carousels - Collapsible sections - Touch-optimized controls (min 44x44px) **Tablet (768px - 1024px):** - BottomNavigation hidden - GamifiedHeader expanded - 2-column grids - Sidebars overlay **Desktop (> 1024px):** - Full navigation - 3-4 column grids - Persistent sidebars - Hover states **Hook:** ```typescript const { isMobile, isTablet, isDesktop } = useResponsiveLayout(); // Usage {isMobile && } {isDesktop && } ``` --- ## 11. Buenas Prácticas ### 11.1 Frontend #### 11.1.1 React Query ```typescript // DO: Query keys descriptivas y jerárquicas queryKey: ['dashboard', userId, 'coins'] queryKey: ['modules', moduleId, 'exercises'] // DO: Usar staleTime para reducir re-fetches staleTime: 5 * 60 * 1000, // 5 min // DO: Invalidar queries relacionadas después de mutations onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['dashboard'] }); queryClient.invalidateQueries({ queryKey: ['gamification', 'coins'] }); } // DON'T: Queries sin enabled cuando dependen de parámetros enabled: !!userId, // SIEMPRE verificar ``` #### 11.1.2 State Management ```typescript // DO: Zustand para global state, React Query para server state // Global UI state → Zustand // Server data → React Query // DO: Hooks para lógica reutilizable export function useDashboardData() { ... } // DON'T: Props drilling más de 2 niveles // Usar context o store ``` #### 11.1.3 Performance ```typescript // DO: Lazy load de mecánicas const DynamicMechanic = React.lazy(() => import(`@/features/mechanics/${mechanicType}`) ); // DO: Memoizar cálculos pesados const expNeeded = useMemo(() => calculateNextRankXP(currentRank), [currentRank] ); // DO: Debounce en búsquedas const debouncedSearch = useDebounce(searchQuery, 300); ``` ### 11.2 Backend #### 11.2.1 Controllers ```typescript // DO: DTOs con validación completa @Post('submit') @ApiOperation({ summary: 'Submit exercise completion' }) @ApiOkResponse({ type: SubmissionResultDto }) async submitExercise( @CurrentUser() user: User, @Param('exerciseId') exerciseId: string, @Body() dto: SubmitExerciseDto, ): Promise { return this.submissionService.submitExercise(user.id, exerciseId, dto); } ``` #### 11.2.2 Services ```typescript // DO: Transactions para operaciones atómicas async submitExercise(userId: string, dto: SubmitExerciseDto) { return this.dataSource.transaction(async (manager) => { // 1. Crear submission const submission = await manager.save(ExerciseSubmission, {...}); // 2. Actualizar progreso await manager.update(ModuleProgress, {...}); // 3. Otorgar XP y ML Coins await this.grantRewards(userId, submission, manager); // 4. Check achievements await this.checkAchievements(userId, submission, manager); return submission; }); } ``` #### 11.2.3 Optimización ```typescript // DO: Eager loading para evitar N+1 queries const exercises = await this.exercisesRepo.find({ where: { module_id: moduleId }, relations: ['module', 'submissions'], }); // DO: Cache para datos que cambian poco @Cacheable('ranks', 3600) // 1 hora async getRanks(): Promise { return this.ranksRepo.find(); } ``` --- ## 12. Testing ### 12.1 Tests Unitarios Frontend ```typescript // useDashboardData.test.ts describe('useDashboardData', () => { it('should fetch dashboard data successfully', async () => { const { result } = renderHook(() => useDashboardData(), { wrapper: createWrapper(), }); await waitFor(() => { expect(result.current.loading).toBe(false); }); expect(result.current.rank).toBeDefined(); expect(result.current.coins).toBeDefined(); }); }); ``` ### 12.2 Tests de Integración ```typescript // ExerciseSubmission.integration.test.ts describe('Exercise Submission Flow', () => { it('should complete exercise and grant rewards', async () => { const user = await createTestUser(); const exercise = await createTestExercise(); const response = await request(app.getHttpServer()) .post(`/progress/exercises/${exercise.id}/submit`) .set('Authorization', `Bearer ${user.token}`) .send({ answers: { q1: 'correct' }, timeSpent: 120, hintsUsed: 0, }) .expect(201); expect(response.body.xpEarned).toBeGreaterThan(0); expect(response.body.mlCoinsEarned).toBeGreaterThan(0); }); }); ``` --- ## 13. Checklist de Desarrollo ### 13.1 Nueva Funcionalidad - [ ] Definir types en `student/types/` o `@shared/types` - [ ] Crear/actualizar DTOs en backend - [ ] Implementar service en backend - [ ] Crear/modificar controller con guards - [ ] Agregar validaciones (class-validator) - [ ] Crear API service en frontend - [ ] Implementar custom hook si necesario - [ ] Crear componentes UI necesarios - [ ] Integrar en página correspondiente - [ ] Agregar tests unitarios - [ ] Probar responsive (mobile, tablet, desktop) - [ ] Documentar en Swagger (decoradores) - [ ] Actualizar esta guía si aplica ### 13.2 Code Review - [ ] Types alineados frontend/backend - [ ] Guards aplicados correctamente (JwtAuth mínimo) - [ ] Validación de DTOs completa - [ ] Error handling implementado - [ ] React Query keys descriptivas - [ ] Invalidación de cache correcta después de mutations - [ ] Loading y error states manejados - [ ] Responsive design verificado - [ ] Accessibility (ARIA labels, keyboard navigation) - [ ] Performance optimizado (memo, lazy load) --- ## 14. Troubleshooting ### 14.1 Problemas Comunes | Problema | Causa Probable | Solución | |----------|----------------|----------| | 401 Unauthorized | Token JWT expirado/inválido | Renovar token con refresh endpoint | | Data desactualizada | Cache no invalidado | `queryClient.invalidateQueries()` | | Types mismatch | Desync FE/BE | Regenerar types desde DTOs backend | | Exercise no se guarda | Auto-save disabled | Verificar `enabled` en `useExerciseAutoSave` | | XP no se actualiza | Estado local no sincroniza | Llamar `refresh()` de `useDashboardData` | | Achievements no se desbloquean | Condiciones no se cumplen | Verificar lógica en backend service | | Power-up no aplica | Item no en inventory | Verificar inventario antes de usar | ### 14.2 Debugging ```typescript // Habilitar logs de React Query en dev if (import.meta.env.DEV) { import('@tanstack/react-query-devtools').then(({ ReactQueryDevtools }) => { // Montar devtools }); } // Log de API calls apiClient.interceptors.request.use((config) => { console.log(`[API] ${config.method?.toUpperCase()} ${config.url}`); return config; }); // Log de state changes (Zustand) devtools(storeImpl, { name: 'RanksStore' }) ``` --- ## 15. Performance y Optimización ### 15.1 Frontend Optimization **Lazy Loading de Rutas:** ```typescript const DashboardComplete = lazy(() => import('./pages/DashboardComplete')); const ExercisePage = lazy(() => import('./pages/ExercisePage')); const GamificationPage = lazy(() => import('./pages/GamificationPage')); }> } /> } /> } /> ``` **Code Splitting:** ```typescript // Dynamic imports for mechanics const loadMechanic = (type: string) => { return import(`@/features/mechanics/${type}/${type}Exercise`); }; ``` **Image Optimization:** - Usar WebP para imágenes modernas - Lazy load de imágenes con `loading="lazy"` - Sprites para iconos pequeños ### 15.2 Backend Optimization **Database Indexing:** ```sql -- Indices críticos CREATE INDEX idx_exercise_submissions_user ON progress.exercise_submissions(user_id); CREATE INDEX idx_user_stats_total_xp ON gamification.user_stats(total_xp DESC); CREATE INDEX idx_achievements_trigger ON gamification.achievements(trigger); ``` **Query Optimization:** ```typescript // Usar select específico en vez de SELECT * const stats = await this.userStatsRepo.findOne({ where: { user_id: userId }, select: ['total_xp', 'total_ml_coins', 'current_streak'], }); ``` **Caching:** - Redis para leaderboards (TTL 5 min) - Cache de ranks/achievements (TTL 1 hora) - Invalidación al actualizar datos --- ## 16. Seguridad ### 16.1 Autenticación y Autorización **Guards:** - **JwtAuthGuard:** TODOS los endpoints (excepto public) - **RolesGuard:** Si endpoint específico para rol **Validación de Ownership:** ```typescript // Verificar que submission pertenece al usuario const submission = await this.submissionRepo.findOne({ where: { id: submissionId, user_id: userId // CRÍTICO } }); if (!submission) { throw new ForbiddenException('Not your submission'); } ``` ### 16.2 Validación de Datos ```typescript // DTOs con class-validator export class SubmitExerciseDto { @IsObject() @ValidateNested() answers!: Record; @IsNumber() @Min(0) @Max(7200) // Max 2 horas timeSpent!: number; @IsNumber() @Min(0) @Max(10) hintsUsed!: number; } ``` ### 16.3 Rate Limiting ```typescript // Exercise submission: max 100/día por usuario @ThrottlerGuard({ limit: 100, ttl: 86400 }) @Post('submit') async submitExercise(...) { ... } ``` --- ## 17. Referencias ### Documentos Complementarios del Portal Student | Documento | Descripción | |-----------|-------------| | [EXERCISE-MECHANICS-REFERENCE.md](./EXERCISE-MECHANICS-REFERENCE.md) | Referencia completa de 30+ mecánicas implementadas | | [GAMIFICATION-SYSTEM-GUIDE.md](./GAMIFICATION-SYSTEM-GUIDE.md) | Sistema de gamificación en profundidad | | [STUDENT-API-REFERENCE.md](./STUDENT-API-REFERENCE.md) | Referencia de 60+ APIs con ejemplos | ### Guías Generales - [COMPONENT-PATTERNS.md](./frontend/COMPONENT-PATTERNS.md) - Patrones de componentes - [HOOK-PATTERNS.md](./frontend/HOOK-PATTERNS.md) - Patrones de hooks - [REACT-QUERY-GUIDE.md](./frontend/REACT-QUERY-GUIDE.md) - Uso de React Query - [ZUSTAND-PATTERNS.md](./frontend/ZUSTAND-PATTERNS.md) - Patrones de Zustand - [TYPES-CONVENTIONS.md](./frontend/TYPES-CONVENTIONS.md) - Convenciones de types - [DTO-CONVENTIONS.md](./backend/DTO-CONVENTIONS.md) - Convenciones de DTOs - [ESTRUCTURA-MODULOS.md](./backend/ESTRUCTURA-MODULOS.md) - Estructura de módulos - [ESTANDARES-API-ROUTES.md](../../orchestration/directivas/ESTANDARES-API-ROUTES.md) - Rutas API ### Documentación de Arquitectura - [ADR-001: Sistema de Ranks Maya](../../97-adr/ADR-001-sistema-ranks-maya.md) - [ADR-002: ML Coins Economy](../../97-adr/ADR-002-ml-coins-economy.md) - [ADR-003: Exercise Mechanics](../../97-adr/ADR-003-exercise-mechanics.md) --- ## Changelog | Versión | Fecha | Cambios | |---------|-------|---------| | 1.0.0 | 2025-11-29 | Creación inicial - Documentación completa del Portal Student | --- **Mantenido por:** Tech Lead - GAMILIT Project **Última revisión:** 2025-11-29