109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { z } from 'zod';
|
|
import { prisma, getTenantPrisma } from '@/lib/prisma';
|
|
import { generateJitsiRoomName } from '@/lib/jitsi';
|
|
|
|
const CreateClassSchema = z.object({
|
|
tenantId: z.string().min(1, 'tenantId is required'),
|
|
title: z.string().min(1, 'title is required'),
|
|
description: z.string().optional(),
|
|
startTime: z.string().or(z.date()),
|
|
endTime: z.string().or(z.date()),
|
|
capacity: z.number().int().positive().default(20),
|
|
});
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const body = await req.json();
|
|
const validated = CreateClassSchema.parse(body);
|
|
|
|
// 1. Verify tenant existence
|
|
const tenant = await prisma.tenant.findUnique({
|
|
where: { id: validated.tenantId },
|
|
});
|
|
|
|
if (!tenant) {
|
|
return NextResponse.json(
|
|
{ error: 'Tenant not found' },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
const start = new Date(validated.startTime);
|
|
const end = new Date(validated.endTime);
|
|
const timestamp = Date.now();
|
|
|
|
// 2. Generate deterministic tenant-isolated Jitsi room name
|
|
const tempSessionId = `temp-${Math.random().toString(36).slice(2, 8)}`;
|
|
const jitsiRoomId = generateJitsiRoomName(tenant.slug, tempSessionId, timestamp);
|
|
|
|
// 3. Create ClassSession in PostgreSQL via tenant-scoped Prisma client
|
|
const tenantPrisma = getTenantPrisma(tenant.id);
|
|
const classSession = await tenantPrisma.classSession.create({
|
|
data: {
|
|
tenantId: tenant.id,
|
|
title: validated.title,
|
|
description: validated.description,
|
|
startTime: start,
|
|
endTime: end,
|
|
capacity: validated.capacity,
|
|
jitsiRoomId,
|
|
},
|
|
});
|
|
|
|
return NextResponse.json(
|
|
{
|
|
success: true,
|
|
classSession,
|
|
roomName: classSession.jitsiRoomId,
|
|
},
|
|
{ status: 201 }
|
|
);
|
|
} catch (error: any) {
|
|
if (error instanceof z.ZodError) {
|
|
return NextResponse.json(
|
|
{ error: 'Validation failed', details: error.issues },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
console.error('Error creating class session:', error);
|
|
return NextResponse.json(
|
|
{ error: error.message || 'Internal server error' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function GET(req: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(req.url);
|
|
const tenantId = searchParams.get('tenantId');
|
|
|
|
if (!tenantId) {
|
|
return NextResponse.json(
|
|
{ error: 'tenantId query parameter is required' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const tenantPrisma = getTenantPrisma(tenantId);
|
|
const classes = await tenantPrisma.classSession.findMany({
|
|
orderBy: { startTime: 'asc' },
|
|
include: {
|
|
bookings: {
|
|
include: {
|
|
user: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
return NextResponse.json({ classes });
|
|
} catch (error: any) {
|
|
return NextResponse.json(
|
|
{ error: error.message || 'Internal server error' },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
} |