- 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>
10 KiB
US-ADM-003: Dashboard de Maestro
Épica: EAI-005 (Plataforma de Maestro Básica) Sprint: Mes 1, Semana 2 Story Points: 8 SP Presupuesto: $3,200 MXN Prioridad: Alta (Alcance Inicial) Estado: ✅ Completada (Mes 1)
Descripción
Como profesor, quiero tener un dashboard general que me muestre un resumen de todas mis aulas para tener una vista panorámica de mi trabajo y acceder rápidamente a cada aula.
Contexto del Alcance Inicial:
Este es el dashboard principal del profesor al iniciar sesión. Muestra un resumen de todas sus aulas con estadísticas básicas y acceso rápido a analytics. NO incluye gráficas avanzadas, comparativas entre aulas, ni métricas de engagement (eso va a EXT-001 Portal de Maestros Completo).
Criterios de Aceptación
CA-01: Vista General de Aulas
- Grid/cards con todas las aulas del profesor
- Para cada aula muestra:
- Nombre y nivel/grado
-
total de estudiantes
- Progreso promedio (%)
-
de módulos asignados
- Acceso rápido a dashboard del aula (US-ANA-001)
- Acceso a lista de estudiantes (US-ADM-002)
CA-02: Resumen Global
- Cards con métricas totales:
- Total de aulas
- Total de estudiantes (suma de todas las aulas)
- Promedio general de progreso
- Destacar aula con mejor/peor progreso
CA-03: Actividad Reciente Global
- Feed de las últimas 10 actividades de TODAS las aulas
- Cada actividad muestra: estudiante, aula, actividad, timestamp
- Link rápido a perfil del estudiante
CA-04: Acciones Rápidas
- Botón "Crear Nueva Aula" (US-ADM-001)
- Selector de aula en header (dropdown para cambiar de contexto)
CA-05: Navegación
- Breadcrumb: Dashboard
- Sidebar con:
- Dashboard (esta vista)
- Mis Aulas (lista completa)
- Configuración (placeholder)
Especificaciones Técnicas
Backend
Endpoint Principal:
GET /api/teacher/dashboard
Response:
{
"summary": {
"totalClassrooms": 3,
"totalStudents": 75,
"averageProgress": 62.5
},
"classrooms": [
{
"id": "uuid",
"name": "Matemáticas 6A",
"level": "primaria",
"grade": 6,
"studentCount": 25,
"averageProgress": 65.5,
"moduleCount": 5,
"lastActivity": "2025-11-02T10:00:00Z"
}
],
"recentActivities": [
{
"id": "activity-uuid",
"studentName": "Juan Pérez",
"classroomName": "Matemáticas 6A",
"activityName": "Suma de fracciones",
"timestamp": "2025-11-02T10:30:00Z"
}
],
"insights": {
"bestPerformingClassroom": {
"id": "uuid",
"name": "Matemáticas 6A",
"progress": 75.5
},
"needsAttentionClassroom": {
"id": "uuid",
"name": "Ciencias 5B",
"progress": 45.2
}
}
}
Controller:
@Get('teacher/dashboard')
async getTeacherDashboard(@CurrentUser() teacher: User) {
return this.teacherService.getDashboard(teacher.id);
}
Service:
async getDashboard(teacherId: string) {
const classrooms = await this.getClassroomsSummary(teacherId);
const recentActivities = await this.getRecentActivitiesAcrossClassrooms(teacherId, 10);
const summary = {
totalClassrooms: classrooms.length,
totalStudents: classrooms.reduce((sum, c) => sum + c.studentCount, 0),
averageProgress: classrooms.length > 0
? classrooms.reduce((sum, c) => sum + c.averageProgress, 0) / classrooms.length
: 0
};
const sortedByProgress = [...classrooms].sort((a, b) => b.averageProgress - a.averageProgress);
return {
summary,
classrooms,
recentActivities,
insights: {
bestPerformingClassroom: sortedByProgress[0] || null,
needsAttentionClassroom: sortedByProgress[sortedByProgress.length - 1] || null
}
};
}
Frontend
Ruta:
/teacher/dashboard
Componente Principal:
// TeacherDashboard.tsx
export const TeacherDashboard = () => {
const { dashboardData, isLoading } = useTeacherDashboard();
const navigate = useNavigate();
if (isLoading) return <DashboardSkeleton />;
return (
<div className="teacher-dashboard">
<PageHeader
title="Dashboard"
subtitle={`Bienvenido, ${dashboardData.teacherName}`}
action={
<Button
onClick={() => navigate('/teacher/classrooms/new')}
leftIcon={<PlusIcon />}
>
Crear Aula
</Button>
}
/>
<SummaryCards summary={dashboardData.summary} />
<InsightsSection insights={dashboardData.insights} />
<ClassroomGrid
classrooms={dashboardData.classrooms}
onViewClassroom={(id) => navigate(`/teacher/classroom/${id}/dashboard`)}
/>
<RecentActivityFeed activities={dashboardData.recentActivities} />
</div>
);
};
Componente de Cards de Resumen:
// SummaryCards.tsx
export const SummaryCards = ({ summary }) => {
return (
<div className="summary-cards">
<SummaryCard
icon={<ClassroomIcon />}
label="Aulas"
value={summary.totalClassrooms}
/>
<SummaryCard
icon={<UsersIcon />}
label="Estudiantes"
value={summary.totalStudents}
/>
<SummaryCard
icon={<ProgressIcon />}
label="Progreso Promedio"
value={`${summary.averageProgress.toFixed(1)}%`}
/>
</div>
);
};
Componente de Insights:
// InsightsSection.tsx
export const InsightsSection = ({ insights }) => {
if (!insights.bestPerformingClassroom) return null;
return (
<div className="insights-section">
<InsightCard
type="success"
icon={<TrophyIcon />}
title="Mejor Desempeño"
classroom={insights.bestPerformingClassroom}
/>
{insights.needsAttentionClassroom && (
<InsightCard
type="warning"
icon={<AlertIcon />}
title="Requiere Atención"
classroom={insights.needsAttentionClassroom}
/>
)}
</div>
);
};
Componente de Grid de Aulas:
// ClassroomGrid.tsx
export const ClassroomGrid = ({ classrooms, onViewClassroom }) => {
if (classrooms.length === 0) {
return (
<EmptyState
icon={<ClassroomIcon />}
title="No tienes aulas creadas"
description="Crea tu primera aula para comenzar"
/>
);
}
return (
<div className="classroom-grid">
{classrooms.map(classroom => (
<ClassroomDashboardCard
key={classroom.id}
classroom={classroom}
onClick={() => onViewClassroom(classroom.id)}
/>
))}
</div>
);
};
const ClassroomDashboardCard = ({ classroom, onClick }) => {
return (
<Card className="classroom-dashboard-card" onClick={onClick}>
<CardHeader>
<h3>{classroom.name}</h3>
<Badge>{getLevelLabel(classroom.level)} {classroom.grade}°</Badge>
</CardHeader>
<CardBody>
<div className="stats">
<Stat
icon={<UsersIcon />}
label="Estudiantes"
value={classroom.studentCount}
/>
<Stat
icon={<ProgressIcon />}
label="Progreso"
value={`${classroom.averageProgress.toFixed(1)}%`}
/>
<Stat
icon={<ModulesIcon />}
label="Módulos"
value={classroom.moduleCount}
/>
</div>
<ProgressBar percentage={classroom.averageProgress} />
</CardBody>
<CardFooter>
<Button variant="primary" size="sm" fullWidth>
Ver Dashboard
</Button>
</CardFooter>
</Card>
);
};
Diseño UI/UX
Layout Desktop
+-------------------------------------------------------------------+
| Dashboard [+ Crear Aula] |
| Bienvenido, Prof. García |
+-------------------------------------------------------------------+
| [3 Aulas] [75 Estudiantes] [62.5% Progreso] |
+-------------------------------------------------------------------+
| 🏆 Mejor Desempeño: Matemáticas 6A (75.5%) |
| ⚠️ Requiere Atención: Ciencias 5B (45.2%) |
+-------------------------------------------------------------------+
| MIS AULAS |
| +------------------+ +------------------+ +------------------+ |
| | Matemáticas 6A | | Español 5B | | Ciencias 6A | |
| | Primaria - 6° | | Primaria - 5° | | Primaria - 6° | |
| | 👥 25 | 📊 65.5% | | 👥 30 | 📊 58% | | 👥 20 | 📊 64% | |
| | [████████░] 65% | | [███████░░] 58% | | [████████░] 64% | |
| | [Ver Dashboard] | | [Ver Dashboard] | | [Ver Dashboard] | |
| +------------------+ +------------------+ +------------------+ |
+-------------------------------------------------------------------+
| ACTIVIDAD RECIENTE |
| • Juan Pérez (Mat 6A) completó "Suma de fracciones" - 5 min |
| • Ana López (Esp 5B) completó "Comprensión lectora" - 10 min |
+-------------------------------------------------------------------+
Alcance Básico vs Extensiones
EAI-005 (Este alcance - Admin Base):
- ✅ Dashboard simple con resumen de aulas
- ✅ Métricas básicas (# estudiantes, progreso promedio)
- ✅ Grid de aulas con stats básicas
- ✅ Actividad reciente (últimas 10)
- ✅ Insights simples (mejor/peor aula)
EXT-001 (Extensión futura - Portal Maestros Completo):
- ⏳ Gráficas de tendencia de progreso
- ⏳ Comparativas entre aulas
- ⏳ Métricas de engagement
- ⏳ Dashboard personalizable (widgets)
- ⏳ Filtros por fecha
- ⏳ Exportación de reportes
Dependencias
Dependencias de User Stories:
- US-ADM-001 (aulas)
- US-ANA-001 (para navegación a dashboard de aula)
Estimación de Esfuerzo
Backend: 3 SP Frontend: 4 SP Testing: 1 SP
Total: 8 SP = $3,200 MXN