diff --git a/app/(dashboard)/playlist/PlaylistClient.tsx b/app/(dashboard)/playlist/PlaylistClient.tsx
index d2b2d13..96c70b1 100644
--- a/app/(dashboard)/playlist/PlaylistClient.tsx
+++ b/app/(dashboard)/playlist/PlaylistClient.tsx
@@ -38,6 +38,7 @@ interface PlaylistVersion {
posterUrl: string | null;
fps: number;
approvalStatus: string;
+ taskTitle: string;
}
interface PlaylistShot {
@@ -315,6 +316,7 @@ function ShotThumbnail({
{/* Info */}
{shot.shotCode}
+
{shot.latestVersion.taskTitle}
c.startsWith("text-")) ?? "text-zinc-400"
diff --git a/app/api/playlist/route.ts b/app/api/playlist/route.ts
index f87fb89..9cebae0 100644
--- a/app/api/playlist/route.ts
+++ b/app/api/playlist/route.ts
@@ -13,13 +13,14 @@ export async function GET(req: NextRequest) {
return NextResponse.json({ error: "projectId required" }, { status: 400 });
}
+ // All versions are linked to tasks (taskId), not directly to shots.
+ // We query shots with their tasks, and for each task get the latest version.
const shots = await db.shot.findMany({
where: {
projectId,
- versions: {
+ tasks: {
some: {
- shotId: { not: null },
- mimeType: { startsWith: "video/" },
+ versions: { some: { isLatest: true } },
},
},
},
@@ -30,36 +31,60 @@ export async function GET(req: NextRequest) {
episode: true,
status: true,
thumbnailUrl: true,
- versions: {
- where: {
- isLatest: true,
- mimeType: { startsWith: "video/" },
- },
- take: 1,
+ tasks: {
select: {
id: true,
- versionNumber: true,
- fileUrl: true,
- thumbnailUrl: true,
- posterUrl: true,
- fps: true,
- approvalStatus: true,
+ title: true,
+ versions: {
+ where: { isLatest: true },
+ take: 1,
+ orderBy: { createdAt: "desc" },
+ select: {
+ id: true,
+ versionNumber: true,
+ fileUrl: true,
+ thumbnailUrl: true,
+ posterUrl: true,
+ fps: true,
+ approvalStatus: true,
+ mimeType: true,
+ createdAt: true,
+ },
+ },
},
},
},
});
- // Only return shots that actually have a latest video version
+ // For each shot, pick the most recently uploaded latest version across all tasks
const playlist = shots
- .map((shot) => ({
- id: shot.id,
- shotCode: shot.shotCode,
- episode: shot.episode,
- status: shot.status,
- thumbnailUrl: shot.thumbnailUrl,
- latestVersion: shot.versions[0] ?? null,
- }))
- .filter((shot) => shot.latestVersion !== null);
+ .map((shot) => {
+ const versions = shot.tasks
+ .flatMap((t) => t.versions.map((v) => ({ ...v, taskTitle: t.title })))
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
+
+ const latest = versions[0] ?? null;
+ if (!latest) return null;
+
+ return {
+ id: shot.id,
+ shotCode: shot.shotCode,
+ episode: shot.episode,
+ status: shot.status,
+ thumbnailUrl: shot.thumbnailUrl,
+ latestVersion: {
+ id: latest.id,
+ versionNumber: latest.versionNumber,
+ fileUrl: latest.fileUrl,
+ thumbnailUrl: latest.thumbnailUrl,
+ posterUrl: latest.posterUrl,
+ fps: latest.fps,
+ approvalStatus: latest.approvalStatus,
+ taskTitle: latest.taskTitle,
+ },
+ };
+ })
+ .filter((s): s is NonNullable => s !== null);
return NextResponse.json({ shots: playlist });
}