diff --git a/app/api/client/[token]/versions/[versionId]/route.ts b/app/api/client/[token]/versions/[versionId]/route.ts
index 9d258dd..8f62ef5 100644
--- a/app/api/client/[token]/versions/[versionId]/route.ts
+++ b/app/api/client/[token]/versions/[versionId]/route.ts
@@ -40,7 +40,7 @@ export async function GET(
task: {
include: {
project: { select: { id: true, name: true, code: true } },
- shot: { select: { shotCode: true } },
+ shot: { select: { id: true, shotCode: true, highResKey: true, highResFilename: true } },
asset: { select: { assetCode: true, name: true } },
},
},
@@ -78,10 +78,17 @@ export async function GET(
},
});
+ // Resolve the shot that has the high-res file (comes from version.shot OR version.task.shot)
+ const highResShot = version.shot ?? (version.task as any)?.shot ?? null;
+
const serializedVersion = {
...version,
fileSize: version.fileSize?.toString() ?? null,
- // Expose only whether a high-res file exists, never the storage key
+ // Top-level high-res fields so the client works for both shot and task versions
+ hasHighRes: !!(highResShot?.highResKey),
+ highResShotId: highResShot?.highResKey ? (highResShot.id ?? null) : null,
+ highResFilename: highResShot?.highResFilename ?? null,
+ // Expose only whether a high-res file exists on the shot relation, never the storage key
shot: version.shot
? {
...version.shot,
@@ -90,6 +97,17 @@ export async function GET(
highResKey: undefined,
}
: null,
+ task: version.task
+ ? {
+ ...version.task,
+ shot: (version.task as any)?.shot
+ ? {
+ ...((version.task as any).shot),
+ highResKey: undefined, // strip storage key
+ }
+ : null,
+ }
+ : null,
};
return NextResponse.json({ version: serializedVersion, comments });
diff --git a/app/client/[token]/review/[versionId]/page.tsx b/app/client/[token]/review/[versionId]/page.tsx
index d1d3d1f..6cdf6f3 100644
--- a/app/client/[token]/review/[versionId]/page.tsx
+++ b/app/client/[token]/review/[versionId]/page.tsx
@@ -54,6 +54,10 @@ interface Version {
duration: number | null;
approvalStatus: string;
notes: string | null;
+ // Top-level high-res flags (normalised from either shot or task.shot)
+ hasHighRes?: boolean;
+ highResShotId?: string | null;
+ highResFilename?: string | null;
shot?: {
id: string;
shotCode: string;
@@ -66,7 +70,7 @@ interface Version {
title: string;
type: string;
project: { id: string; name: string; code: string };
- shot?: { shotCode: string } | null;
+ shot?: { id: string; shotCode: string } | null;
asset?: { assetCode: string; name: string } | null;
} | null;
}
@@ -205,10 +209,11 @@ export default function ClientReviewPage({
};
const handleDownloadHighRes = async () => {
- if (!version?.shot?.id || !token) return;
+ const shotId = version?.highResShotId ?? version?.shot?.id;
+ if (!shotId || !token) return;
setDownloadingHighRes(true);
try {
- const res = await fetch(`/api/client/${token}/shots/${version.shot.id}/highres/download`);
+ const res = await fetch(`/api/client/${token}/shots/${shotId}/highres/download`);
if (!res.ok) throw new Error("Could not get download link");
const { url } = await res.json();
// Open the presigned URL — the Content-Disposition header forces a download
@@ -384,14 +389,14 @@ export default function ClientReviewPage({
Approve
- {version.shot?.hasHighRes && (
+ {(version.hasHighRes || version.shot?.hasHighRes) && (