diff --git a/lib/CompoundTypes.ts b/lib/CompoundTypes.ts index 4f57590..296fffd 100644 --- a/lib/CompoundTypes.ts +++ b/lib/CompoundTypes.ts @@ -25,4 +25,11 @@ export type Quizzes = { questions : string; passed : boolean; score : number; +} + +export type AnswersType = string[] | null; + +export type ExamSubmissionResponse = { + moduleID: number; + score: number; } \ No newline at end of file diff --git a/prisma/migrations/20231006165619_init/migration.sql b/prisma/migrations/20231006165619_init/migration.sql new file mode 100644 index 0000000..df77ba3 --- /dev/null +++ b/prisma/migrations/20231006165619_init/migration.sql @@ -0,0 +1,128 @@ +/* + Warnings: + + - You are about to drop the column `curriculumId` on the `Module` table. All the data in the column will be lost. + - You are about to drop the column `createdAt` on the `ModuleExam` table. All the data in the column will be lost. + - You are about to drop the column `updatedAt` on the `ModuleExam` table. All the data in the column will be lost. + - You are about to drop the column `date` on the `Progress` table. All the data in the column will be lost. + - You are about to drop the column `age` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `createdAt` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `education` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `emailVerified` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `employmentStatus` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `ethnicity` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `gender` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `languages` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `livingStatus` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `maritalStatus` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `password` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `registrationDate` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `updatedAt` on the `User` table. All the data in the column will be lost. + - You are about to drop the column `verified` on the `User` table. All the data in the column will be lost. + - You are about to drop the `Account` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Advisor` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Badge` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Consultation` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Curriculum` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `Session` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `UserBadge` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `VerificationRequest` table. If the table is not empty, all the data it contains will be lost. + - A unique constraint covering the columns `[moduleId]` on the table `ModuleExam` will be added. If there are existing duplicate values, this will fail. + - A unique constraint covering the columns `[subModuleId]` on the table `SubModuleQuiz` will be added. If there are existing duplicate values, this will fail. + - Added the required column `order` to the `Lesson` table without a default value. This is not possible if the table is not empty. + - Added the required column `moduleId` to the `Progress` table without a default value. This is not possible if the table is not empty. + - Added the required column `subModuleId` to the `Progress` table without a default value. This is not possible if the table is not empty. + - Added the required column `moduleExamScores` to the `User` table without a default value. This is not possible if the table is not empty. + - Added the required column `subModuleQuizScores` to the `User` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "Account" DROP CONSTRAINT "Account_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "Consultation" DROP CONSTRAINT "Consultation_advisorId_fkey"; + +-- DropForeignKey +ALTER TABLE "Consultation" DROP CONSTRAINT "Consultation_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "Module" DROP CONSTRAINT "Module_curriculumId_fkey"; + +-- DropForeignKey +ALTER TABLE "Progress" DROP CONSTRAINT "Progress_lessonId_fkey"; + +-- DropForeignKey +ALTER TABLE "Session" DROP CONSTRAINT "Session_userId_fkey"; + +-- DropForeignKey +ALTER TABLE "UserBadge" DROP CONSTRAINT "UserBadge_badgeId_fkey"; + +-- DropForeignKey +ALTER TABLE "UserBadge" DROP CONSTRAINT "UserBadge_userId_fkey"; + +-- AlterTable +ALTER TABLE "Lesson" ADD COLUMN "order" INTEGER NOT NULL; + +-- AlterTable +ALTER TABLE "Module" DROP COLUMN "curriculumId"; + +-- AlterTable +ALTER TABLE "ModuleExam" DROP COLUMN "createdAt", +DROP COLUMN "updatedAt", +ADD COLUMN "answers" TEXT[]; + +-- AlterTable +ALTER TABLE "Progress" DROP COLUMN "date", +ADD COLUMN "moduleId" INTEGER NOT NULL, +ADD COLUMN "subModuleId" INTEGER NOT NULL; + +-- AlterTable +ALTER TABLE "User" DROP COLUMN "age", +DROP COLUMN "createdAt", +DROP COLUMN "education", +DROP COLUMN "emailVerified", +DROP COLUMN "employmentStatus", +DROP COLUMN "ethnicity", +DROP COLUMN "gender", +DROP COLUMN "languages", +DROP COLUMN "livingStatus", +DROP COLUMN "maritalStatus", +DROP COLUMN "password", +DROP COLUMN "registrationDate", +DROP COLUMN "updatedAt", +DROP COLUMN "verified", +ADD COLUMN "lessonsCompleted" INTEGER[], +ADD COLUMN "moduleExamScores" JSONB NOT NULL, +ADD COLUMN "preferences" TEXT[], +ADD COLUMN "registered" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "subModuleQuizScores" JSONB NOT NULL; + +-- DropTable +DROP TABLE "Account"; + +-- DropTable +DROP TABLE "Advisor"; + +-- DropTable +DROP TABLE "Badge"; + +-- DropTable +DROP TABLE "Consultation"; + +-- DropTable +DROP TABLE "Curriculum"; + +-- DropTable +DROP TABLE "Session"; + +-- DropTable +DROP TABLE "UserBadge"; + +-- DropTable +DROP TABLE "VerificationRequest"; + +-- CreateIndex +CREATE UNIQUE INDEX "ModuleExam_moduleId_key" ON "ModuleExam"("moduleId"); + +-- CreateIndex +CREATE UNIQUE INDEX "SubModuleQuiz_subModuleId_key" ON "SubModuleQuiz"("subModuleId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 558d55b..9d67017 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -85,8 +85,7 @@ model ModuleExam { moduleId Int @unique module Module @relation(fields: [moduleId], references: [id]) questions String[] - passed Boolean - score Int + answers String[] } @@ -95,8 +94,6 @@ model SubModuleQuiz { subModuleId Int @unique subModule SubModule @relation(fields: [subModuleId], references: [id]) questions String[] // Similar as above - passed Boolean - score Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } diff --git a/src/models/users.ts b/src/models/users.ts index 2468212..97aa39e 100644 --- a/src/models/users.ts +++ b/src/models/users.ts @@ -31,6 +31,31 @@ export default class Users { } } + public async updateUserModuleExam(userId: number, moduleId: number, moduleExamId: number, results: boolean[], score: number) { + let user: User; + + try { + const user = await this.usersDB.findUnique({ + where: { id: userId }, + }); + if (!user) { + throw "User Not Found" + } + + user.moduleExamScores[moduleId] = {"moduleExamId": moduleExamId, "results":results, "score": score} + await this.usersDB.update({ + where: { id: userId }, + data: { + moduleExamScores: user?.moduleExamScores, + }, + }); + + } catch (Error) { + throw "User Not Found" + } + + + } // Get Insensitive User Information By ID public async getUserById(id: number) { try { diff --git a/src/pages/api/modules/[id]/exams.ts b/src/pages/api/modules/[id]/exams.ts index 4b6893e..d76ba35 100644 --- a/src/pages/api/modules/[id]/exams.ts +++ b/src/pages/api/modules/[id]/exams.ts @@ -3,7 +3,7 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { getServerSession } from "next-auth"; import { authOptions } from "../../auth/[...nextauth]"; import { PrismaClient, ModuleExam } from "@prisma/client"; -const prisma = new PrismaClient(); +import prisma from "../../../../../lib/client"; import { Message } from "../../../../../lib/CompoundTypes"; diff --git a/src/pages/api/modules/[id]/submissions.ts b/src/pages/api/modules/[id]/submissions.ts new file mode 100644 index 0000000..d088b29 --- /dev/null +++ b/src/pages/api/modules/[id]/submissions.ts @@ -0,0 +1,75 @@ +// GET, PUT, DELETE operations for a specific user by ID +import type { NextApiRequest, NextApiResponse } from "next"; +import { getServerSession } from "next-auth"; +import { authOptions } from "../../auth/[...nextauth]"; +import { PrismaClient, ModuleExam } from "@prisma/client"; +import { Message } from "../../../../../lib/CompoundTypes"; +import { AnswersType } from "../../../../../lib/CompoundTypes"; +import persistentUserInstance from "../../../../../lib/persistentUserInstance"; +import { ExamSubmissionResponse } from "../../../../../lib/CompoundTypes"; +import prisma from "../../../../../lib/client"; +export default async function handler( + req: NextApiRequest, + res: NextApiResponse +) { + const session = await getServerSession(req, res, authOptions); + const supportedRequestMethods: { [key: string]: Function } = { + POST: postSubmission, + }; + + if (req.method) { + return supportedRequestMethods[req.method](req, res, session); + } + return res.status(405).send({ message: "request method not supported" }); +} + +async function postSubmission( + req: NextApiRequest, + res: NextApiResponse +) { + const moduleId = Number(req.query.id); + const userId = Number(req?.body?.userId) + const submission: AnswersType = req?.body?.submission + try { + const moduleExam = await prisma.moduleExam.findUnique({ + where: { + moduleId + }, + + }); + const correctAnswers = moduleExam?.answers + const moduleExamId = moduleExam?.id + + + if (!moduleExamId || !correctAnswers || correctAnswers.length == 0) { + return res.status(404).send({ message: "Module Exam not found" }) + } + + + if (correctAnswers?.length != submission?.length) { + return res.status(400).send({ message: "Different amount of questions and answers" }) + } + + let result:boolean[] = [] + let score = 0 + for(let i=0; i< correctAnswers.length; i++) { + if (correctAnswers[i] == submission[i]) { + result.push(true) + score += 1 + } else { + result.push(false) + } + } + score = (score / result.length) * 100 + try { + await persistentUserInstance.updateUserModuleExam(userId, moduleId, moduleExamId, result, score); + } catch (Error) { + return res.status(403).send({message: "User Not Found"}) + } + + return res.status(200).send({"moduleID": moduleId, "score": score}); + + } catch (error) { + return res.status(403).send({ message: "Please input an Integer" }); + } + } diff --git a/src/pages/api/subModules/[id].ts b/src/pages/api/subModules/[id].ts index deacddc..b393822 100644 --- a/src/pages/api/subModules/[id].ts +++ b/src/pages/api/subModules/[id].ts @@ -6,7 +6,8 @@ import { authOptions } from "../auth/[...nextauth]"; import Users from "@/models/users"; import { error } from "console"; import { PrismaClient, User } from "@prisma/client"; -const prisma = new PrismaClient(); +import prisma from "../../../../lib/client"; + import persistentQuizzesInstance from "../../../../lib/persistentQuizzesInstance"; import { QuizInfo } from "@/models/quizzes"; diff --git a/src/pages/api/users/[id].ts b/src/pages/api/users/[id].ts index 32304a1..1a31f5c 100644 --- a/src/pages/api/users/[id].ts +++ b/src/pages/api/users/[id].ts @@ -6,8 +6,7 @@ import { authOptions } from "../auth/[...nextauth]"; import Users from "@/models/users"; import { error } from "console"; import { PrismaClient, User } from "@prisma/client"; -const prisma = new PrismaClient(); - +import prisma from "../../../../lib/client"; import { InsensitiveUserInformation } from "@/models/users"; type Message = {