From ceef74f1afc8d766f6346874d23c3838dccef5bf Mon Sep 17 00:00:00 2001 From: Adriaan Jacquet Date: Tue, 4 Mar 2025 15:50:20 +0100 Subject: [PATCH] feat: controller en service laag toegevoegd voor student/:id/classes --- backend/src/controllers/students.ts | 53 ++++++++++++++++++-- backend/src/data/classes/class-repository.ts | 7 +++ backend/src/interfaces/classes.ts | 17 +++++++ backend/src/routes/class.ts | 2 +- backend/src/routes/student.ts | 20 ++------ backend/src/services/students.ts | 51 ++++++++++++++++++- 6 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 backend/src/interfaces/classes.ts diff --git a/backend/src/controllers/students.ts b/backend/src/controllers/students.ts index b129eb57..9b4b8f3c 100644 --- a/backend/src/controllers/students.ts +++ b/backend/src/controllers/students.ts @@ -1,13 +1,31 @@ import { Request, Response } from 'express'; -import { getStudentById } from "../services/students"; +import { getStudent, getStudentClasses, getStudentClassIds } from '../services/students'; +import { ClassDTO } from '../interfaces/classes'; -export async function getStudent( +export async function getAllStudentsHandler ( + req: Request, + res: Response, +): Promise { + try { + res.json({ + students: [ + '0', + '1', + ] + }); + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getStudentHandler( req: Request, res: Response, ): Promise { try { const username = req.params.id; - const student = await getStudentById(username); + const student = await getStudent(username); if (!student) { res.status(404).json({ error: "Student not found" }); @@ -21,7 +39,34 @@ export async function getStudent( } res.json(student); } - + + } catch (error) { + console.error('Error fetching learning objects:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} + +export async function getStudentClassesHandler ( + req: Request, + res: Response, +): Promise { + try { + const full = req.query.full === 'true'; + const username = req.params.id; + + let classes: ClassDTO[] | string[]; + if (full) classes = await getStudentClasses(username); + else classes = await getStudentClassIds(username); + + res.json({ + classes: classes, + endpoints: { + self: `${req.baseUrl}/${req.params.id}`, + classes: `${req.baseUrl}/${req.params.id}/invitations`, + questions: `${req.baseUrl}/${req.params.id}/assignments`, + students: `${req.baseUrl}/${req.params.id}/students`, + } + }); } catch (error) { console.error('Error fetching learning objects:', error); res.status(500).json({ error: 'Internal server error' }); diff --git a/backend/src/data/classes/class-repository.ts b/backend/src/data/classes/class-repository.ts index e3b9f959..a9455323 100644 --- a/backend/src/data/classes/class-repository.ts +++ b/backend/src/data/classes/class-repository.ts @@ -1,5 +1,6 @@ import { DwengoEntityRepository } from '../dwengo-entity-repository.js'; import { Class } from '../../entities/classes/class.entity.js'; +import { Student } from '../../entities/users/student.entity.js'; export class ClassRepository extends DwengoEntityRepository { public findById(id: string): Promise { @@ -8,4 +9,10 @@ export class ClassRepository extends DwengoEntityRepository { public deleteById(id: string): Promise { return this.deleteWhere({ classId: id }); } + public findByStudent(student: Student): Promise { + return this.find( + { students: student }, + { populate: ["students", "teachers"] } // voegt student en teacher objecten toe + ) + } } diff --git a/backend/src/interfaces/classes.ts b/backend/src/interfaces/classes.ts new file mode 100644 index 00000000..78731b59 --- /dev/null +++ b/backend/src/interfaces/classes.ts @@ -0,0 +1,17 @@ +import { ClassJoinRequest } from "../entities/classes/class-join-request.entity"; +import { Student } from "../entities/users/student.entity"; +import { Teacher } from "../entities/users/teacher.entity"; + +export interface ClassDTO { + id: string; + displayName: string; + teachers: string[]; + students: string[]; + joinRequests: string[]; + endpoints?: { + classes: string; + questions: string; + invitations: string; + groups: string; + }; +} diff --git a/backend/src/routes/class.ts b/backend/src/routes/class.ts index e554a7f2..f310367d 100644 --- a/backend/src/routes/class.ts +++ b/backend/src/routes/class.ts @@ -19,7 +19,7 @@ router.get('/:id', (req, res) => { teachers: [ '0' ], students: [ '0' ], joinRequests: [ '0' ], - links: { + endpoints: { self: `${req.baseUrl}/${req.params.id}`, classes: `${req.baseUrl}/${req.params.id}/invitations`, questions: `${req.baseUrl}/${req.params.id}/assignments`, diff --git a/backend/src/routes/student.ts b/backend/src/routes/student.ts index 6a6280e6..ca74d2f7 100644 --- a/backend/src/routes/student.ts +++ b/backend/src/routes/student.ts @@ -1,27 +1,15 @@ import express from 'express' -import { getStudentById } from '../services/students'; -import { getStudent } from '../controllers/students'; +import { getAllStudentsHandler, getStudentClassesHandler, getStudentHandler } from '../controllers/students'; const router = express.Router(); // root endpoint used to search objects -router.get('/', (req, res) => { - res.json({ - students: [ - '0', - '1', - ] - }); -}); +router.get('/', getAllStudentsHandler); // information about a student's profile -router.get('/:id', getStudent); +router.get('/:id', getStudentHandler); // the list of classes a student is in -router.get('/:id/classes', (req, res) => { - res.json({ - classes: [ '0' ], - }); -}) +router.get('/:id/classes', getStudentClassesHandler); // the list of submissions a student has made router.get('/:id/submissions', (req, res) => { diff --git a/backend/src/services/students.ts b/backend/src/services/students.ts index b2aa953b..d38103ed 100644 --- a/backend/src/services/students.ts +++ b/backend/src/services/students.ts @@ -1,7 +1,14 @@ -import { getStudentRepository } from "../data/repositories"; +import { getClassRepository, getStudentRepository } from "../data/repositories"; +import { Class } from "../entities/classes/class.entity"; +import { ClassDTO } from "../interfaces/classes"; import { StudentDTO } from "../interfaces/students"; -export async function getStudentById(username: string): Promise { +export async function getAllStudents(): Promise { + // TODO + return []; +} + +export async function getStudent(username: string): Promise { const studentRepository = getStudentRepository(); const student = await studentRepository.findByUsername(username); @@ -16,3 +23,43 @@ export async function getStudentById(username: string): Promise { + const studentRepository = getStudentRepository(); + const student = await studentRepository.findByUsername(username); + + if (!student) return []; + + const classRepository = getClassRepository(); + // a weird error when running npm run dev occurs when using .findByStudent + // the error says that the function could not be found which is weird + // because typescript does not throw any errors + const classes = await classRepository.find( + { students: student }, + { populate: ["students", "teachers"] } // voegt student en teacher objecten toe + ) + // const classes = await classRepository.findByStudent(student); + + if (!classes) return []; + + return classes; +} + +export async function getStudentClasses(username: string): Promise { + const classes = await fetchStudentClasses(username); + + return classes.map((cls: Class): ClassDTO => { + return { + id: cls.classId, + displayName: cls.displayName, + teachers: cls.teachers.map(teacher => teacher.username), + students: cls.students.map(student => student.username), + joinRequests: [], // TODO + } + }); +} + +export async function getStudentClassIds(username: string): Promise { + const classes = await fetchStudentClasses(username); + return classes.map(cls => cls.classId); // class is a native keyword +} +