feat(api): add user search endpoint and normalize response data and validation
This commit is contained in:
parent
b9dda271af
commit
16a5825dd3
14 changed files with 574 additions and 368 deletions
|
@ -1,6 +1,19 @@
|
|||
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(''),
|
||||
})
|
||||
.refine((data) => new Date(data.start_time) < new Date(data.end_time), {
|
||||
error: 'Start time must be before end time',
|
||||
});
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
|
@ -74,11 +87,31 @@ export const GET = auth(async (req) => {
|
|||
{ participants: { some: { user_id: dbUser.id } } },
|
||||
],
|
||||
},
|
||||
include: {
|
||||
organizer: true,
|
||||
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: {
|
||||
include: {
|
||||
user: true,
|
||||
select: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
status: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -86,23 +119,7 @@ export const GET = auth(async (req) => {
|
|||
|
||||
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,
|
||||
})),
|
||||
})),
|
||||
events: userEvents,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -150,14 +167,14 @@ export const GET = auth(async (req) => {
|
|||
* event:
|
||||
* $ref: '#/components/schemas/Event'
|
||||
* 400:
|
||||
* description: Missing required fields.
|
||||
* description: Bad request due to invalid input data.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/ErrorResponse'
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/ErrorResponse'
|
||||
* example:
|
||||
* success: false
|
||||
* message: Missing required fields
|
||||
* message: 'Invalid input data'
|
||||
* 401:
|
||||
* description: Not authenticated.
|
||||
* content:
|
||||
|
@ -189,36 +206,19 @@ export const POST = auth(async (req) => {
|
|||
{ status: 404 },
|
||||
);
|
||||
|
||||
const body = await req.json();
|
||||
const { title, description, start_time, end_time, location } = body;
|
||||
|
||||
if (!title || !start_time || !end_time) {
|
||||
const dataRaw = await req.json();
|
||||
const data = await postEventSchema.safeParseAsync(dataRaw);
|
||||
if (!data.success) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: 'Missing required fields' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (isNaN(new Date(start_time).getTime())) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: 'Invalid start_time' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (isNaN(new Date(end_time).getTime())) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: 'Invalid end_time' },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
if (new Date(start_time) >= new Date(end_time)) {
|
||||
return NextResponse.json(
|
||||
{ success: false, message: 'start_time must be before end_time' },
|
||||
{
|
||||
success: false,
|
||||
message: 'Invalid request data',
|
||||
errors: data.error.issues,
|
||||
},
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
const { title, description, start_time, end_time, location } = data.data;
|
||||
|
||||
const newEvent = await prisma.meeting.create({
|
||||
data: {
|
||||
|
@ -226,26 +226,41 @@ export const POST = auth(async (req) => {
|
|||
description,
|
||||
start_time,
|
||||
end_time,
|
||||
location: location || '',
|
||||
location,
|
||||
organizer_id: req.auth.user.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,
|
||||
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: [],
|
||||
},
|
||||
event: newEvent,
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue