@@ -30,6 +30,7 @@ import {
|
||||
ChevronRight,
|
||||
Copy,
|
||||
Check,
|
||||
Download,
|
||||
} from "lucide-react";
|
||||
import { useReviewStore } from "@/hooks/use-review-player";
|
||||
import { ReviewPasswordGate } from "@/components/clients/ReviewPasswordGate";
|
||||
@@ -56,6 +57,8 @@ interface Version {
|
||||
shot?: {
|
||||
id: string;
|
||||
shotCode: string;
|
||||
hasHighRes?: boolean;
|
||||
highResFilename?: string | null;
|
||||
project: { id: string; name: string; code: string };
|
||||
} | null;
|
||||
task?: {
|
||||
@@ -108,6 +111,7 @@ export default function ClientReviewPage({
|
||||
const [nextReview, setNextReview] = useState<{ versionId: string; label: string } | null>(null);
|
||||
const [prevReview, setPrevReview] = useState<{ versionId: string; label: string } | null>(null);
|
||||
const [copiedTaskName, setCopiedTaskName] = useState(false);
|
||||
const [downloadingHighRes, setDownloadingHighRes] = useState(false);
|
||||
|
||||
const playerRef = useRef<ReviewPlayerRef>(null);
|
||||
const { toast } = useToast();
|
||||
@@ -200,6 +204,22 @@ export default function ClientReviewPage({
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownloadHighRes = async () => {
|
||||
if (!version?.shot?.id || !token) return;
|
||||
setDownloadingHighRes(true);
|
||||
try {
|
||||
const res = await fetch(`/api/client/${token}/shots/${version.shot.id}/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
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
} catch {
|
||||
toast({ title: "Download failed", variant: "destructive" });
|
||||
} finally {
|
||||
setDownloadingHighRes(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmitApproval = async () => {
|
||||
if (!approvalDialog.status || !version) return;
|
||||
setSubmittingApproval(true);
|
||||
@@ -364,6 +384,19 @@ export default function ClientReviewPage({
|
||||
<CheckCircle2 className="h-3.5 w-3.5" />
|
||||
Approve
|
||||
</Button>
|
||||
{version.shot?.hasHighRes && (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
className="h-8 text-xs gap-1 text-sky-400 border-sky-500/30 hover:bg-sky-500/10"
|
||||
disabled={downloadingHighRes}
|
||||
onClick={handleDownloadHighRes}
|
||||
title={version.shot.highResFilename ?? "Download high-res file"}
|
||||
>
|
||||
<Download className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">{downloadingHighRes ? "Getting link…" : "High Res"}</span>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Right: Prev / Next navigation */}
|
||||
|
||||
Reference in New Issue
Block a user