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) && (