# C2: Guía de Sincronización Backend → Frontend **Fecha:** 2026-01-10 **Estado:** DOCUMENTADO **Objetivo:** Elevar coherencia Backend→Frontend de 28.2% a 75%+ --- ## Estado Actual ``` DTOs Backend: 124 total Types Frontend: 35 implementados Coverage: 28.2% DTOs Faltantes: 89 (71.8%) ``` --- ## Prioridad 1: Interfaces Críticas Faltantes ### 1.1 UserStats (CRÍTICO - Gamification Core) **Backend:** `apps/backend/src/modules/gamification/entities/user-stats.entity.ts` **Frontend a crear:** `apps/frontend/src/shared/types/gamification.types.ts` ```typescript // Estructura requerida (40 propiedades) export interface UserStats { id: string; user_id: string; tenant_id?: string; // Level & XP level: number; total_xp: number; xp_to_next_level: number; // Maya Rank System current_rank: MayaRank; rank_progress: number; // ML Coins ml_coins: number; ml_coins_earned_total: number; ml_coins_spent_total: number; // Streaks current_streak: number; max_streak: number; streak_started_at?: string; last_activity_date?: string; // Progress exercises_completed: number; exercises_correct: number; modules_completed: number; achievements_earned: number; missions_completed: number; // Rankings global_rank_position?: number; class_rank_position?: number; // Time tracking total_time_spent_seconds: number; average_session_duration_seconds: number; // Detailed stats accuracy_rate: number; fastest_completion_seconds?: number; comodines_used_total: number; hints_used_total: number; // Social friends_count: number; challenges_won: number; challenges_lost: number; // Metadata metadata?: Record; created_at: string; updated_at: string; } export type MayaRank = | 'ajaw' | 'nacom' | 'ah_kin' | 'halach_uinic' | 'kukul_kan'; ``` **Esfuerzo:** 2 horas **Impacto:** Desbloquea toda la UI de gamificación --- ### 1.2 Module Interface Completa **Backend:** `apps/backend/src/modules/educational/entities/module.entity.ts` **Frontend a actualizar:** `apps/frontend/src/shared/types/educational.types.ts` **Propiedades a agregar (31 faltantes):** ```typescript export interface Module { // Existentes... // Gamification (AGREGAR) xp_reward: number; ml_coins_reward: number; // Academic (AGREGAR) grade_levels: string[]; subjects: string[]; competencies: string[]; // Maya Rank (AGREGAR) maya_rank_required?: MayaRank; maya_rank_granted?: MayaRank; // Versioning (AGREGAR) version: number; version_notes?: string; reviewed_by?: string; reviewed_at?: string; // Metadata (AGREGAR) settings?: ModuleSettings; metadata?: Record; is_featured: boolean; is_demo_module: boolean; demo_duration_seconds?: number; // Prerequisites (AGREGAR) prerequisite_modules?: string[]; prerequisite_achievements?: string[]; // Statistics (AGREGAR) completion_rate?: number; average_score?: number; total_attempts?: number; } export interface ModuleSettings { allow_skip: boolean; show_hints: boolean; time_limit_seconds?: number; max_attempts?: number; } ``` **Esfuerzo:** 1.5 horas --- ### 1.3 ExerciseType Enum Completo **Backend:** Definido en múltiples lugares **Frontend a actualizar:** `apps/frontend/src/shared/types/educational.types.ts` ```typescript export enum ExerciseType { // Comprensión lectora CRUCIGRAMA = 'crucigrama', LINEA_TIEMPO = 'linea_tiempo', SOPA_LETRAS = 'sopa_letras', MAPA_CONCEPTUAL = 'mapa_conceptual', EMPAREJAMIENTO = 'emparejamiento', // Pensamiento crítico DETECTIVE_TEXTUAL = 'detective_textual', CONSTRUCCION_HIPOTESIS = 'construccion_hipotesis', PREDICCION_NARRATIVA = 'prediccion_narrativa', PUZZLE_CONTEXTO = 'puzzle_contexto', RUEDA_INFERENCIAS = 'rueda_inferencias', // Argumentación TRIBUNAL_OPINIONES = 'tribunal_opiniones', DEBATE_DIGITAL = 'debate_digital', ANALISIS_FUENTES = 'analisis_fuentes', PODCAST_ARGUMENTATIVO = 'podcast_argumentativo', MATRIZ_PERSPECTIVAS = 'matriz_perspectivas', // Media literacy VERIFICADOR_FAKE_NEWS = 'verificador_fake_news', INFOGRAFIA_INTERACTIVA = 'infografia_interactiva', QUIZ_TIKTOK = 'quiz_tiktok', NAVEGACION_HIPERTEXTUAL = 'navegacion_hipertextual', ANALISIS_MEMES = 'analisis_memes', // Escritura creativa DIARIO_INTERACTIVO = 'diario_interactivo', RESUMEN_VISUAL = 'resumen_visual', COMPRENSION_AUDITIVA = 'comprension_auditiva', COLLAGE_PRENSA = 'collage_prensa', TEXTO_MOVIMIENTO = 'texto_movimiento', CALL_TO_ACTION = 'call_to_action', // Nuevos (sincronizar con DB) CAPSULA_TIEMPO = 'capsula_tiempo', COLLAGE_DIGITAL = 'collage_digital', DIARIO_MULTIMEDIA = 'diario_multimedia', COMIC_DIGITAL = 'comic_digital', VIDEO_CARTA = 'video_carta', VERDADERO_FALSO = 'verdadero_falso', COMPLETAR_ESPACIOS = 'completar_espacios', } ``` **Componentes a actualizar:** - Exercise renderer switch/case - Exercise type selector - Exercise preview component - Exercise analytics dashboard **Esfuerzo:** 1-2 horas --- ### 1.4 Admin Module Types **Backend DTOs (24 total):** `apps/backend/src/modules/admin/dto/` **Frontend a crear:** - `apps/frontend/src/shared/types/admin.types.ts` - `apps/frontend/src/lib/api/admin.api.ts` ```typescript // admin.types.ts export interface OrganizationDto { id: string; name: string; slug: string; settings: OrganizationSettings; is_active: boolean; created_at: string; updated_at: string; } export interface UserDetailsDto { id: string; email: string; first_name: string; last_name: string; role: UserRole; organization_id?: string; is_active: boolean; last_login_at?: string; created_at: string; } export interface SystemHealthDto { status: 'healthy' | 'degraded' | 'down'; database: HealthCheck; cache: HealthCheck; storage: HealthCheck; uptime_seconds: number; version: string; } export interface HealthCheck { status: 'up' | 'down'; latency_ms: number; last_check: string; } // ... 20 DTOs más (ver backend) ``` **Esfuerzo:** 3 horas --- ## Prioridad 2: Interfaces Incompletas ### 2.1 Achievement Interface **Propiedades a agregar (13 faltantes):** ```typescript export interface Achievement { // Existentes... // AGREGAR: ml_coins_reward: number; xp_reward: number; difficulty_level: DifficultyLevel; unlock_message?: string; locked_message?: string; is_secret: boolean; // Renombrar de isHidden is_repeatable: boolean; max_completions?: number; cooldown_hours?: number; prerequisites?: string[]; trigger_type: AchievementTrigger; trigger_config: Record; tier: AchievementTier; } export type AchievementTrigger = | 'exercise_completion' | 'streak_milestone' | 'xp_threshold' | 'rank_promotion' | 'social_action'; export type AchievementTier = 'bronze' | 'silver' | 'gold' | 'platinum'; ``` **Esfuerzo:** 1 hora --- ### 2.2 Classroom Interface **Propiedades a agregar (16 faltantes):** ```typescript export interface Classroom { // Existentes... // AGREGAR: grade_level: string; section?: string; subject: string; academic_year: string; schedule?: ClassroomSchedule; meeting_url?: string; max_students: number; current_students: number; is_active: boolean; settings: ClassroomSettings; modules_assigned: string[]; start_date?: string; end_date?: string; cover_image_url?: string; description?: string; metadata?: Record; } export interface ClassroomSchedule { days: DayOfWeek[]; start_time: string; // HH:mm end_time: string; timezone: string; } export interface ClassroomSettings { allow_late_submissions: boolean; show_leaderboard: boolean; notify_teacher_on_completion: boolean; } ``` **Esfuerzo:** 1 hora --- ### 2.3 ExerciseSubmission Interface **Propiedades a agregar (10 faltantes):** ```typescript export interface ExerciseSubmission { // Existentes... // AGREGAR: comodines_used: ComodinUsage[]; hint_used: boolean; hints_count: number; ml_coins_spent: number; time_spent_seconds: number; attempt_number: number; status: SubmissionStatus; started_at: string; graded_at?: string; graded_by?: string; // 'auto' | user_id } export interface ComodinUsage { comodin_type: string; used_at: string; } export type SubmissionStatus = | 'in_progress' | 'submitted' | 'graded' | 'expired'; // NOTA: Remover attempt_id que no existe en backend ``` **Esfuerzo:** 45 minutos --- ## Prioridad 3: Módulos Sin Cobertura (0%) ### 3.1 Missions Module **Backend DTOs:** 3 **Archivos a crear:** - `apps/frontend/src/shared/types/missions.types.ts` ```typescript export interface Mission { id: string; name: string; description: string; mission_type: MissionType; target_value: number; current_progress: number; rewards: MissionRewards; expires_at?: string; is_completed: boolean; completed_at?: string; } export type MissionType = | 'daily' | 'weekly' | 'special' | 'event'; export interface MissionRewards { xp: number; ml_coins: number; achievement_id?: string; } ``` ### 3.2 Notifications Module **Backend DTOs:** 4 **Archivos a crear:** - `apps/frontend/src/shared/types/notifications.types.ts` ```typescript export interface Notification { id: string; user_id: string; type: NotificationType; title: string; message: string; data?: Record; is_read: boolean; created_at: string; read_at?: string; } export type NotificationType = | 'achievement_unlocked' | 'mission_completed' | 'level_up' | 'friend_request' | 'classroom_announcement' | 'system'; ``` ### 3.3 Powerups/Comodines Module **Backend DTOs:** 4 **Archivos a crear:** - `apps/frontend/src/shared/types/powerups.types.ts` ```typescript export interface Comodin { id: string; name: string; description: string; comodin_type: ComodinType; cost_ml_coins: number; effect_config: ComodinEffect; icon_url?: string; is_active: boolean; } export type ComodinType = | 'fifty_fifty' | 'extra_time' | 'hint' | 'skip_question' | 'double_xp'; export interface ComodinEffect { duration_seconds?: number; magnitude?: number; target?: string; } export interface ComodinInventory { user_id: string; comodin_id: string; quantity: number; acquired_at: string; } ``` ### 3.4 Content Module **Backend DTOs:** 6 **Similar a educational pero para contenido estático** **Esfuerzo total módulos:** ~9 horas --- ## Checklist de Implementación ### Fase 1: Interfaces Críticas (4-6 horas) - [ ] Crear `gamification.types.ts` con UserStats - [ ] Actualizar Module interface - [ ] Completar ExerciseType enum - [ ] Crear `admin.types.ts` ### Fase 2: Interfaces Incompletas (3 horas) - [ ] Actualizar Achievement interface - [ ] Actualizar Classroom interface - [ ] Actualizar ExerciseSubmission interface ### Fase 3: Módulos Faltantes (9 horas) - [ ] Crear `missions.types.ts` - [ ] Crear `notifications.types.ts` - [ ] Crear `powerups.types.ts` - [ ] Crear content types ### Fase 4: API Clients (3 horas) - [ ] Crear `admin.api.ts` - [ ] Crear `missions.api.ts` - [ ] Crear `notifications.api.ts` - [ ] Crear `powerups.api.ts` --- ## Métricas Objetivo | Métrica | Actual | Post-Fase 1 | Post-Fase 3 | |---------|--------|-------------|-------------| | DTOs implementados | 35 | 60 | 95 | | Coverage | 28.2% | 48% | 77% | | Interfaces críticas | 0/4 | 4/4 | 4/4 | | Módulos cubiertos | 5/9 | 6/9 | 9/9 | --- ## Notas de Naming Consistency ### Convención Recomendada Para mantener consistencia con backend NestJS: 1. **Propiedades:** `snake_case` (coincide con DB y backend) 2. **Types/Interfaces:** `PascalCase` 3. **Enums:** `SCREAMING_SNAKE_CASE` para values, `PascalCase` para type ### Transformaciones Automáticas Considerar implementar interceptor/transformer: ```typescript // api-client.ts import { snakeToCamel, camelToSnake } from './utils'; export const apiClient = { get: async (url: string): Promise => { const response = await fetch(url); const data = await response.json(); return snakeToCamel(data) as T; }, post: async (url: string, body: unknown): Promise => { const response = await fetch(url, { method: 'POST', body: JSON.stringify(camelToSnake(body)), }); return snakeToCamel(await response.json()) as T; }, }; ``` --- **Documentado por:** Documentation-Architect (Fase C2) **Fecha:** 2026-01-10 **Próximo paso:** Entregar a NEXUS-FRONTEND para implementación