# Guia de Desarrollo - Portal Teacher

**Fecha de creacion:** 2025-11-29
**Version:** 1.0.0
**Estado:** VIGENTE
**Aplica a:** apps/frontend/src/apps/teacher/ + apps/backend/src/modules/teacher/

---

## 1. Vision General

### 1.1 Proposito

El Portal Teacher es la interfaz principal para docentes en GAMILIT. Proporciona herramientas para:

- **Gestion de Aulas:** Crear, administrar y monitorear classrooms
- **Seguimiento de Estudiantes:** Progreso, desempeno, alertas
- **Asignaciones:** Crear y gestionar tareas/ejercicios
- **Comunicacion:** Mensajes y feedback a estudiantes
- **Analitica:** Dashboards e insights de aprendizaje
- **Gamificacion:** Bonificaciones, logros, economia de aula
- **Reportes:** Generacion de informes PDF/Excel

### 1.2 Usuarios Objetivo

| Rol | Acceso | Funcionalidades |
|-----|--------|-----------------|
| Teacher | Completo | Todas las funcionalidades del portal |
| Admin | Supervision | Vista de todas las aulas + configuracion |

---

## 2. Arquitectura

### 2.1 Estructura de Carpetas

#### Frontend (apps/frontend/src/apps/teacher/)

```
teacher/
├── index.ts                    # Barrel export principal
├── layouts/
│   └── TeacherLayout.tsx       # Layout principal con navegacion
├── pages/                      # Paginas del portal (19 paginas)
│   ├── TeacherDashboardPage.tsx
│   ├── TeacherClassesPage.tsx
│   ├── TeacherStudentsPage.tsx
│   ├── TeacherAssignmentsPage.tsx
│   ├── TeacherAlertsPage.tsx
│   ├── TeacherAnalyticsPage.tsx
│   ├── TeacherGamificationPage.tsx
│   ├── TeacherReportsPage.tsx
│   ├── TeacherCommunicationPage.tsx
│   ├── TeacherContentPage.tsx
│   ├── TeacherProgressPage.tsx
│   ├── TeacherMonitoringPage.tsx
│   ├── TeacherExerciseResponsesPage.tsx
│   ├── TeacherResourcesPage.tsx
│   └── TeacherSettingsPage.tsx     # 🆕 Configuración del profesor
├── components/                 # Componentes organizados por dominio
│   ├── dashboard/              # Componentes del dashboard
│   ├── assignments/            # Gestion de tareas
│   ├── alerts/                 # Alertas de intervencion
│   ├── analytics/              # Graficas y metricas
│   ├── progress/               # Progreso de estudiantes
│   ├── monitoring/             # Monitoreo en tiempo real
│   ├── reports/                # Generacion de reportes
│   ├── responses/              # Respuestas de ejercicios
│   ├── communication/          # Mensajes y anuncios
│   ├── collaboration/          # Compartir recursos
│   └── index.ts
├── hooks/                      # Custom hooks (17 hooks)
│   ├── useTeacherDashboard.ts
│   ├── useClassrooms.ts
│   ├── useAssignments.ts
│   ├── useStudentProgress.ts
│   ├── useAnalytics.ts
│   ├── useInterventionAlerts.ts
│   ├── useGrading.ts
│   ├── useGrantBonus.ts
│   ├── useEconomyAnalytics.ts
│   ├── useStudentsEconomy.ts
│   ├── useAchievementsStats.ts
│   ├── useTeacherMessages.ts
│   ├── useTeacherContent.ts
│   ├── useExerciseResponses.ts
│   └── index.ts
└── types/
    └── index.ts                # 40+ interfaces/types
```

#### Backend (apps/backend/src/modules/teacher/)

```
teacher/
├── teacher.module.ts           # Modulo NestJS principal
├── index.ts                    # Barrel exports
├── controllers/                # 7 controllers
│   ├── teacher.controller.ts           # Analytics, progress, insights
│   ├── teacher-classrooms.controller.ts
│   ├── teacher-grades.controller.ts
│   ├── teacher-communication.controller.ts
│   ├── teacher-content.controller.ts
│   ├── intervention-alerts.controller.ts
│   └── exercise-responses.controller.ts
├── services/                   # 14 services
│   ├── teacher-dashboard.service.ts
│   ├── teacher-classrooms-crud.service.ts
│   ├── student-progress.service.ts
│   ├── analytics.service.ts
│   ├── grading.service.ts
│   ├── intervention-alerts.service.ts
│   ├── student-risk-alert.service.ts    # CRON job
│   ├── ml-predictor.service.ts          # Predicciones ML
│   ├── reports.service.ts
│   ├── bonus-coins.service.ts
│   ├── teacher-messages.service.ts
│   ├── teacher-content.service.ts
│   ├── exercise-responses.service.ts
│   └── student-blocking.service.ts
├── dto/                        # Data Transfer Objects
│   ├── analytics.dto.ts
│   ├── classroom.dto.ts
│   ├── classroom-response.dto.ts
│   ├── classroom-progress.dto.ts
│   ├── grades.dto.ts
│   ├── grading.dto.ts
│   ├── grant-bonus.dto.ts
│   ├── teacher-messages.dto.ts
│   ├── teacher-content.dto.ts
│   ├── teacher-notes.dto.ts
│   ├── reports.dto.ts
│   ├── exercise-responses.dto.ts
│   ├── intervention-alerts.dto.ts
│   └── student-blocking/
├── entities/                   # Entidades TypeORM
│   ├── student-intervention-alert.entity.ts
│   ├── message.entity.ts
│   ├── teacher-content.entity.ts
│   └── teacher-report.entity.ts
├── guards/                     # Guards de autorizacion
│   ├── teacher.guard.ts
│   └── classroom-ownership.guard.ts
├── interfaces/
│   └── ml-predictor.interface.ts
└── __tests__/                  # Tests unitarios
```

### 2.2 Diagrama de Dependencias

```
┌─────────────────────────────────────────────────────────────────┐
│                        FRONTEND                                  │
├─────────────────────────────────────────────────────────────────┤
│  Pages ──────► Components ──────► Hooks ──────► API Services    │
│                    │                   │                         │
│                    └───────────────────┼─────► Types             │
└────────────────────────────────────────┼─────────────────────────┘
                                         │
                                    HTTP/REST
                                         │
┌────────────────────────────────────────▼─────────────────────────┐
│                        BACKEND                                    │
├──────────────────────────────────────────────────────────────────┤
│  Controllers ──────► Services ──────► Repositories ──────► DB    │
│       │                  │                                       │
│       └──────────────────┼─────► Guards                          │
│                          │                                       │
│                          └─────► External Modules                │
│                                  (Auth, Social, Progress, etc.)  │
└──────────────────────────────────────────────────────────────────┘
```

---

## 3. Patrones de Diseno

### 3.1 Frontend Patterns

#### 3.1.1 Page + Hook Pattern

Cada pagina tiene un hook correspondiente que encapsula la logica:

```typescript
// Pattern: Page con Hook dedicado

// TeacherDashboardPage.tsx
export const TeacherDashboardPage: React.FC = () => {
  const {
    stats,
    classrooms,
    pendingSubmissions,
    alerts,
    isLoading,
    error,
    refetch,
  } = useTeacherDashboard();

  if (isLoading) return <DashboardSkeleton />;
  if (error) return <ErrorDisplay error={error} />;

  return (
    <TeacherLayout>
      <TeacherDashboardHero stats={stats} />
      <ClassroomsGrid classrooms={classrooms} />
      <PendingSubmissionsList submissions={pendingSubmissions} />
      <StudentAlerts alerts={alerts} />
    </TeacherLayout>
  );
};

// useTeacherDashboard.ts
export function useTeacherDashboard(): UseTeacherDashboardReturn {
  const { data: stats, isLoading: statsLoading } = useQuery({
    queryKey: ['teacher', 'dashboard', 'stats'],
    queryFn: () => teacherApi.getDashboardStats(),
  });

  const { data: classrooms, isLoading: classroomsLoading } = useQuery({
    queryKey: ['teacher', 'classrooms'],
    queryFn: () => classroomsApi.getTeacherClassrooms(),
  });

  // ... mas queries

  return {
    stats,
    classrooms,
    isLoading: statsLoading || classroomsLoading,
    // ...
  };
}
```

#### 3.1.2 Component Composition

Componentes organizados por dominio, compuestos desde componentes mas pequenos:

```typescript
// dashboard/index.ts - Barrel export
export { TeacherDashboardHero } from './TeacherDashboardHero';
export { ClassroomsGrid } from './ClassroomsGrid';
export { ClassroomCard } from './ClassroomCard';
export { PendingSubmissionsList } from './PendingSubmissionsList';
export { StudentAlerts } from './StudentAlerts';
export { QuickActionsPanel } from './QuickActionsPanel';
export { RecentAssignmentsList } from './RecentAssignmentsList';
export { CreateClassroomModal } from './CreateClassroomModal';
export { CreateAssignmentModal } from './CreateAssignmentModal';
export { GradeSubmissionModal } from './GradeSubmissionModal';
```

#### 3.1.3 Modal Pattern

Modales para acciones complejas:

```typescript
// Pattern: Modal con form interno

interface CreateClassroomModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSuccess: (classroom: Classroom) => void;
}

export const CreateClassroomModal: React.FC<CreateClassroomModalProps> = ({
  isOpen,
  onClose,
  onSuccess,
}) => {
  const { mutate: createClassroom, isPending } = useMutation({
    mutationFn: classroomsApi.create,
    onSuccess: (data) => {
      onSuccess(data);
      onClose();
    },
  });

  return (
    <Modal isOpen={isOpen} onClose={onClose}>
      <ClassroomForm
        onSubmit={createClassroom}
        isLoading={isPending}
        onCancel={onClose}
      />
    </Modal>
  );
};
```

### 3.2 Backend Patterns

#### 3.2.1 Guard-Based Authorization

```typescript
// Pattern: Guards para autorizacion

@Controller('teacher')
@UseGuards(JwtAuthGuard, TeacherGuard)  // Requiere autenticacion + rol teacher
@ApiTags('Teacher')
export class TeacherController {

  @Get('classrooms/:classroomId/students')
  @UseGuards(ClassroomOwnershipGuard)  // Verifica propiedad del aula
  async getClassroomStudents(
    @Param('classroomId') classroomId: string,
    @CurrentUser() teacher: User,
  ): Promise<StudentListDto[]> {
    return this.studentProgressService.getClassroomStudents(classroomId);
  }
}
```

#### 3.2.2 TeacherGuard

```typescript
// guards/teacher.guard.ts
@Injectable()
export class TeacherGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;

    if (!user) return false;

    // Verificar rol teacher o admin
    const hasTeacherRole = user.roles?.some(
      (role: UserRole) =>
        role.role?.name === 'teacher' || role.role?.name === 'admin'
    );

    return hasTeacherRole;
  }
}
```

#### 3.2.3 ClassroomOwnershipGuard

```typescript
// guards/classroom-ownership.guard.ts
@Injectable()
export class ClassroomOwnershipGuard implements CanActivate {
  constructor(
    @InjectRepository(TeacherClassroom, 'social')
    private teacherClassroomRepo: Repository<TeacherClassroom>,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    const classroomId = request.params.classroomId;

    if (!classroomId || !user?.id) return false;

    // Verificar que el teacher tiene acceso al classroom
    const teacherClassroom = await this.teacherClassroomRepo.findOne({
      where: {
        teacher_id: user.id,
        classroom_id: classroomId,
      },
    });

    return !!teacherClassroom;
  }
}
```

#### 3.2.4 Service Layer Pattern

```typescript
// Pattern: Service con cache y multi-datasource

@Injectable()
export class AnalyticsService {
  constructor(
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    @InjectRepository(ModuleProgress, 'progress')
    private moduleProgressRepo: Repository<ModuleProgress>,
    @InjectRepository(ExerciseSubmission, 'progress')
    private submissionRepo: Repository<ExerciseSubmission>,
  ) {}

  async getClassroomAnalytics(classroomId: string): Promise<ClassroomAnalyticsDto> {
    // Intentar cache primero
    const cacheKey = `classroom:${classroomId}:analytics`;
    const cached = await this.cacheManager.get<ClassroomAnalyticsDto>(cacheKey);
    if (cached) return cached;

    // Calcular analytics
    const analytics = await this.calculateAnalytics(classroomId);

    // Guardar en cache (5 min TTL)
    await this.cacheManager.set(cacheKey, analytics, 300_000);

    return analytics;
  }
}
```

#### 3.2.5 CRON Jobs para Alertas

```typescript
// Pattern: Scheduled jobs para deteccion de riesgo

@Injectable()
export class StudentRiskAlertService {
  constructor(
    private readonly interventionAlertsService: InterventionAlertsService,
    private readonly mlPredictorService: MlPredictorService,
  ) {}

  @Cron('0 */6 * * *') // Cada 6 horas
  async checkStudentRisks(): Promise<void> {
    const students = await this.getActiveStudents();

    for (const student of students) {
      const riskLevel = await this.mlPredictorService.predictRisk(student.id);

      if (riskLevel === 'high') {
        await this.interventionAlertsService.createAlert({
          student_id: student.id,
          type: 'declining_trend',
          priority: 'high',
          message: `Estudiante ${student.name} muestra patron de riesgo`,
        });
      }
    }
  }
}
```

---

## 4. Buenas Practicas

### 4.1 Frontend

#### 4.1.1 Hooks

```typescript
// DO: Hooks especificos por funcionalidad
export function useClassrooms() { ... }
export function useClassroomStudents(classroomId: string) { ... }
export function useCreateClassroom() { ... }

// DON'T: Un hook gigante que hace todo
export function useTeacher() { ... } // Evitar
```

#### 4.1.2 Types

```typescript
// DO: Types especificos y documentados
/**
 * Estado de un estudiante en el monitoreo
 * @see Backend: StudentMonitoringDto
 */
export type StudentStatus = 'active' | 'inactive' | 'offline';

// DO: Alineacion con backend
export interface Classroom {
  id: string;
  name: string;
  student_count: number; // Backend: current_students_count
  created_at: string;    // ISO string (JSON serialization)
}
```

#### 4.1.3 Queries

```typescript
// DO: Query keys descriptivas y anidadas
const { data } = useQuery({
  queryKey: ['teacher', 'classrooms', classroomId, 'students'],
  queryFn: () => api.getClassroomStudents(classroomId),
  enabled: !!classroomId,
});

// DO: Invalidar queries relacionadas en mutations
const { mutate } = useMutation({
  mutationFn: api.createAssignment,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ['teacher', 'assignments'] });
    queryClient.invalidateQueries({ queryKey: ['teacher', 'dashboard'] });
  },
});
```

### 4.2 Backend

#### 4.2.1 Controllers

```typescript
// DO: Decoradores completos para Swagger
@Get('classrooms/:id')
@UseGuards(ClassroomOwnershipGuard)
@ApiOperation({ summary: 'Obtener detalle de aula' })
@ApiParam({ name: 'id', description: 'ID del classroom' })
@ApiOkResponse({ type: ClassroomDetailDto })
@ApiNotFoundResponse({ description: 'Aula no encontrada' })
async getClassroom(@Param('id') id: string): Promise<ClassroomDetailDto> {
  return this.classroomService.findById(id);
}
```

#### 4.2.2 Services

```typescript
// DO: Logging y error handling
@Injectable()
export class BonusCoinsService {
  private readonly logger = new Logger(BonusCoinsService.name);

  async grantBonus(teacherId: string, dto: GrantBonusDto): Promise<void> {
    this.logger.log(`Teacher ${teacherId} granting ${dto.amount} coins to ${dto.studentId}`);

    try {
      await this.mlCoinsService.addTransaction({
        user_id: dto.studentId,
        amount: dto.amount,
        type: 'teacher_bonus',
        description: dto.reason,
        granted_by: teacherId,
      });
    } catch (error) {
      this.logger.error(`Failed to grant bonus: ${error.message}`);
      throw new InternalServerErrorException('Error al otorgar bonificacion');
    }
  }
}
```

#### 4.2.3 DTOs

```typescript
// DO: Validacion completa con mensajes
export class GrantBonusDto {
  @ApiProperty({ description: 'ID del estudiante' })
  @IsUUID('4', { message: 'student_id debe ser UUID valido' })
  student_id!: string;

  @ApiProperty({ description: 'Cantidad de ML Coins', minimum: 1, maximum: 1000 })
  @IsNumber()
  @Min(1, { message: 'Minimo 1 ML Coin' })
  @Max(1000, { message: 'Maximo 1000 ML Coins' })
  amount!: number;

  @ApiPropertyOptional({ description: 'Razon de la bonificacion' })
  @IsOptional()
  @IsString()
  @MaxLength(500)
  reason?: string;
}
```

---

## 5. APIs del Portal Teacher

### 5.1 Endpoints Principales

| Metodo | Endpoint | Descripcion | Guard |
|--------|----------|-------------|-------|
| GET | `/teacher/dashboard/stats` | Estadisticas del dashboard | TeacherGuard |
| GET | `/teacher/classrooms` | Lista de aulas del teacher | TeacherGuard |
| POST | `/teacher/classrooms` | Crear nueva aula | TeacherGuard |
| GET | `/teacher/classrooms/:id/students` | Estudiantes del aula | ClassroomOwnership |
| GET | `/teacher/classrooms/:id/progress` | Progreso del aula | ClassroomOwnership |
| GET | `/teacher/assignments` | Lista de tareas | TeacherGuard |
| POST | `/teacher/assignments` | Crear tarea | TeacherGuard |
| GET | `/teacher/alerts` | Alertas de intervencion | TeacherGuard |
| PATCH | `/teacher/alerts/:id/resolve` | Resolver alerta | TeacherGuard |
| GET | `/teacher/analytics/:classroomId` | Analytics del aula | ClassroomOwnership |
| POST | `/teacher/bonus-coins` | Otorgar bonificacion | TeacherGuard |
| GET | `/teacher/exercise-responses` | Respuestas de ejercicios | TeacherGuard |
| POST | `/teacher/grades/:submissionId` | Calificar submission | TeacherGuard |
| GET | `/teacher/messages` | Mensajes enviados | TeacherGuard |
| POST | `/teacher/messages` | Enviar mensaje | TeacherGuard |

### 5.2 Frontend API Services

```
services/api/teacher/
├── teacherApi.ts              # Dashboard y general
├── classroomsApi.ts           # CRUD de aulas
├── assignmentsApi.ts          # Gestion de tareas
├── studentProgressApi.ts      # Progreso estudiantes
├── analyticsApi.ts            # Analiticas
├── interventionAlertsApi.ts   # Alertas
├── gradingApi.ts              # Calificaciones
├── bonusCoinsApi.ts           # Bonificaciones
├── exerciseResponsesApi.ts    # Respuestas
├── teacherMessagesApi.ts      # Comunicacion
├── teacherContentApi.ts       # Contenido
└── index.ts                   # Barrel export
```

---

## 6. Seguridad

### 6.1 Autorizacion

1. **JwtAuthGuard:** Verifica token JWT valido
2. **TeacherGuard:** Verifica rol teacher/admin
3. **ClassroomOwnershipGuard:** Verifica acceso al aula especifica

### 6.2 Reglas de Acceso

```yaml
Teacher puede:
  - Ver/editar SOLO sus propias aulas
  - Ver estudiantes SOLO de sus aulas
  - Calificar submissions SOLO de sus aulas
  - Otorgar bonificaciones SOLO a estudiantes de sus aulas

Teacher NO puede:
  - Ver aulas de otros teachers
  - Acceder a datos de estudiantes fuera de sus aulas
  - Modificar configuracion del sistema
  - Crear/eliminar usuarios
```

### 6.3 Validacion de Datos

```typescript
// Siempre validar pertenencia antes de operaciones
async gradeSubmission(teacherId: string, submissionId: string, grade: number) {
  const submission = await this.getSubmission(submissionId);

  // Verificar que el submission pertenece a un aula del teacher
  const hasAccess = await this.verifyTeacherOwnership(
    teacherId,
    submission.classroom_id
  );

  if (!hasAccess) {
    throw new ForbiddenException('No tiene acceso a esta submission');
  }

  // Proceder con calificacion
}
```

---

## 7. Testing

### 7.1 Tests Unitarios Backend

```typescript
// teacher-classrooms.controller.spec.ts
describe('TeacherClassroomsController', () => {
  let controller: TeacherClassroomsController;
  let service: TeacherClassroomsCrudService;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      controllers: [TeacherClassroomsController],
      providers: [
        { provide: TeacherClassroomsCrudService, useValue: mockService },
      ],
    }).compile();

    controller = module.get(TeacherClassroomsController);
  });

  it('should return classrooms for teacher', async () => {
    mockService.findByTeacher.mockResolvedValue([mockClassroom]);

    const result = await controller.getClassrooms(mockUser);

    expect(result).toHaveLength(1);
    expect(mockService.findByTeacher).toHaveBeenCalledWith(mockUser.id);
  });
});
```

### 7.2 Tests Frontend

```typescript
// useTeacherDashboard.test.ts
describe('useTeacherDashboard', () => {
  it('should fetch dashboard data', async () => {
    const { result } = renderHook(() => useTeacherDashboard(), {
      wrapper: QueryClientProvider,
    });

    await waitFor(() => {
      expect(result.current.isLoading).toBe(false);
    });

    expect(result.current.stats).toBeDefined();
    expect(result.current.classrooms).toBeDefined();
  });
});
```

---

## 8. Checklist de Desarrollo

### 8.1 Nueva Funcionalidad

- [ ] Definir tipos en `teacher/types/index.ts`
- [ ] Crear DTO en backend `teacher/dto/`
- [ ] Implementar service en `teacher/services/`
- [ ] Crear/modificar controller
- [ ] Agregar guards si necesario
- [ ] Crear API service en frontend
- [ ] Implementar hook en `teacher/hooks/`
- [ ] Crear componentes necesarios
- [ ] Integrar en pagina correspondiente
- [ ] Agregar tests unitarios
- [ ] Documentar en Swagger (decoradores)

### 8.2 Code Review

- [ ] Guards aplicados correctamente
- [ ] Validacion de DTOs completa
- [ ] Error handling implementado
- [ ] Logs apropiados en services
- [ ] Types alineados frontend/backend
- [ ] Query keys descriptivas
- [ ] Invalidacion de cache correcta

---

## 9. Troubleshooting

### 9.1 Problemas Comunes

| Problema | Causa | Solucion |
|----------|-------|----------|
| 403 Forbidden | Guard rechaza | Verificar rol y ownership |
| Data desactualizada | Cache | Invalidar queries manualmente |
| Types mismatch | Desync FE/BE | Regenerar types con OpenAPI |
| Performance lenta | Queries N+1 | Usar relations en TypeORM |

### 9.2 Debugging

```typescript
// Habilitar logs en development
if (process.env.NODE_ENV === 'development') {
  apiClient.interceptors.request.use((config) => {
    console.log(`[Teacher API] ${config.method?.toUpperCase()} ${config.url}`);
    return config;
  });
}
```

---

## 10. Referencias

### Documentos Complementarios del Portal Teacher

| Documento | Descripcion |
|-----------|-------------|
| [PORTAL-TEACHER-API-REFERENCE.md](./PORTAL-TEACHER-API-REFERENCE.md) | Referencia completa de 45+ APIs con ejemplos |
| [PORTAL-TEACHER-FLOWS.md](./PORTAL-TEACHER-FLOWS.md) | Flujos de datos, diagramas e integracion |

### Guias Generales

- [COMPONENT-PATTERNS.md](./frontend/COMPONENT-PATTERNS.md) - Patrones de componentes
- [HOOK-PATTERNS.md](./frontend/HOOK-PATTERNS.md) - Patrones de hooks
- [DTO-CONVENTIONS.md](./backend/DTO-CONVENTIONS.md) - Convenciones de DTOs
- [ESTRUCTURA-MODULOS.md](./backend/ESTRUCTURA-MODULOS.md) - Estructura de modulos
- [ESTANDARES-API-ROUTES.md](../../orchestration/directivas/ESTANDARES-API-ROUTES.md) - Rutas API

---

## Changelog

| Version | Fecha | Cambios |
|---------|-------|---------|
| 1.1.0 | 2025-11-29 | Agregada TeacherSettingsPage (/teacher/settings) |
| 1.0.0 | 2025-11-29 | Creacion inicial |
