import { Inject, Injectable, Logger } from '@nestjs/common' import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos' import { DateTimeUtils } from 'src/common/utils/datetime.utils' import { Builder } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' @Injectable() export class WorkshopSubscriptionSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, ) { super() } @PothosRef() workshopSubscription() { return this.builder.prismaObject('WorkshopSubscription', { description: 'A workshop subscription in the system.', fields: (t) => ({ userId: t.exposeID('userId', { description: 'The ID of the user who subscribed to the workshop.', }), workshopId: t.exposeID('workshopId', { description: 'The ID of the workshop that the user subscribed to.', }), user: t.relation('user', { description: 'The user who subscribed to the workshop.', }), workshop: t.relation('workshop', { description: 'The workshop that the user subscribed to.', }), createdAt: t.expose('createdAt', { type: 'DateTime', description: 'The date and time the workshop subscription was created.', }), notified: t.exposeBoolean('notified', { description: 'Whether the user has been notified about the workshop.', }), }), }) } @Pothos() init(): void { this.builder.queryFields((t) => ({ workshopSubscription: t.prismaField({ type: this.workshopSubscription(), args: this.builder.generator.findUniqueArgs('WorkshopSubscription'), description: 'Retrieve a single workshop subscription by its unique identifier.', resolve: async (query, _root, args) => { return await this.prisma.workshopSubscription.findUnique({ ...query, where: args.where, }) }, }), workshopSubscriptions: t.prismaField({ type: [this.workshopSubscription()], args: this.builder.generator.findManyArgs('WorkshopSubscription'), description: 'Retrieve a list of workshop subscriptions with optional filtering, ordering, and pagination.', resolve: async (query, _root, args, _ctx) => { return await this.prisma.workshopSubscription.findMany({ ...query, skip: args.skip ?? undefined, take: args.take ?? undefined, orderBy: args.orderBy ?? undefined, where: args.filter ?? undefined, }) }, }), subscribedWorkshops: t.prismaField({ type: [this.workshopSubscription()], description: 'Retrieve a list of workshops that the current user is subscribed to.', resolve: async (query, _root, _args, ctx, _info) => { if (!ctx.me) { throw new Error('User is not authenticated') } return await this.prisma.workshopSubscription.findMany({ ...query, where: { userId: ctx.me.id, }, }) }, }), })) this.builder.mutationFields((t) => ({ subscribeToWorkshop: t.prismaField({ type: this.workshopSubscription(), args: { workshopId: t.arg.string({ description: 'The ID of the workshop to subscribe to.', required: true, }), }, resolve: async (_query, _root, args, ctx) => { const userId = ctx.me?.id // retrieve the workshop const workshop = await this.prisma.workshop.findUnique({ where: { id: args.workshopId }, }) if (!workshop) { throw new Error('Workshop not found') } if (!userId) { throw new Error('User not authenticated') } // check if workshop is in the future if (workshop.date < DateTimeUtils.now().toJSDate()) { throw new Error('Workshop has already started or is over') } // check if user is already subscribed to the workshop const existingSubscription = await this.prisma.workshopSubscription.findFirst({ where: { userId, workshopId: args.workshopId }, }) if (existingSubscription) { throw new Error('User already subscribed to workshop') } // create the workshop subscription const result = await this.prisma.workshopSubscription.create({ data: { userId, workshopId: args.workshopId, }, }) // update participant count by querying the workshop subscription const participantCount = await this.prisma.workshopSubscription.count({ where: { workshopId: args.workshopId }, }) await this.prisma.workshop.update({ where: { id: args.workshopId }, data: { registeredParticipants: participantCount, }, }) return result }, }), })) } }