105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
||
import { auth } from "@clerk/nextjs/server";
|
||
import { revalidateTag } from "next/cache";
|
||
import { prisma } from "@/lib/prisma";
|
||
import { generateMonumentQR } from "@/lib/qrcode";
|
||
import { getPublicUrl } from "@/lib/upload";
|
||
|
||
export async function POST(req: NextRequest) {
|
||
const { userId } = await auth();
|
||
if (!userId) {
|
||
return NextResponse.json({ error: "Неавторизирано" }, { status: 401 });
|
||
}
|
||
|
||
try {
|
||
const body = await req.json();
|
||
const { title, description, bornDate, passedDate, subdomain, templateId, images } = body;
|
||
|
||
if (!title?.trim()) {
|
||
return NextResponse.json({ error: "Името е задолжително" }, { status: 400 });
|
||
}
|
||
if (!subdomain || subdomain.length < 3) {
|
||
return NextResponse.json({ error: "Поддоменот мора да има најмалку 3 карактери" }, { status: 400 });
|
||
}
|
||
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(subdomain)) {
|
||
return NextResponse.json({ error: "Поддоменот може да содржи само мали букви, цифри и цртички" }, { status: 400 });
|
||
}
|
||
if (templateId < 1 || templateId > 3) {
|
||
return NextResponse.json({ error: "Невалиден шаблон" }, { status: 400 });
|
||
}
|
||
if (!images || images.length === 0 || images.length > 3) {
|
||
return NextResponse.json({ error: "Потребни се 1-3 фотографии" }, { status: 400 });
|
||
}
|
||
|
||
const existing = await prisma.user.findUnique({ where: { subdomain } });
|
||
if (existing && existing.clerkId !== userId) {
|
||
return NextResponse.json({ error: "Поддоменот е веќе зафатен" }, { status: 409 });
|
||
}
|
||
|
||
const existingUser = await prisma.user.findUnique({ where: { clerkId: userId } });
|
||
|
||
let user;
|
||
if (existingUser) {
|
||
if (existingUser.subdomain !== subdomain) {
|
||
revalidateTag(`memorial-${existingUser.subdomain}`);
|
||
}
|
||
await prisma.image.deleteMany({ where: { userId: existingUser.id } });
|
||
user = await prisma.user.update({
|
||
where: { clerkId: userId },
|
||
data: {
|
||
title,
|
||
description,
|
||
bornDate: bornDate || null,
|
||
passedDate: passedDate || null,
|
||
subdomain,
|
||
templateId,
|
||
published: true,
|
||
images: {
|
||
create: images.map((img: { key: string }, i: number) => ({
|
||
url: getPublicUrl(img.key),
|
||
key: img.key,
|
||
order: i + 1,
|
||
})),
|
||
},
|
||
},
|
||
include: { images: true },
|
||
});
|
||
} else {
|
||
user = await prisma.user.create({
|
||
data: {
|
||
clerkId: userId,
|
||
title,
|
||
description,
|
||
bornDate: bornDate || null,
|
||
passedDate: passedDate || null,
|
||
subdomain,
|
||
templateId,
|
||
published: true,
|
||
images: {
|
||
create: images.map((img: { key: string }, i: number) => ({
|
||
url: getPublicUrl(img.key),
|
||
key: img.key,
|
||
order: i + 1,
|
||
})),
|
||
},
|
||
},
|
||
include: { images: true },
|
||
});
|
||
}
|
||
|
||
revalidateTag("memorial");
|
||
revalidateTag(`memorial-${subdomain}`);
|
||
|
||
const qrCode = await generateMonumentQR(subdomain);
|
||
|
||
return NextResponse.json({
|
||
success: true,
|
||
monumentUrl: `https://${subdomain}.${process.env.NEXT_PUBLIC_APP_DOMAIN}`,
|
||
qrCode,
|
||
user,
|
||
});
|
||
} catch (error) {
|
||
console.error("Publish error:", error);
|
||
return NextResponse.json({ error: "Внатрешна грешка на серверот" }, { status: 500 });
|
||
}
|
||
} |