feat: enhance QuizSchema and related schemas with new fields and relations

- Updated QuizSchema to expose correctAnswer as a field with a resolver, improving data retrieval for quizzes.
- Introduced new object types for correctAnswer, allowing for flexible data structures (StringType and StringListType).
- Modified createQuiz mutation to automatically associate the current user as centerMentorId, enhancing data integrity.
- Added personalMilestone relation to ScheduleSchema, linking schedules to personal milestones for better tracking.
- Included quiz relation in ServiceSchema, establishing a connection between services and their associated quizzes.
- Updated Prisma types to reflect the new relationships and fields, ensuring consistency across the application.
This commit is contained in:
2024-12-07 18:18:33 +07:00
parent d59df7d2ab
commit bb88d6ed00
7 changed files with 159 additions and 5 deletions

View File

@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common'
import { PersonalMilestoneSchema } from './personalmilestone.schema'
@Module({
imports: [PersonalMilestoneSchema],
})
export class PersonalMilestoneModule {}

View File

@@ -0,0 +1,90 @@
import { Inject, Injectable, Logger } 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 { PersonalMilestoneStatus } from '@prisma/client'
@Injectable()
export class PersonalMilestoneSchema extends PothosSchema {
constructor(
@Inject(SchemaBuilderToken) private readonly builder: Builder,
private readonly prisma: PrismaService,
) {
super()
}
@PothosRef()
personalMilestone() {
return this.builder.prismaObject('PersonalMilestone', {
fields: (t) => ({
id: t.exposeID('id', {
description: 'The ID of the personal milestone.',
}),
scheduleId: t.exposeString('scheduleId', {
description: 'The ID of the schedule the personal milestone belongs to.',
}),
schedule: t.relation('schedule', {
description: 'The schedule the personal milestone belongs to.',
}),
userId: t.exposeString('userId', {
description: 'The ID of the user the personal milestone belongs to.',
}),
user: t.relation('user', {
description: 'The user the personal milestone belongs to.',
}),
title: t.exposeString('title', {
description: 'The title of the personal milestone.',
}),
description: t.exposeString('description', {
description: 'The description of the personal milestone.',
}),
status: t.expose('status', {
type: PersonalMilestoneStatus,
description: 'The status of the personal milestone.',
}),
createdAt: t.expose('createdAt', {
type: 'DateTime',
description: 'The date the personal milestone was created.',
}),
updatedAt: t.expose('updatedAt', {
type: 'DateTime',
description: 'The date the personal milestone was last updated.',
}),
}),
})
}
@Pothos()
init(): void {
this.builder.queryFields((t) => ({
personalMilestone: t.prismaField({
type: this.personalMilestone(),
args: this.builder.generator.findUniqueArgs('PersonalMilestone'),
description: 'Retrieve a single personal milestone by its unique identifier.',
resolve: async (_query, _root, args, ctx, _info) => {
if (ctx.isSubscription) throw new Error('Not allowed')
if (!ctx.http.me) throw new Error('Cannot get your info')
return this.prisma.personalMilestone.findUnique({
where: args.where,
})
},
}),
personalMilestones: t.prismaField({
type: [this.personalMilestone()],
args: this.builder.generator.findManyArgs('PersonalMilestone'),
description: 'Retrieve multiple personal milestones.',
resolve: async (_query, _root, args, ctx, _info) => {
if (ctx.isSubscription) throw new Error('Not allowed')
if (!ctx.http.me) throw new Error('Cannot get your info')
return this.prisma.personalMilestone.findMany({
where: args.filter ?? undefined,
orderBy: args.orderBy ?? undefined,
skip: args.skip ?? undefined,
take: args.take ?? undefined,
cursor: args.cursor ?? undefined,
})
},
}),
}))
}
}

View File

@@ -53,7 +53,10 @@ export class QuizSchema extends PothosSchema {
type: AnswerType, type: AnswerType,
}), }),
answers: t.exposeStringList('answers'), answers: t.exposeStringList('answers'),
correctAnswer: t.exposeString('correctAnswer'), correctAnswer: t.field({
type: this.correctAnswerObject(),
resolve: (parent) => parent.correctAnswer,
}),
messageForCorrectAnswer: t.exposeString('messageForCorrectAnswer'), messageForCorrectAnswer: t.exposeString('messageForCorrectAnswer'),
messageForIncorrectAnswer: t.exposeString('messageForIncorrectAnswer'), messageForIncorrectAnswer: t.exposeString('messageForIncorrectAnswer'),
explanation: t.exposeString('explanation'), explanation: t.exposeString('explanation'),
@@ -68,6 +71,41 @@ export class QuizSchema extends PothosSchema {
}) })
} }
@PothosRef()
stringType() {
return this.builder.objectRef('StringType')
}
@PothosRef()
stringListType() {
return this.builder.objectRef('StringListType')
}
@PothosRef()
correctAnswerObject() {
const StringType = this.builder.objectType(this.stringType(), {
fields: (t) => ({
value: t.string({
resolve: (parent) => parent as string,
}),
}),
})
const StringListType = this.builder.objectType(this.stringListType(), {
fields: (t) => ({
items: t.stringList({
resolve: (parent) => parent as string[],
}),
}),
})
return this.builder.unionType('CorrectAnswerObject', {
types: [StringType, StringListType],
resolveType: (value) => {
return Array.isArray(value) ? StringListType : StringType
},
})
}
@Pothos() @Pothos()
init(): void { init(): void {
this.builder.queryFields((t) => ({ this.builder.queryFields((t) => ({
@@ -100,12 +138,24 @@ export class QuizSchema extends PothosSchema {
this.builder.mutationFields((t) => ({ this.builder.mutationFields((t) => ({
createQuiz: t.prismaField({ createQuiz: t.prismaField({
type: this.quiz(), type: this.quiz(),
args: { data: t.arg({ type: this.builder.generator.getCreateInput('Quiz'), required: true }) }, args: {
data: t.arg({
type: this.builder.generator.getCreateInput('Quiz', ['id', 'centerMentorId', 'createdAt', 'updatedAt']),
required: true,
}),
},
resolve: async (query, _root, args, ctx, _info) => { resolve: async (query, _root, args, ctx, _info) => {
if (ctx.isSubscription) throw new Error('Subscription is not allowed') if (ctx.isSubscription) throw new Error('Subscription is not allowed')
if (!ctx.http.me) throw new Error('User is not authenticated') if (!ctx.http.me) throw new Error('User is not authenticated')
if (!args.data) throw new Error('Data is required') if (!args.data) throw new Error('Data is required')
return await this.prisma.quiz.create({ ...query, data: args.data })
return await this.prisma.quiz.create({
...query,
data: {
...args.data,
centerMentorId: ctx.http.me.id,
},
})
}, },
}), }),
updateQuiz: t.prismaField({ updateQuiz: t.prismaField({

View File

@@ -68,6 +68,10 @@ export class ScheduleSchema extends PothosSchema {
description: 'The managed service the schedule belongs to.', description: 'The managed service the schedule belongs to.',
nullable: false, nullable: false,
}), }),
personalMilestone: t.relation('personalMilestone', {
description: 'The personal milestone of the schedule.',
nullable: true,
}),
}), }),
}) })
} }

View File

@@ -129,6 +129,9 @@ export class ServiceSchema extends PothosSchema {
return serviceFeedbacks.length > 0 return serviceFeedbacks.length > 0
}, },
}), }),
quiz: t.relation('quiz', {
description: 'The quiz of the service.',
}),
}), }),
}) })
} }

File diff suppressed because one or more lines are too long