From 62d45fb590a7bb2abc1b37fc9971c472711e90d3 Mon Sep 17 00:00:00 2001 From: Dominik Stahl Date: Fri, 13 Jun 2025 16:43:36 +0200 Subject: [PATCH] feat(api): add endpoint for event creation and listing of all events --- next-swagger-doc.json | 28 +++++ src/app/api/event/route.ts | 223 +++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 src/app/api/event/route.ts diff --git a/next-swagger-doc.json b/next-swagger-doc.json index 78b2e99..774fed8 100644 --- a/next-swagger-doc.json +++ b/next-swagger-doc.json @@ -43,6 +43,34 @@ "image": { "type": "string", "format": "uri" }, "timezone": { "type": "string", "description": "User timezone" } } + }, + "SimpleUser": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "name": { "type": "string" } + } + }, + "Event": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "title": { "type": "string" }, + "description": { "type": "string" }, + "start_time": { "type": "string", "format": "date-time" }, + "end_time": { "type": "string", "format": "date-time" }, + "status": { "type": "string" }, + "location": { "type": "string" }, + "organizer": { + "$ref": "#/components/schemas/SimpleUser" + }, + "participants": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimpleUser" + } + } + } } } }, diff --git a/src/app/api/event/route.ts b/src/app/api/event/route.ts new file mode 100644 index 0000000..a70f022 --- /dev/null +++ b/src/app/api/event/route.ts @@ -0,0 +1,223 @@ +import { prisma } from '@/prisma'; +import { auth } from '@/auth'; +import { NextResponse } from 'next/server'; + +/** + * @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. + * 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 } } }, + ], + }, + include: { + organizer: true, + participants: { + include: { + user: true, + }, + }, + }, + }); + + return NextResponse.json({ + success: true, + events: userEvents.map((event) => ({ + id: event.id, + title: event.title, + description: event.description, + start_time: event.start_time, + end_time: event.end_time, + status: event.status, + location: event.location, + organizer: { + id: event.organizer.id, + name: event.organizer.name, + }, + participants: event.participants.map((participant) => ({ + id: participant.user.id, + name: participant.user.name, + })), + })), + }); +}); + +/** + * @swagger + * /api/event: + * post: + * summary: Create a new event + * description: Creates a new event as the authenticated user (organizer). + * 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 + * responses: + * 200: + * description: Event created successfully. + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * event: + * $ref: '#/components/schemas/Event' + * 400: + * description: Missing required fields. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * example: + * success: false + * message: Missing required fields + * 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 body = await req.json(); + const { title, description, start_time, end_time } = body; + + if (!title || !start_time || !end_time) { + return NextResponse.json( + { success: false, message: 'Missing required fields' }, + { status: 400 }, + ); + } + + const newEvent = await prisma.meeting.create({ + data: { + title, + description, + start_time, + end_time, + organizer_id: req.auth.user.id, + }, + }); + + return NextResponse.json({ + success: true, + event: { + id: newEvent.id, + title: newEvent.title, + description: newEvent.description, + start_time: newEvent.start_time, + end_time: newEvent.end_time, + status: newEvent.status, + location: newEvent.location, + organizer: { + id: req.auth.user.id, + name: req.auth.user.name, + }, + participants: [], + }, + }); +});