From 4af2e848b8a2c601487ecab820e31af6773621ca Mon Sep 17 00:00:00 2001 From: Ly Tuan Kiet Date: Fri, 6 Dec 2024 21:52:11 +0700 Subject: [PATCH] feat: implement Quiz and Question schemas with GraphQL integration - Introduced QuizSchema and QuestionSchema extending PothosSchema for enhanced GraphQL capabilities. - Added methods to expose Quiz and Question fields, including relations and various attributes. - Implemented query and mutation fields for creating, updating, and retrieving quizzes, ensuring proper authentication and error handling. - Enhanced the overall structure of the schema to improve data integrity and access control. --- src/Quiz/quiz.schema.ts | 135 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/src/Quiz/quiz.schema.ts b/src/Quiz/quiz.schema.ts index 70ef8f8..4e95032 100644 --- a/src/Quiz/quiz.schema.ts +++ b/src/Quiz/quiz.schema.ts @@ -1,4 +1,135 @@ -import { Injectable } from '@nestjs/common' +import { Inject, Injectable } from '@nestjs/common' +import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos' +import { Builder } from '../Graphql/graphql.builder' +import { PrismaService } from '../Prisma/prisma.service' +import { AnswerType } from '@prisma/client' +import { QuestionType } from '@prisma/client' @Injectable() -export class QuizSchema {} +export class QuizSchema extends PothosSchema { + constructor( + @Inject(SchemaBuilderToken) private readonly builder: Builder, + private readonly prisma: PrismaService, + ) { + super() + } + + // Types section + @PothosRef() + quiz() { + return this.builder.prismaObject('Quiz', { + fields: (t) => ({ + id: t.exposeID('id'), + scheduleId: t.exposeID('scheduleId'), + schedule: t.relation('schedule'), + quizTitle: t.exposeString('quizTitle'), + quizSynopsis: t.exposeString('quizSynopsis'), + progressBarColor: t.exposeString('progressBarColor'), + nrOfQuestions: t.exposeInt('nrOfQuestions'), + questions: t.relation('questions'), + createdAt: t.expose('createdAt', { + type: 'DateTime', + }), + updatedAt: t.expose('updatedAt', { + type: 'DateTime', + }), + }), + }) + } + + @PothosRef() + question() { + return this.builder.prismaObject('Question', { + fields: (t) => ({ + id: t.exposeID('id'), + quizId: t.exposeID('quizId'), + quiz: t.relation('quiz'), + question: t.exposeString('question'), + questionType: t.expose('questionType', { + type: QuestionType, + }), + questionPic: t.exposeString('questionPic'), + answerSelectionType: t.expose('answerSelectionType', { + type: AnswerType, + }), + answers: t.exposeStringList('answers'), + correctAnswer: t.exposeString('correctAnswer'), + messageForCorrectAnswer: t.exposeString('messageForCorrectAnswer'), + messageForIncorrectAnswer: t.exposeString('messageForIncorrectAnswer'), + explanation: t.exposeString('explanation'), + point: t.exposeInt('point'), + createdAt: t.expose('createdAt', { + type: 'DateTime', + }), + updatedAt: t.expose('updatedAt', { + type: 'DateTime', + }), + }), + }) + } + + @Pothos() + init(): void { + this.builder.queryFields((t) => ({ + quiz: t.prismaField({ + type: this.quiz(), + args: this.builder.generator.findUniqueArgs('Quiz'), + resolve: async (query, _root, args, ctx, _info) => { + if (ctx.isSubscription) throw new Error('Subscription is not allowed') + if (!ctx.http.me) throw new Error('User is not authenticated') + return await this.prisma.quiz.findUnique({ ...query, where: { id: args.where.id } }) + }, + }), + quizzes: t.prismaField({ + type: [this.quiz()], + args: this.builder.generator.findManyArgs('Quiz'), + resolve: async (query, _root, args, ctx, _info) => { + if (ctx.isSubscription) throw new Error('Subscription is not allowed') + if (!ctx.http.me) throw new Error('User is not authenticated') + return await this.prisma.quiz.findMany({ + ...query, + where: args.filter ?? undefined, + orderBy: args.orderBy ?? undefined, + cursor: args.cursor ?? undefined, + take: args.take ?? undefined, + skip: args.skip ?? undefined, + }) + }, + }), + })) + this.builder.mutationFields((t) => ({ + createQuiz: t.prismaField({ + type: this.quiz(), + args: { data: t.arg({ type: this.builder.generator.getCreateInput('Quiz'), required: true }) }, + resolve: async (query, _root, args, ctx, _info) => { + if (ctx.isSubscription) throw new Error('Subscription is not allowed') + if (!ctx.http.me) throw new Error('User is not authenticated') + if (!args.data) throw new Error('Data is required') + return await this.prisma.quiz.create({ ...query, data: args.data }) + }, + }), + updateQuiz: t.prismaField({ + type: this.quiz(), + args: { + where: t.arg({ + type: this.builder.generator.getWhereUnique('Quiz'), + required: true, + }), + data: t.arg({ + type: this.builder.generator.getUpdateInput('Quiz'), + required: true, + }), + }, + resolve: async (query, _root, args, ctx, _info) => { + if (ctx.isSubscription) throw new Error('Subscription is not allowed') + if (!ctx.http.me) throw new Error('User is not authenticated') + return await this.prisma.quiz.update({ + ...query, + where: args.where, + data: args.data, + }) + }, + }), + })) + } +}