Files
vfxreview/app/api/client/[token]/project/route.ts
T
twotalesanimation 23f0ceca3f
Deploy / deploy (push) Successful in 2m57s
client passwords
2026-06-12 12:37:57 +02:00

117 lines
3.1 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { validateReviewToken } from "@/lib/review-auth";
/** GET /api/client/[token]/project — returns project + shots with tasks that have client-visible versions */
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ token: string }> }
) {
const { token } = await params;
const result = await validateReviewToken(token, req);
if (result.type === "requiresPassword") {
return NextResponse.json({ requiresPassword: true }, { status: 401 });
}
if (result.type === "invalid") {
return NextResponse.json({ error: "Invalid or expired review link" }, { status: 403 });
}
const session = result.session;
const project = await db.project.findUnique({
where: { id: session.projectId },
select: { id: true, name: true, code: true, description: true, status: true },
});
if (!project) {
return NextResponse.json({ error: "Project not found" }, { status: 404 });
}
// Only return shots that have been explicitly shared with the client
const shots = await db.shot.findMany({
where: {
projectId: session.projectId,
sharedWithClient: true,
},
orderBy: [{ episode: "asc" }, { sequence: "asc" }, { shotCode: "asc" }],
select: {
id: true,
shotCode: true,
episode: true,
sequence: true,
description: true,
status: true,
shotApprovalStatus: true,
thumbnailUrl: true,
tasks: {
where: {
versions: { some: { isClientVisible: true } },
},
select: {
id: true,
title: true,
type: true,
status: true,
versions: {
where: { isClientVisible: true, isLatest: true },
take: 1,
select: {
id: true,
versionNumber: true,
approvalStatus: true,
fps: true,
duration: true,
thumbnailUrl: true,
notes: true,
createdAt: true,
},
},
},
},
},
});
// Asset tasks with client-visible versions (no shotId)
const assetTasks = await db.task.findMany({
where: {
projectId: session.projectId,
shotId: null,
versions: { some: { isClientVisible: true } },
},
select: {
id: true,
title: true,
type: true,
status: true,
asset: { select: { id: true, assetCode: true, name: true } },
versions: {
where: { isClientVisible: true, isLatest: true },
take: 1,
select: {
id: true,
versionNumber: true,
approvalStatus: true,
fps: true,
duration: true,
thumbnailUrl: true,
notes: true,
createdAt: true,
},
},
},
});
// Increment access count
await db.reviewSession.update({
where: { id: session.id },
data: { accessCount: { increment: 1 } },
});
return NextResponse.json({
project,
shots,
assetTasks,
sessionLabel: session.label,
});
}