test
Deploy / deploy (push) Successful in 2m32s

This commit is contained in:
twotalesanimation
2026-05-29 10:40:28 +02:00
parent 521eb38dcd
commit 36ee62dacc
2 changed files with 196 additions and 17 deletions
+61 -17
View File
@@ -38,6 +38,8 @@ const createShotSchema = z.object({
dueDate: z.string().optional(),
thumbnailUrl: z.string().url().optional(),
shotGroupName: z.string().max(100).optional(),
// Optional explicit shot code — bypasses auto-generation
shotCode: z.string().max(100).optional(),
});
// ── POST /api/ext/shots ───────────────────────────────────────────────────────
@@ -109,26 +111,46 @@ export async function POST(req: NextRequest) {
);
}
// Auto-increment shot number within scene (+ episode for episodic)
const scopeWhere = {
projectId: parsed.projectId,
scene,
...(project.projectType === "EPISODIC" ? { episode } : {}),
};
// Use explicit shotCode if provided, otherwise auto-increment
let shotCode: string;
let shotNumber: number;
const maxShot = await db.shot.findFirst({
where: scopeWhere,
orderBy: { shotNumber: "desc" },
select: { shotNumber: true },
});
if (parsed.shotCode) {
// Check uniqueness manually since we bypass auto-generation
const existing = await db.shot.findUnique({
where: { projectId_shotCode: { projectId: parsed.projectId, shotCode: parsed.shotCode } },
select: { id: true },
});
if (existing) {
return NextResponse.json(
{ error: "A shot with that code already exists in this project", shotCode: parsed.shotCode },
{ status: 409 }
);
}
shotCode = parsed.shotCode;
shotNumber = 0;
} else {
// Auto-increment shot number within scene (+ episode for episodic)
const scopeWhere = {
projectId: parsed.projectId,
scene,
...(project.projectType === "EPISODIC" ? { episode } : {}),
};
const shotNumber = (maxShot?.shotNumber ?? 0) + 10;
const paddedNumber = shotNumber.toString().padStart(4, "0");
const maxShot = await db.shot.findFirst({
where: scopeWhere,
orderBy: { shotNumber: "desc" },
select: { shotNumber: true },
});
const shotCode =
project.projectType === "EPISODIC" && episode
? `${project.showId}_${episode}_${scene}_${paddedNumber}`
: `${project.showId}_${scene}_${paddedNumber}`;
shotNumber = (maxShot?.shotNumber ?? 0) + 10;
const paddedNumber = shotNumber.toString().padStart(4, "0");
shotCode =
project.projectType === "EPISODIC" && episode
? `${project.showId}_${episode}_${scene}_${paddedNumber}`
: `${project.showId}_${scene}_${paddedNumber}`;
}
// Upload thumbnail if provided as a file
let thumbnailUrl = parsed.thumbnailUrl;
@@ -214,3 +236,25 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}
// ── GET /api/ext/shots?projectId=... ─────────────────────────────────────────
export async function GET(req: NextRequest) {
if (!isAuthorized(req)) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { searchParams } = new URL(req.url);
const projectId = searchParams.get("projectId");
if (!projectId) {
return NextResponse.json({ error: "projectId is required" }, { status: 400 });
}
const shots = await db.shot.findMany({
where: { projectId },
orderBy: { createdAt: "asc" },
select: { id: true, shotCode: true, scene: true, episode: true, status: true },
});
return NextResponse.json({ shots });
}