| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- import { getServerSession } from 'next-auth'
- import { authOptions } from '@/lib/auth'
- import { redirect } from 'next/navigation'
- import { db } from '@/lib/db'
- import { teacherAssignments, sections, classes, periods, studentEnrollments, attendance, eq, and } from '@/lib/db/schema'
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
- import { BookOpen, Users, ClipboardCheck, Calendar } from 'lucide-react'
- import { DashboardLayout } from '@/components/dashboard-layout'
- interface TeacherStats {
- totalSections: number
- totalStudents: number
- attendanceRecords: number
- activePeriods: number
- }
- interface AssignedSection {
- id: string
- name: string
- className: string
- periodName: string
- studentCount: number
- maxStudents: number
- }
- async function getTeacherStats(teacherId: string): Promise<TeacherStats> {
- // Get teacher's assigned sections
- const assignedSections = await db
- .select({ sectionId: teacherAssignments.sectionId })
- .from(teacherAssignments)
- .where(eq(teacherAssignments.teacherId, teacherId))
- const sectionIds = assignedSections.map(a => a.sectionId)
- if (sectionIds.length === 0) {
- return {
- totalSections: 0,
- totalStudents: 0,
- attendanceRecords: 0,
- activePeriods: 0
- }
- }
- // Count total students enrolled in teacher's sections
- const studentCount = await db
- .select()
- .from(studentEnrollments)
- .where(eq(studentEnrollments.sectionId, sectionIds[0] as string)) // This is a simplified query
- // Count attendance records for teacher's sections
- const attendanceCount = await db
- .select()
- .from(attendance)
- .where(eq(attendance.sectionId, sectionIds[0] as string)) // This is a simplified query
- // Count active periods
- const activePeriods = await db
- .select()
- .from(periods)
- .where(eq(periods.isActive, true))
- return {
- totalSections: sectionIds.length,
- totalStudents: studentCount.length,
- attendanceRecords: attendanceCount.length,
- activePeriods: activePeriods.length
- }
- }
- async function getAssignedSections(teacherId: string): Promise<AssignedSection[]> {
- const result = await db
- .select({
- sectionId: sections.id,
- sectionName: sections.name,
- className: classes.name,
- periodName: periods.name,
- maxStudents: sections.maxStudents
- })
- .from(teacherAssignments)
- .innerJoin(sections, eq(teacherAssignments.sectionId, sections.id))
- .innerJoin(classes, eq(sections.classId, classes.id))
- .innerJoin(periods, eq(classes.periodId, periods.id))
- .where(eq(teacherAssignments.teacherId, teacherId))
- // Get student count for each section
- const sectionsWithStudents = await Promise.all(
- result.map(async (section) => {
- const studentCount = await db
- .select()
- .from(studentEnrollments)
- .where(eq(studentEnrollments.sectionId, section.sectionId))
- return {
- id: section.sectionId,
- name: section.sectionName,
- className: section.className,
- periodName: section.periodName,
- studentCount: studentCount.length,
- maxStudents: section.maxStudents || 0
- }
- })
- )
- return sectionsWithStudents
- }
- export default async function TeacherDashboard() {
- const session = await getServerSession(authOptions)
- if (!session || session.user.role !== 'teacher') {
- redirect('/auth/signin')
- }
- const stats = await getTeacherStats(session.user.id)
- const assignedSections = await getAssignedSections(session.user.id)
- const breadcrumbs = [
- { label: "Dashboard" }
- ]
- return (
- <DashboardLayout breadcrumbs={breadcrumbs}>
- <div className="space-y-6">
- <div>
- <h1 className="text-2xl font-bold text-gray-900">
- Bienvenido, {session.user.firstName} {session.user.lastName}
- </h1>
- <p className="text-gray-600">
- Gestiona tus clases y estudiantes desde aquí
- </p>
- </div>
- {/* Stats Cards */}
- <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
- <Card>
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium">
- Secciones Asignadas
- </CardTitle>
- <BookOpen className="h-4 w-4 text-muted-foreground" />
- </CardHeader>
- <CardContent>
- <div className="text-2xl font-bold">{stats.totalSections}</div>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium">
- Total Estudiantes
- </CardTitle>
- <Users className="h-4 w-4 text-muted-foreground" />
- </CardHeader>
- <CardContent>
- <div className="text-2xl font-bold">{stats.totalStudents}</div>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium">
- Registros de Asistencia
- </CardTitle>
- <ClipboardCheck className="h-4 w-4 text-muted-foreground" />
- </CardHeader>
- <CardContent>
- <div className="text-2xl font-bold">{stats.attendanceRecords}</div>
- </CardContent>
- </Card>
- <Card>
- <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
- <CardTitle className="text-sm font-medium">
- Períodos Activos
- </CardTitle>
- <Calendar className="h-4 w-4 text-muted-foreground" />
- </CardHeader>
- <CardContent>
- <div className="text-2xl font-bold">{stats.activePeriods}</div>
- </CardContent>
- </Card>
- </div>
- {/* Assigned Sections */}
- <Card>
- <CardHeader>
- <CardTitle>Mis Secciones</CardTitle>
- </CardHeader>
- <CardContent>
- {assignedSections.length === 0 ? (
- <p className="text-gray-500 text-center py-8">
- No tienes secciones asignadas actualmente.
- </p>
- ) : (
- <div className="space-y-4">
- {assignedSections.map((section) => (
- <div
- key={section.id}
- className="flex items-center justify-between p-4 border rounded-lg hover:bg-gray-50"
- >
- <div>
- <h3 className="font-medium">
- {section.className} - {section.name}
- </h3>
- <p className="text-sm text-gray-600">
- Período: {section.periodName}
- </p>
- </div>
- <div className="text-right">
- <p className="text-sm font-medium">
- {section.studentCount}/{section.maxStudents} estudiantes
- </p>
- <div className="w-24 bg-gray-200 rounded-full h-2 mt-1">
- <div
- className="bg-blue-600 h-2 rounded-full"
- style={{
- width: `${Math.min(
- (section.studentCount / section.maxStudents) * 100,
- 100
- )}%`
- }}
- ></div>
- </div>
- </div>
- </div>
- ))}
- </div>
- )}
- </CardContent>
- </Card>
- </div>
- </DashboardLayout>
- )
- }
|