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 { LiveKitRoomService } from 'src/LiveKit/livekit.room.service' import { v4 as uuidv4 } from 'uuid' import { CollaborationSession, Role } from '@prisma/client' import { DateTimeUtils } from 'src/common/utils/datetime.utils' @Injectable() export class CollaborationSessionSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, // private readonly liveKitRoomService: LiveKitRoomService, ) { super() } @PothosRef() collaborationSession() { return this.builder.prismaObject('CollaborationSession', { description: 'A collaboration session in the system.', fields: (t) => ({ id: t.exposeID('id', { description: 'The ID of the collaboration session.', }), chatRoomId: t.exposeString('chatRoomId', { description: 'The ID of the chat room.', }), chatRoom: t.relation('chatRoom', { description: 'The chat room.', }), meetingRoom: t.relation('meetingRoom', { description: 'The meeting room.', }), scheduleDate: t.relation('scheduleDate', { description: 'The schedule date.', }), activeDocumentId: t.exposeString('activeDocumentId', { description: 'The ID of the active document.', }), activeDocument: t.relation('activeDocument', { description: 'The active document.', }), createdAt: t.expose('createdAt', { type: 'DateTime', description: 'The creation date of the collaboration session.', }), updatedAt: t.expose('updatedAt', { type: 'DateTime', description: 'The update date of the collaboration session.', }), }), }) } @Pothos() init(): void { this.builder.queryFields((t) => ({ // get collaboration session by schedule date id, if not exist, create new one collaborationSession: t.prismaField({ type: this.collaborationSession(), args: { scheduleDateId: t.arg.string({ description: 'The ID of the schedule date.', required: true, }), }, description: 'Retrieve a single collaboration session by its unique identifier.', resolve: async (_query, _root, args, ctx, _info) => { if (ctx.isSubscription) throw new Error('Not allowed') const scheduleDate = await this.prisma.scheduleDate.findUnique({ where: { id: args.scheduleDateId, }, }) if (!scheduleDate) throw new Error('Schedule date not found') let collaborationSession: CollaborationSession | null = null collaborationSession = await this.prisma.collaborationSession.findUniqueOrThrow({ where: { scheduleDateId: scheduleDate.id, }, }) /* ---------- use case 1 : customer get collaboration session by id --------- */ if (ctx.http.me?.role === Role.CUSTOMER && collaborationSession) { if (scheduleDate.participantIds.includes(ctx.http.me?.id)) { return collaborationSession } throw new Error('User not allowed') } /* ---------- use case 2 : center mentor get collaboration session by schedule date id --------- */ if (ctx.http.me?.role !== Role.CENTER_MENTOR) throw new Error('Mentor does not created collaboration session yet') // check if order is exist in schedule date if (!scheduleDate.orderId) throw new Error('Order not found') const order = await this.prisma.order.findUnique({ where: { id: scheduleDate.orderId, }, }) if (!order) throw new Error('Order not found') if (!order.chatRoomId) throw new Error('Order chat room not found') // only in time before 10 minutes from start time or less and not after end time can create new collaboration session const now = DateTimeUtils.now() const startTime = DateTimeUtils.fromDate(scheduleDate.start) const endTime = DateTimeUtils.fromDate(scheduleDate.end) /* ----------------------- disabled in development mode ---------------------- */ // if ( // now.diff(startTime, 'minutes').minutes > 10 || // before start time 10 minutes // now > endTime // after end time // ) { // throw new Error('Collaboration session not allowed in this time') // } if (!collaborationSession) { const chatRoom = await this.prisma.chatRoom.findUnique({ where: { id: order.chatRoomId, }, }) if (!chatRoom) throw new Error('Chat room not found') // create new one const newCollaborationSession = await this.prisma.collaborationSession.create({ data: { scheduleDateId: scheduleDate.id, // assign chat room chatRoomId: order.chatRoomId, }, }) // case after start time and before end time, mark as late if (now > startTime && now < endTime) { // mark as late await this.prisma.scheduleDate.update({ where: { id: scheduleDate.id, }, data: { lateStart: DateTimeUtils.now().toJSDate(), }, }) } return newCollaborationSession // if not exist use case } return collaborationSession // if exist use case }, }), collaborationSessions: t.prismaField({ type: [this.collaborationSession()], args: this.builder.generator.findManyArgs('CollaborationSession'), description: 'Retrieve a list of collaboration sessions with optional filtering, ordering, and pagination.', resolve: async (query, _root, args, _ctx, _info) => { return await this.prisma.collaborationSession.findMany({ ...query, skip: args.skip ?? undefined, take: args.take ?? undefined, orderBy: args.orderBy ?? undefined, where: args.filter ?? undefined, }) }, }), })) this.builder.mutationFields((t) => ({ createCollaborationSession: t.prismaField({ type: this.collaborationSession(), args: { input: t.arg({ type: this.builder.generator.getCreateInput('CollaborationSession'), required: true, }), }, description: 'Create a new collaboration session.', resolve: async (query, _root, args, _ctx, _info) => { // for test only !!! if (args.input.chatRoom.create) { args.input.chatRoom.create.id = uuidv4() } // call livekit room service to create room // this.liveKitRoomService.createServiceMeetingRoom( // args.input.chatRoom.create?.id ?? '', // ) return await this.prisma.collaborationSession.create({ ...query, data: args.input, }) }, }), })) } }