comicbox/pages/api/submit-page-bubbles.ts

119 lines
3.4 KiB
TypeScript

import { ComicBubble, Prisma } from '@prisma/client';
import { NextApiRequest, NextApiResponse } from 'next';
import { unstable_getServerSession } from 'next-auth';
import { z } from 'zod';
import { auditPageUpdate } from '../../src/audit';
import { prisma } from '../../src/db';
import { authOptions } from './auth/[...nextauth]';
const PageBubblesSchema = z.object({
bubbles: z.array(
z.object({
area: z.object({
x: z.number(),
y: z.number(),
width: z.number(),
height: z.number(),
}),
character: z.number(),
index: z.number(),
text: z.string(),
})
),
comicId: z.number(),
pageId: z.number(),
});
export type PageBubbles = z.infer<typeof PageBubblesSchema>;
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'PUT')
return res.status(405).json({ error: 'method not allowed' });
const session = await unstable_getServerSession(req, res, authOptions);
if (!session || !session.user)
return res.status(401).json({ error: 'authentication required' });
const data = PageBubblesSchema.parse(req.body);
const page = await prisma.comicPage.findFirst({
where: {
comicId: data.comicId,
id: data.pageId,
},
include: {
bubbles: true,
},
});
if (!page) return res.status(404).json({ error: 'not found' });
const existingCharacters: number[] = [];
const ops: Prisma.Prisma__ComicBubbleClient<ComicBubble>[] = [];
for (const bubble of data.bubbles) {
if (!existingCharacters.includes(bubble.character)) {
const char = await prisma.comicCharacter.findFirst({
where: {
id: bubble.character,
},
});
if (!char) {
return res.status(400).json({ message: 'bad request' });
}
}
const op = prisma.comicBubble.upsert({
where: {
comicId_pageId_idx: {
comicId: data.comicId,
pageId: data.pageId,
idx: bubble.index,
},
},
update: {
areaX: bubble.area.x,
areaY: bubble.area.y,
areaWidth: bubble.area.width,
areaHeight: bubble.area.height,
characterId: bubble.character,
content: bubble.text,
},
create: {
comicId: data.comicId,
pageId: data.pageId,
idx: bubble.index,
areaX: bubble.area.x,
areaY: bubble.area.y,
areaWidth: bubble.area.width,
areaHeight: bubble.area.height,
characterId: bubble.character,
content: bubble.text,
},
});
ops.push(op);
}
await prisma.$transaction(ops);
const after = await prisma.comicPage.update({
where: {
comicId_id: {
comicId: page.comicId,
id: page.id,
},
},
data: {
lastEditedById: session.user.id,
},
include: {
bubbles: true,
}
});
await auditPageUpdate(page, after, data, session.user);
res.status(201).json({});
}