- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
985 lines
21 KiB
Markdown
985 lines
21 KiB
Markdown
# Portal Teacher - API Reference
|
|
|
|
**Fecha de creacion:** 2025-11-29
|
|
**Version:** 1.0.0
|
|
**Estado:** VIGENTE
|
|
**Complementa:** PORTAL-TEACHER-GUIDE.md
|
|
|
|
---
|
|
|
|
## 1. Resumen de Endpoints
|
|
|
|
El Portal Teacher expone **45+ endpoints** organizados en 7 controladores:
|
|
|
|
| Controller | Base Path | Endpoints | Descripcion |
|
|
|------------|-----------|-----------|-------------|
|
|
| TeacherController | `/teacher` | 20 | Dashboard, progress, analytics, grading |
|
|
| TeacherClassroomsController | `/teacher/classrooms` | 12 | CRUD de aulas, estudiantes |
|
|
| InterventionAlertsController | `/teacher/alerts` | 5 | Alertas de intervencion |
|
|
| TeacherCommunicationController | `/teacher/messages` | 6 | Mensajes y comunicacion |
|
|
| TeacherContentController | `/teacher/content` | 5 | Contenido personalizado |
|
|
| ExerciseResponsesController | `/teacher/exercise-responses` | 4 | Respuestas de ejercicios |
|
|
| TeacherGradesController | `/teacher/grades` | 3 | Calificaciones |
|
|
|
|
---
|
|
|
|
## 2. Dashboard APIs
|
|
|
|
### 2.1 GET /teacher/dashboard/stats
|
|
|
|
Obtiene estadisticas generales del dashboard del teacher.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/dashboard/stats
|
|
Authorization: Bearer {token}
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"total_classrooms": 5,
|
|
"total_students": 127,
|
|
"active_students": 98,
|
|
"pending_submissions": 23,
|
|
"average_completion": 72.5,
|
|
"average_score": 85.3,
|
|
"alerts_count": 4,
|
|
"recent_activity_count": 15
|
|
}
|
|
```
|
|
|
|
**Frontend Hook:**
|
|
```typescript
|
|
// hooks/useTeacherDashboard.ts
|
|
export function useTeacherDashboard() {
|
|
const { data: stats } = useQuery({
|
|
queryKey: ['teacher', 'dashboard', 'stats'],
|
|
queryFn: () => teacherApi.getDashboardStats(),
|
|
staleTime: 60_000, // 1 minuto
|
|
});
|
|
|
|
return { stats };
|
|
}
|
|
```
|
|
|
|
### 2.2 GET /teacher/dashboard/activities
|
|
|
|
Obtiene actividades recientes.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/dashboard/activities?limit=10
|
|
Authorization: Bearer {token}
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"activities": [
|
|
{
|
|
"id": "uuid",
|
|
"type": "submission",
|
|
"student_id": "uuid",
|
|
"student_name": "Juan Perez",
|
|
"action": "submitted_exercise",
|
|
"exercise_name": "Timeline - Marie Curie",
|
|
"classroom_name": "5to A - Matematicas",
|
|
"timestamp": "2025-11-29T10:30:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2.3 GET /teacher/dashboard/alerts
|
|
|
|
Obtiene alertas de estudiantes en riesgo.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"alerts": [
|
|
{
|
|
"id": "uuid",
|
|
"student_id": "uuid",
|
|
"student_name": "Maria Garcia",
|
|
"type": "declining_trend",
|
|
"severity": "high",
|
|
"message": "Desempeno en declive en ultimas 2 semanas",
|
|
"classroom_name": "5to A",
|
|
"created_at": "2025-11-28T15:00:00Z"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 2.4 GET /teacher/dashboard/top-performers
|
|
|
|
Obtiene top estudiantes por desempeno.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/dashboard/top-performers?limit=5
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"students": [
|
|
{
|
|
"id": "uuid",
|
|
"name": "Ana Lopez",
|
|
"avatar_url": "https://...",
|
|
"classroom_name": "5to A",
|
|
"total_xp": 15000,
|
|
"maya_rank": "Arquitecto Maya",
|
|
"completion_rate": 95.5,
|
|
"average_score": 92.3
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Classrooms APIs
|
|
|
|
### 3.1 GET /teacher/classrooms
|
|
|
|
Lista todas las aulas del teacher.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/classrooms?page=1&limit=10&status=active&search=matematicas
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Param | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| page | number | No | Pagina (default: 1) |
|
|
| limit | number | No | Items por pagina (default: 10) |
|
|
| search | string | No | Buscar por nombre |
|
|
| status | string | No | active, inactive, archived, all |
|
|
| grade_level | string | No | Filtrar por nivel |
|
|
| subject | string | No | Filtrar por materia |
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"name": "5to A - Matematicas",
|
|
"code": "5A-MAT-2025",
|
|
"grade_level": "5to",
|
|
"subject": "Matematicas",
|
|
"student_count": 28,
|
|
"active_students": 25,
|
|
"average_progress": 72.5,
|
|
"status": "active",
|
|
"is_owner": true,
|
|
"created_at": "2025-01-15T10:00:00Z"
|
|
}
|
|
],
|
|
"total": 5,
|
|
"page": 1,
|
|
"limit": 10,
|
|
"total_pages": 1
|
|
}
|
|
```
|
|
|
|
**Frontend Hook:**
|
|
```typescript
|
|
// hooks/useClassrooms.ts
|
|
export function useClassrooms(filters?: GetClassroomsQueryDto) {
|
|
const query = useQuery({
|
|
queryKey: ['teacher', 'classrooms', filters],
|
|
queryFn: () => classroomsApi.getAll(filters),
|
|
});
|
|
|
|
const createMutation = useMutation({
|
|
mutationFn: classroomsApi.create,
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['teacher', 'classrooms'] });
|
|
},
|
|
});
|
|
|
|
return {
|
|
classrooms: query.data?.data ?? [],
|
|
isLoading: query.isLoading,
|
|
createClassroom: createMutation.mutate,
|
|
isCreating: createMutation.isPending,
|
|
};
|
|
}
|
|
```
|
|
|
|
### 3.2 POST /teacher/classrooms
|
|
|
|
Crea una nueva aula.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/classrooms
|
|
Content-Type: application/json
|
|
Authorization: Bearer {token}
|
|
|
|
{
|
|
"name": "6to B - Ciencias",
|
|
"grade_level": "6to",
|
|
"subject": "Ciencias",
|
|
"description": "Clase de ciencias naturales",
|
|
"max_students": 35,
|
|
"settings": {
|
|
"allow_late_submissions": true,
|
|
"auto_grade_enabled": false
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response (201):**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"name": "6to B - Ciencias",
|
|
"code": "6B-CIE-2025-ABC123",
|
|
"grade_level": "6to",
|
|
"subject": "Ciencias",
|
|
"student_count": 0,
|
|
"status": "active",
|
|
"is_owner": true,
|
|
"created_at": "2025-11-29T10:00:00Z"
|
|
}
|
|
```
|
|
|
|
### 3.3 GET /teacher/classrooms/:id/students
|
|
|
|
Obtiene estudiantes de un aula.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/classrooms/uuid/students?page=1&limit=20&sort_by=progress&sort_order=desc
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"user_id": "uuid",
|
|
"name": "Juan Perez",
|
|
"email": "juan@example.com",
|
|
"avatar_url": "https://...",
|
|
"status": "active",
|
|
"enrolled_at": "2025-02-01T10:00:00Z",
|
|
"progress": {
|
|
"completion_percentage": 75.5,
|
|
"average_score": 85.3,
|
|
"total_xp": 12500,
|
|
"maya_rank": "Constructor Maya",
|
|
"exercises_completed": 45,
|
|
"exercises_total": 60
|
|
},
|
|
"last_activity": "2025-11-28T15:30:00Z",
|
|
"is_blocked": false
|
|
}
|
|
],
|
|
"total": 28,
|
|
"page": 1,
|
|
"limit": 20,
|
|
"total_pages": 2
|
|
}
|
|
```
|
|
|
|
### 3.4 GET /teacher/classrooms/:id/progress
|
|
|
|
Obtiene progreso detallado del aula por modulo.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"classroomData": {
|
|
"id": "uuid",
|
|
"name": "5to A - Matematicas",
|
|
"student_count": 28,
|
|
"active_students": 25,
|
|
"average_completion": 72.5,
|
|
"average_score": 85.3,
|
|
"total_exercises": 60,
|
|
"completed_exercises": 45
|
|
},
|
|
"moduleProgress": [
|
|
{
|
|
"module_id": "uuid",
|
|
"module_name": "Modulo 1: Marie Curie - Primera Exploracion",
|
|
"module_order": 1,
|
|
"completion_percentage": 85.5,
|
|
"average_score": 88.3,
|
|
"students_completed": 22,
|
|
"students_in_progress": 4,
|
|
"students_not_started": 2,
|
|
"average_time_minutes": 120.5,
|
|
"exercises": [
|
|
{
|
|
"exercise_id": "uuid",
|
|
"exercise_name": "Timeline - Vida de Marie Curie",
|
|
"mechanic_type": "timeline",
|
|
"completion_rate": 92.0,
|
|
"average_score": 87.5,
|
|
"average_attempts": 1.3
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Student Progress APIs
|
|
|
|
### 4.1 GET /teacher/students/:studentId/progress
|
|
|
|
Obtiene progreso completo de un estudiante.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/students/uuid/progress?include_exercises=true&date_from=2025-01-01
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"student": {
|
|
"id": "uuid",
|
|
"name": "Juan Perez",
|
|
"email": "juan@example.com"
|
|
},
|
|
"summary": {
|
|
"total_xp": 15000,
|
|
"ml_coins_balance": 2500,
|
|
"maya_rank": "Arquitecto Maya",
|
|
"level": 12,
|
|
"completion_percentage": 78.5,
|
|
"average_score": 86.2,
|
|
"total_time_minutes": 1250,
|
|
"streak_days": 15
|
|
},
|
|
"modules": [
|
|
{
|
|
"module_id": "uuid",
|
|
"module_name": "Modulo 1",
|
|
"status": "completed",
|
|
"completion_percentage": 100,
|
|
"average_score": 92.5,
|
|
"time_spent_minutes": 180,
|
|
"completed_at": "2025-11-15T10:00:00Z"
|
|
}
|
|
],
|
|
"achievements": [
|
|
{
|
|
"id": "uuid",
|
|
"name": "Primera Victoria",
|
|
"description": "Completar primer ejercicio",
|
|
"icon_url": "https://...",
|
|
"unlocked_at": "2025-02-01T15:00:00Z"
|
|
}
|
|
],
|
|
"activity_timeline": [
|
|
{
|
|
"date": "2025-11-28",
|
|
"exercises_completed": 3,
|
|
"xp_earned": 450,
|
|
"time_spent_minutes": 45
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 4.2 GET /teacher/students/:studentId/insights
|
|
|
|
Obtiene insights AI del estudiante.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"student_id": "uuid",
|
|
"generated_at": "2025-11-29T10:00:00Z",
|
|
"risk_level": "low",
|
|
"strengths": [
|
|
"Excelente en ejercicios de comprension literal",
|
|
"Alta consistencia en entregas",
|
|
"Buen manejo del tiempo"
|
|
],
|
|
"weaknesses": [
|
|
"Dificultad en inferencias complejas",
|
|
"Tendencia a respuestas apresuradas en critica"
|
|
],
|
|
"predictions": {
|
|
"completion_probability": 0.92,
|
|
"estimated_completion_date": "2025-12-15",
|
|
"risk_of_dropout": 0.05
|
|
},
|
|
"recommendations": [
|
|
{
|
|
"type": "exercise",
|
|
"priority": "high",
|
|
"message": "Recomendar mas ejercicios de inferencia",
|
|
"suggested_exercises": ["uuid1", "uuid2"]
|
|
},
|
|
{
|
|
"type": "intervention",
|
|
"priority": "medium",
|
|
"message": "Programar sesion de retroalimentacion"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 4.3 POST /teacher/students/:studentId/note
|
|
|
|
Agrega nota de teacher sobre estudiante.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/students/uuid/note
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"classroom_id": "uuid",
|
|
"content": "Estudiante muestra mejora notable en ultimas semanas",
|
|
"is_private": true,
|
|
"tags": ["mejora", "seguimiento"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Grading APIs
|
|
|
|
### 5.1 GET /teacher/submissions
|
|
|
|
Obtiene submissions pendientes de calificar.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/submissions?status=pending&classroom_id=uuid&page=1&limit=20
|
|
```
|
|
|
|
**Query Parameters:**
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| status | string | pending, graded, all |
|
|
| classroom_id | string | Filtrar por aula |
|
|
| assignment_id | string | Filtrar por tarea |
|
|
| student_id | string | Filtrar por estudiante |
|
|
| module_id | string | Filtrar por modulo |
|
|
| date_from | string | Fecha desde (ISO) |
|
|
| date_to | string | Fecha hasta (ISO) |
|
|
| sort_by | string | submitted_at, score, student_name |
|
|
| sort_order | string | asc, desc |
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"student": {
|
|
"id": "uuid",
|
|
"name": "Juan Perez",
|
|
"avatar_url": "https://..."
|
|
},
|
|
"exercise": {
|
|
"id": "uuid",
|
|
"name": "Timeline - Marie Curie",
|
|
"mechanic_type": "timeline"
|
|
},
|
|
"classroom": {
|
|
"id": "uuid",
|
|
"name": "5to A"
|
|
},
|
|
"submitted_at": "2025-11-28T15:30:00Z",
|
|
"auto_score": 85.5,
|
|
"final_score": null,
|
|
"status": "pending",
|
|
"attempt_number": 1,
|
|
"time_spent_seconds": 320,
|
|
"answers": { /* respuestas del estudiante */ }
|
|
}
|
|
],
|
|
"total": 23,
|
|
"page": 1,
|
|
"limit": 20
|
|
}
|
|
```
|
|
|
|
### 5.2 POST /teacher/submissions/:id/feedback
|
|
|
|
Califica y proporciona feedback.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/submissions/uuid/feedback
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"score": 90,
|
|
"feedback": "Excelente trabajo en la organizacion cronologica",
|
|
"strengths": ["Precision en fechas", "Conexiones logicas"],
|
|
"areas_to_improve": ["Agregar mas contexto historico"],
|
|
"xp_bonus": 50,
|
|
"requires_revision": false
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"id": "uuid",
|
|
"status": "graded",
|
|
"final_score": 90,
|
|
"feedback": "Excelente trabajo...",
|
|
"graded_at": "2025-11-29T10:30:00Z",
|
|
"graded_by": "uuid",
|
|
"xp_awarded": 150
|
|
}
|
|
```
|
|
|
|
### 5.3 POST /teacher/submissions/bulk-grade
|
|
|
|
Califica multiples submissions.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/submissions/bulk-grade
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"submissions": [
|
|
{ "id": "uuid1", "score": 85, "feedback": "Buen trabajo" },
|
|
{ "id": "uuid2", "score": 92, "feedback": "Excelente" },
|
|
{ "id": "uuid3", "score": 78, "feedback": "Puede mejorar" }
|
|
],
|
|
"apply_auto_xp": true
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"processed": 3,
|
|
"successful": 3,
|
|
"failed": 0,
|
|
"results": [
|
|
{ "id": "uuid1", "status": "success" },
|
|
{ "id": "uuid2", "status": "success" },
|
|
{ "id": "uuid3", "status": "success" }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. Analytics APIs
|
|
|
|
### 6.1 GET /teacher/analytics/classroom/:id
|
|
|
|
Analiticas detalladas de un aula.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"classroom_id": "uuid",
|
|
"period": {
|
|
"from": "2025-01-01",
|
|
"to": "2025-11-29"
|
|
},
|
|
"overview": {
|
|
"total_students": 28,
|
|
"active_students": 25,
|
|
"average_completion": 72.5,
|
|
"average_score": 85.3,
|
|
"total_submissions": 1250,
|
|
"total_time_hours": 450
|
|
},
|
|
"performance_distribution": {
|
|
"excellent": 8, // 90-100
|
|
"good": 12, // 80-89
|
|
"average": 5, // 70-79
|
|
"below_average": 2, // 60-69
|
|
"struggling": 1 // <60
|
|
},
|
|
"completion_trend": [
|
|
{ "week": "2025-W45", "completion_rate": 68.5 },
|
|
{ "week": "2025-W46", "completion_rate": 71.2 },
|
|
{ "week": "2025-W47", "completion_rate": 72.5 }
|
|
],
|
|
"engagement_metrics": {
|
|
"average_sessions_per_week": 3.5,
|
|
"average_session_duration_minutes": 35,
|
|
"peak_activity_hour": 16,
|
|
"most_active_day": "Tuesday"
|
|
},
|
|
"at_risk_students": [
|
|
{
|
|
"student_id": "uuid",
|
|
"name": "Maria Garcia",
|
|
"risk_level": "high",
|
|
"reason": "No activity in 7 days"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 6.2 GET /teacher/analytics/economy
|
|
|
|
Analiticas de economia ML Coins.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"overview": {
|
|
"total_circulation": 125000,
|
|
"average_balance": 980,
|
|
"median_balance": 850,
|
|
"gini_coefficient": 0.32
|
|
},
|
|
"distribution": {
|
|
"ranges": [
|
|
{ "range": "0-500", "count": 15, "percentage": 12.0 },
|
|
{ "range": "501-1000", "count": 45, "percentage": 36.0 },
|
|
{ "range": "1001-2000", "count": 40, "percentage": 32.0 },
|
|
{ "range": "2001-5000", "count": 20, "percentage": 16.0 },
|
|
{ "range": "5001+", "count": 5, "percentage": 4.0 }
|
|
]
|
|
},
|
|
"top_earners": [
|
|
{
|
|
"student_id": "uuid",
|
|
"name": "Ana Lopez",
|
|
"balance": 8500,
|
|
"weekly_earnings": 450,
|
|
"maya_rank": "Arquitecto Maya"
|
|
}
|
|
],
|
|
"spending_patterns": {
|
|
"comodines": 35000,
|
|
"customizations": 15000,
|
|
"power_ups": 8000
|
|
}
|
|
}
|
|
```
|
|
|
|
### 6.3 GET /teacher/analytics/achievements
|
|
|
|
Estadisticas de logros por aula.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"classroom_id": "uuid",
|
|
"total_achievements": 45,
|
|
"total_unlocks": 892,
|
|
"achievements": [
|
|
{
|
|
"id": "uuid",
|
|
"name": "Primera Victoria",
|
|
"description": "Completar primer ejercicio",
|
|
"category": "progress",
|
|
"unlock_count": 28,
|
|
"unlock_percentage": 100,
|
|
"average_unlock_time_days": 2.5
|
|
},
|
|
{
|
|
"id": "uuid",
|
|
"name": "Maestro del Tiempo",
|
|
"description": "Completar Timeline perfecto",
|
|
"category": "mastery",
|
|
"unlock_count": 12,
|
|
"unlock_percentage": 42.8,
|
|
"average_unlock_time_days": 15.3
|
|
}
|
|
],
|
|
"rarest_achievements": [
|
|
{
|
|
"id": "uuid",
|
|
"name": "Leyenda Maya",
|
|
"unlock_count": 2,
|
|
"unlock_percentage": 7.1
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Intervention Alerts APIs
|
|
|
|
### 7.1 GET /teacher/alerts
|
|
|
|
Lista alertas de intervencion.
|
|
|
|
**Request:**
|
|
```http
|
|
GET /api/teacher/alerts?status=active&severity=high&classroom_id=uuid
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"data": [
|
|
{
|
|
"id": "uuid",
|
|
"student": {
|
|
"id": "uuid",
|
|
"name": "Carlos Mendez",
|
|
"avatar_url": "https://..."
|
|
},
|
|
"classroom": {
|
|
"id": "uuid",
|
|
"name": "5to A"
|
|
},
|
|
"type": "declining_trend",
|
|
"severity": "high",
|
|
"status": "active",
|
|
"message": "Desempeno en declive: -15% en ultimas 2 semanas",
|
|
"details": {
|
|
"previous_average": 85.5,
|
|
"current_average": 70.2,
|
|
"trend_period_days": 14
|
|
},
|
|
"suggested_actions": [
|
|
"Programar reunion con estudiante",
|
|
"Revisar ejercicios con dificultad",
|
|
"Contactar a padres si persiste"
|
|
],
|
|
"created_at": "2025-11-27T10:00:00Z"
|
|
}
|
|
],
|
|
"total": 4,
|
|
"by_severity": {
|
|
"critical": 1,
|
|
"high": 2,
|
|
"medium": 1,
|
|
"low": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
### 7.2 PATCH /teacher/alerts/:id/resolve
|
|
|
|
Resuelve una alerta.
|
|
|
|
**Request:**
|
|
```http
|
|
PATCH /api/teacher/alerts/uuid/resolve
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"resolution_notes": "Reunion realizada, estudiante comprometido a mejorar",
|
|
"actions_taken": ["Reunion con estudiante", "Plan de recuperacion"],
|
|
"follow_up_date": "2025-12-05"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 8. Bonus Coins APIs
|
|
|
|
### 8.1 POST /teacher/students/:studentId/bonus
|
|
|
|
Otorga bonificacion de ML Coins.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/students/uuid/bonus
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"amount": 100,
|
|
"reason": "Excelente participacion en clase",
|
|
"category": "participation",
|
|
"notify_student": true
|
|
}
|
|
```
|
|
|
|
**Response (201):**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"transaction": {
|
|
"id": "uuid",
|
|
"amount": 100,
|
|
"type": "teacher_bonus",
|
|
"reason": "Excelente participacion en clase",
|
|
"granted_by": "uuid",
|
|
"granted_at": "2025-11-29T10:30:00Z"
|
|
},
|
|
"student_new_balance": 1850
|
|
}
|
|
```
|
|
|
|
**Frontend Hook:**
|
|
```typescript
|
|
// hooks/useGrantBonus.ts
|
|
export function useGrantBonus() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({ studentId, data }: { studentId: string; data: GrantBonusDto }) =>
|
|
bonusCoinsApi.grantBonus(studentId, data),
|
|
onSuccess: (_, { studentId }) => {
|
|
// Invalidar queries relacionadas
|
|
queryClient.invalidateQueries({ queryKey: ['teacher', 'students', studentId] });
|
|
queryClient.invalidateQueries({ queryKey: ['teacher', 'analytics', 'economy'] });
|
|
toast.success('Bonificacion otorgada exitosamente');
|
|
},
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Reports APIs
|
|
|
|
### 9.1 POST /teacher/reports/generate
|
|
|
|
Genera reporte PDF/Excel.
|
|
|
|
**Request:**
|
|
```http
|
|
POST /api/teacher/reports/generate
|
|
Content-Type: application/json
|
|
|
|
{
|
|
"format": "pdf",
|
|
"report_type": "student_insights",
|
|
"classroom_id": "uuid",
|
|
"student_ids": ["uuid1", "uuid2"],
|
|
"include_sections": [
|
|
"summary",
|
|
"progress",
|
|
"achievements",
|
|
"insights",
|
|
"recommendations"
|
|
],
|
|
"date_range": {
|
|
"from": "2025-01-01",
|
|
"to": "2025-11-29"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response (200):**
|
|
- Content-Type: application/pdf
|
|
- Content-Disposition: attachment; filename="student-insights-report.pdf"
|
|
- Binary PDF content
|
|
|
|
---
|
|
|
|
## 10. Error Handling
|
|
|
|
### 10.1 Codigos de Error Comunes
|
|
|
|
| Code | Description | Resolution |
|
|
|------|-------------|------------|
|
|
| 400 | Bad Request | Validar datos de entrada |
|
|
| 401 | Unauthorized | Token invalido o expirado |
|
|
| 403 | Forbidden | Sin acceso al recurso |
|
|
| 404 | Not Found | Recurso no existe |
|
|
| 409 | Conflict | Duplicado o conflicto |
|
|
| 429 | Too Many Requests | Rate limit excedido |
|
|
| 500 | Internal Error | Contactar soporte |
|
|
|
|
### 10.2 Formato de Error
|
|
|
|
```json
|
|
{
|
|
"statusCode": 403,
|
|
"message": "Teacher does not have access to this classroom",
|
|
"error": "Forbidden",
|
|
"timestamp": "2025-11-29T10:30:00Z",
|
|
"path": "/api/teacher/classrooms/uuid"
|
|
}
|
|
```
|
|
|
|
### 10.3 Manejo en Frontend
|
|
|
|
```typescript
|
|
// hooks/useErrorHandler.ts
|
|
export function useApiError() {
|
|
const handleError = useCallback((error: AxiosError) => {
|
|
const status = error.response?.status;
|
|
const message = (error.response?.data as any)?.message;
|
|
|
|
switch (status) {
|
|
case 401:
|
|
// Redirigir a login
|
|
window.location.href = '/login';
|
|
break;
|
|
case 403:
|
|
toast.error('No tienes acceso a este recurso');
|
|
break;
|
|
case 404:
|
|
toast.error('Recurso no encontrado');
|
|
break;
|
|
case 429:
|
|
toast.error('Demasiadas solicitudes. Intenta de nuevo en un momento.');
|
|
break;
|
|
default:
|
|
toast.error(message || 'Error inesperado');
|
|
}
|
|
}, []);
|
|
|
|
return { handleError };
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 11. Rate Limiting
|
|
|
|
| Endpoint Category | Rate Limit | Window |
|
|
|-------------------|------------|--------|
|
|
| Dashboard | 60 req | 1 min |
|
|
| Analytics | 30 req | 1 min |
|
|
| Grading | 100 req | 1 min |
|
|
| Reports | 10 req | 1 min |
|
|
| Bonus Coins | 20 req | 1 min |
|
|
|
|
---
|
|
|
|
## 12. Websocket Events
|
|
|
|
El Portal Teacher puede suscribirse a eventos en tiempo real:
|
|
|
|
```typescript
|
|
// Suscribirse a eventos
|
|
socket.on('student:submission', (data) => {
|
|
// Nueva submission recibida
|
|
queryClient.invalidateQueries({ queryKey: ['teacher', 'submissions'] });
|
|
});
|
|
|
|
socket.on('student:alert', (data) => {
|
|
// Nueva alerta de estudiante
|
|
queryClient.invalidateQueries({ queryKey: ['teacher', 'alerts'] });
|
|
toast.warning(`Alerta: ${data.message}`);
|
|
});
|
|
|
|
socket.on('student:progress', (data) => {
|
|
// Estudiante completo ejercicio
|
|
queryClient.invalidateQueries({
|
|
queryKey: ['teacher', 'classrooms', data.classroom_id, 'progress']
|
|
});
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## Changelog
|
|
|
|
| Version | Fecha | Cambios |
|
|
|---------|-------|---------|
|
|
| 1.0.0 | 2025-11-29 | Creacion inicial |
|