import { prisma } from '@/prisma'; import { auth } from '@/auth'; import { NextResponse } from 'next/server'; import { z } from 'zod/v4'; const postEventSchema = z .object({ title: z.string().min(1, 'Title is required'), description: z.string().optional(), start_time: z.iso.datetime(), end_time: z.iso.datetime(), location: z.string().optional().default(''), participants: z.array(z.string()).optional(), }) .refine((data) => new Date(data.start_time) < new Date(data.end_time), { error: 'Start time must be before end time', }) .refine( async (data) => !data.participants || (await Promise.all( data.participants.map(async (userId) => { const user = await prisma.user.findUnique({ where: { id: userId } }); return !!user; }), ).then((results) => results.every(Boolean))), { error: 'One or more participant user IDs are invalid', }, ); /** * @swagger * /api/event: * get: * summary: Get all events for the authenticated user * description: Returns all events where the user is an organizer or a participant. * tags: * - Event * responses: * 200: * description: List of events for the user. * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * events: * type: array * items: * $ref: "#/components/schemas/Event" * 401: * description: Not authenticated. * content: * application/json: * schema: * $ref: "#/components/schemas/ErrorResponse" * example: * success: false * message: Not authenticated * 404: * description: User not found. * content: * application/json: * schema: * $ref: "#/components/schemas/ErrorResponse" * example: * success: false * message: User not found */ export const GET = auth(async (req) => { if (!req.auth) return NextResponse.json( { success: false, message: 'Not authenticated' }, { status: 401 }, ); if (!req.auth.user || !req.auth.user.id) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); const dbUser = await prisma.user.findUnique({ where: { id: req.auth.user.id, }, }); if (!dbUser) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); const userEvents = await prisma.meeting.findMany({ where: { OR: [ { organizer_id: dbUser.id }, { participants: { some: { user_id: dbUser.id } } }, ], }, select: { id: true, title: true, description: true, start_time: true, end_time: true, status: true, location: true, created_at: true, updated_at: true, organizer: { select: { id: true, name: true, }, }, participants: { select: { user: { select: { id: true, name: true, }, }, status: true, }, }, }, }); return NextResponse.json({ success: true, events: userEvents, }); }); /** * @swagger * /api/event: * post: * summary: Create a new event * description: Creates a new event as the authenticated user (organizer). * tags: * - Event * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - title * - start_time * - end_time * properties: * title: * type: string * description: * type: string * start_time: * type: string * format: date-time * end_time: * type: string * format: date-time * location: * type: string * participants: * type: array * items: * type: string * description: User ID of a participant * responses: * 200: * description: Event created successfully. * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * event: * $ref: "#/components/schemas/Event" * 400: * description: Invalid request data. * content: * application/json: * schema: * $ref: "#/components/schemas/ZodErrorResponse" * 401: * description: Not authenticated. * content: * application/json: * schema: * $ref: "#/components/schemas/ErrorResponse" * example: * success: false * message: Not authenticated * 404: * description: User not found. * content: * application/json: * schema: * $ref: "#/components/schemas/ErrorResponse" * example: * success: false * message: User not found */ export const POST = auth(async (req) => { if (!req.auth) return NextResponse.json( { success: false, message: 'Not authenticated' }, { status: 401 }, ); if (!req.auth.user || !req.auth.user.id) return NextResponse.json( { success: false, message: 'User not found' }, { status: 404 }, ); const dataRaw = await req.json(); const data = await postEventSchema.safeParseAsync(dataRaw); if (!data.success) { return NextResponse.json( { success: false, message: 'Invalid request data', errors: data.error.issues, }, { status: 400 }, ); } const { title, description, start_time, end_time, location, participants } = data.data; const newEvent = await prisma.meeting.create({ data: { title, description, start_time, end_time, location, organizer_id: req.auth.user.id, participants: participants ? { create: participants.map((userId) => ({ user: { connect: { id: userId } }, })), } : undefined, }, select: { id: true, title: true, description: true, start_time: true, end_time: true, status: true, location: true, created_at: true, updated_at: true, organizer: { select: { id: true, name: true, }, }, participants: { select: { user: { select: { id: true, name: true, }, }, status: true, }, }, }, }); return NextResponse.json({ success: true, event: newEvent, }); });