feat(classes): optimize teacher dashboard ui and implement grade management
This commit is contained in:
@@ -122,6 +122,20 @@ export const getTeacherClasses = cache(async (params?: { teacherId?: string }):
|
||||
|
||||
const rows = await (async () => {
|
||||
try {
|
||||
const ownedIds = await db
|
||||
.select({ id: classes.id })
|
||||
.from(classes)
|
||||
.where(eq(classes.teacherId, teacherId))
|
||||
|
||||
const enrolledIds = await db
|
||||
.select({ id: classEnrollments.classId })
|
||||
.from(classEnrollments)
|
||||
.where(and(eq(classEnrollments.studentId, teacherId), eq(classEnrollments.status, "active")))
|
||||
|
||||
const allIds = Array.from(new Set([...ownedIds.map((x) => x.id), ...enrolledIds.map((x) => x.id)]))
|
||||
|
||||
if (allIds.length === 0) return []
|
||||
|
||||
return await db
|
||||
.select({
|
||||
id: classes.id,
|
||||
@@ -135,26 +149,11 @@ export const getTeacherClasses = cache(async (params?: { teacherId?: string }):
|
||||
})
|
||||
.from(classes)
|
||||
.leftJoin(classEnrollments, eq(classEnrollments.classId, classes.id))
|
||||
.where(eq(classes.teacherId, teacherId))
|
||||
.where(inArray(classes.id, allIds))
|
||||
.groupBy(classes.id, classes.schoolName, classes.name, classes.grade, classes.homeroom, classes.room, classes.invitationCode)
|
||||
.orderBy(asc(classes.schoolName), asc(classes.grade), asc(classes.name), asc(classes.homeroom), asc(classes.room))
|
||||
} catch {
|
||||
return await db
|
||||
.select({
|
||||
id: classes.id,
|
||||
schoolName: sql<string | null>`NULL`.as("schoolName"),
|
||||
name: classes.name,
|
||||
grade: classes.grade,
|
||||
homeroom: classes.homeroom,
|
||||
room: classes.room,
|
||||
invitationCode: sql<string | null>`NULL`.as("invitationCode"),
|
||||
studentCount: sql<number>`COALESCE(SUM(CASE WHEN ${classEnrollments.status} = 'active' THEN 1 ELSE 0 END), 0)`,
|
||||
})
|
||||
.from(classes)
|
||||
.leftJoin(classEnrollments, eq(classEnrollments.classId, classes.id))
|
||||
.where(eq(classes.teacherId, teacherId))
|
||||
.groupBy(classes.id, classes.name, classes.grade, classes.homeroom, classes.room)
|
||||
.orderBy(asc(classes.grade), asc(classes.name), asc(classes.homeroom), asc(classes.room))
|
||||
return []
|
||||
}
|
||||
})()
|
||||
|
||||
@@ -331,6 +330,143 @@ export const getAdminClasses = cache(async (): Promise<AdminClassListItem[]> =>
|
||||
return list
|
||||
})
|
||||
|
||||
export const getGradeManagedClasses = cache(async (userId: string): Promise<AdminClassListItem[]> => {
|
||||
const managedGradeIds = await db
|
||||
.select({ id: grades.id })
|
||||
.from(grades)
|
||||
.where(or(eq(grades.gradeHeadId, userId), eq(grades.teachingHeadId, userId)))
|
||||
|
||||
if (managedGradeIds.length === 0) return []
|
||||
|
||||
const gradeIds = managedGradeIds.map((g) => g.id)
|
||||
|
||||
const [rows, subjectRows] = await Promise.all([
|
||||
(async () => {
|
||||
try {
|
||||
return await db
|
||||
.select({
|
||||
id: classes.id,
|
||||
schoolName: classes.schoolName,
|
||||
schoolId: classes.schoolId,
|
||||
name: classes.name,
|
||||
grade: classes.grade,
|
||||
gradeId: classes.gradeId,
|
||||
homeroom: classes.homeroom,
|
||||
room: classes.room,
|
||||
invitationCode: classes.invitationCode,
|
||||
teacherId: users.id,
|
||||
teacherName: users.name,
|
||||
teacherEmail: users.email,
|
||||
studentCount: sql<number>`COALESCE(SUM(CASE WHEN ${classEnrollments.status} = 'active' THEN 1 ELSE 0 END), 0)`,
|
||||
createdAt: classes.createdAt,
|
||||
updatedAt: classes.updatedAt,
|
||||
})
|
||||
.from(classes)
|
||||
.innerJoin(users, eq(users.id, classes.teacherId))
|
||||
.leftJoin(classEnrollments, eq(classEnrollments.classId, classes.id))
|
||||
.where(inArray(classes.gradeId, gradeIds))
|
||||
.groupBy(
|
||||
classes.id,
|
||||
classes.schoolName,
|
||||
classes.schoolId,
|
||||
classes.name,
|
||||
classes.grade,
|
||||
classes.gradeId,
|
||||
classes.homeroom,
|
||||
classes.room,
|
||||
classes.invitationCode,
|
||||
users.id,
|
||||
users.name,
|
||||
users.email,
|
||||
classes.createdAt,
|
||||
classes.updatedAt
|
||||
)
|
||||
.orderBy(
|
||||
asc(classes.schoolName),
|
||||
asc(classes.grade),
|
||||
asc(classes.name),
|
||||
asc(classes.homeroom),
|
||||
asc(classes.room)
|
||||
)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})(),
|
||||
db
|
||||
.select({
|
||||
classId: classSubjectTeachers.classId,
|
||||
subject: classSubjectTeachers.subject,
|
||||
teacherId: users.id,
|
||||
teacherName: users.name,
|
||||
teacherEmail: users.email,
|
||||
})
|
||||
.from(classSubjectTeachers)
|
||||
.innerJoin(classes, eq(classes.id, classSubjectTeachers.classId))
|
||||
.leftJoin(users, eq(users.id, classSubjectTeachers.teacherId))
|
||||
.where(inArray(classes.gradeId, gradeIds))
|
||||
.orderBy(asc(classSubjectTeachers.classId), asc(classSubjectTeachers.subject)),
|
||||
])
|
||||
|
||||
const subjectsByClassId = new Map<string, Map<ClassSubject, TeacherOption | null>>()
|
||||
for (const r of subjectRows) {
|
||||
const subject = r.subject as ClassSubject
|
||||
if (!DEFAULT_CLASS_SUBJECTS.includes(subject)) continue
|
||||
const teacher =
|
||||
typeof r.teacherId === "string" && r.teacherId.length > 0
|
||||
? { id: r.teacherId, name: r.teacherName ?? "Unnamed", email: r.teacherEmail ?? "" }
|
||||
: null
|
||||
const bySubject = subjectsByClassId.get(r.classId) ?? new Map<ClassSubject, TeacherOption | null>()
|
||||
bySubject.set(subject, teacher)
|
||||
subjectsByClassId.set(r.classId, bySubject)
|
||||
}
|
||||
|
||||
const list = rows.map((r) => {
|
||||
const bySubject = subjectsByClassId.get(r.id)
|
||||
const subjectTeachers: ClassSubjectTeacherAssignment[] = DEFAULT_CLASS_SUBJECTS.map((subject) => ({
|
||||
subject,
|
||||
teacher: bySubject?.get(subject) ?? null,
|
||||
}))
|
||||
|
||||
return {
|
||||
id: r.id,
|
||||
schoolName: r.schoolName,
|
||||
schoolId: r.schoolId,
|
||||
name: r.name,
|
||||
grade: r.grade,
|
||||
gradeId: r.gradeId,
|
||||
homeroom: r.homeroom,
|
||||
room: r.room,
|
||||
invitationCode: r.invitationCode ?? null,
|
||||
teacher: {
|
||||
id: r.teacherId,
|
||||
name: r.teacherName ?? "Unnamed",
|
||||
email: r.teacherEmail,
|
||||
},
|
||||
subjectTeachers,
|
||||
studentCount: Number(r.studentCount ?? 0),
|
||||
createdAt: r.createdAt.toISOString(),
|
||||
updatedAt: r.updatedAt.toISOString(),
|
||||
}
|
||||
})
|
||||
|
||||
list.sort(compareClassLike)
|
||||
return list
|
||||
})
|
||||
|
||||
export const getManagedGrades = cache(async (userId: string) => {
|
||||
return await db
|
||||
.select({
|
||||
id: grades.id,
|
||||
name: grades.name,
|
||||
schoolId: grades.schoolId,
|
||||
schoolName: schools.name,
|
||||
})
|
||||
.from(grades)
|
||||
.innerJoin(schools, eq(schools.id, grades.schoolId))
|
||||
.where(or(eq(grades.gradeHeadId, userId), eq(grades.teachingHeadId, userId)))
|
||||
.orderBy(asc(schools.name), asc(grades.name))
|
||||
})
|
||||
|
||||
export const getStudentClasses = cache(async (studentId: string): Promise<StudentEnrolledClass[]> => {
|
||||
const id = studentId.trim()
|
||||
if (!id) return []
|
||||
@@ -345,9 +481,12 @@ export const getStudentClasses = cache(async (studentId: string): Promise<Studen
|
||||
grade: classes.grade,
|
||||
homeroom: classes.homeroom,
|
||||
room: classes.room,
|
||||
teacherName: users.name,
|
||||
teacherEmail: users.email,
|
||||
})
|
||||
.from(classEnrollments)
|
||||
.innerJoin(classes, eq(classes.id, classEnrollments.classId))
|
||||
.leftJoin(users, eq(users.id, classes.teacherId))
|
||||
.where(and(eq(classEnrollments.studentId, id), eq(classEnrollments.status, "active")))
|
||||
.orderBy(asc(classes.schoolName), asc(classes.grade), asc(classes.name), asc(classes.homeroom), asc(classes.room))
|
||||
} catch {
|
||||
@@ -359,9 +498,12 @@ export const getStudentClasses = cache(async (studentId: string): Promise<Studen
|
||||
grade: classes.grade,
|
||||
homeroom: classes.homeroom,
|
||||
room: classes.room,
|
||||
teacherName: users.name,
|
||||
teacherEmail: users.email,
|
||||
})
|
||||
.from(classEnrollments)
|
||||
.innerJoin(classes, eq(classes.id, classEnrollments.classId))
|
||||
.leftJoin(users, eq(users.id, classes.teacherId))
|
||||
.where(and(eq(classEnrollments.studentId, id), eq(classEnrollments.status, "active")))
|
||||
.orderBy(asc(classes.grade), asc(classes.name), asc(classes.homeroom), asc(classes.room))
|
||||
}
|
||||
@@ -374,6 +516,8 @@ export const getStudentClasses = cache(async (studentId: string): Promise<Studen
|
||||
grade: r.grade,
|
||||
homeroom: r.homeroom,
|
||||
room: r.room,
|
||||
teacherName: r.teacherName,
|
||||
teacherEmail: r.teacherEmail,
|
||||
}))
|
||||
|
||||
list.sort(compareClassLike)
|
||||
@@ -414,12 +558,13 @@ export const getStudentSchedule = cache(async (studentId: string): Promise<Stude
|
||||
})
|
||||
|
||||
export const getClassStudents = cache(
|
||||
async (params?: { classId?: string; q?: string; teacherId?: string }): Promise<ClassStudent[]> => {
|
||||
async (params?: { classId?: string; q?: string; status?: string; teacherId?: string }): Promise<ClassStudent[]> => {
|
||||
const teacherId = params?.teacherId ?? (await getDefaultTeacherId())
|
||||
if (!teacherId) return []
|
||||
|
||||
const classId = params?.classId?.trim()
|
||||
const q = params?.q?.trim().toLowerCase()
|
||||
const status = params?.status?.trim().toLowerCase()
|
||||
|
||||
const conditions: SQL[] = [eq(classes.teacherId, teacherId)]
|
||||
|
||||
@@ -427,6 +572,10 @@ export const getClassStudents = cache(
|
||||
conditions.push(eq(classes.id, classId))
|
||||
}
|
||||
|
||||
if (status === "active" || status === "inactive") {
|
||||
conditions.push(eq(classEnrollments.status, status))
|
||||
}
|
||||
|
||||
if (q && q.length > 0) {
|
||||
const needle = `%${q}%`
|
||||
conditions.push(
|
||||
@@ -439,9 +588,12 @@ export const getClassStudents = cache(
|
||||
id: users.id,
|
||||
name: users.name,
|
||||
email: users.email,
|
||||
image: users.image,
|
||||
gender: users.gender,
|
||||
classId: classes.id,
|
||||
className: classes.name,
|
||||
status: classEnrollments.status,
|
||||
joinedAt: classEnrollments.createdAt,
|
||||
})
|
||||
.from(classEnrollments)
|
||||
.innerJoin(classes, eq(classes.id, classEnrollments.classId))
|
||||
@@ -453,9 +605,12 @@ export const getClassStudents = cache(
|
||||
id: r.id,
|
||||
name: r.name ?? "Unnamed",
|
||||
email: r.email,
|
||||
image: r.image,
|
||||
gender: r.gender,
|
||||
classId: r.classId,
|
||||
className: r.className,
|
||||
status: r.status,
|
||||
joinedAt: r.joinedAt,
|
||||
}))
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user