@@ -28,6 +28,7 @@ import {
|
||||
Clock,
|
||||
} from "lucide-react";
|
||||
import { useReviewStore } from "@/hooks/use-review-player";
|
||||
import { ReviewPasswordGate } from "@/components/clients/ReviewPasswordGate";
|
||||
|
||||
interface Comment {
|
||||
id: string;
|
||||
@@ -80,6 +81,8 @@ export default function ClientReviewPage({
|
||||
const [comments, setComments] = useState<Comment[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [requiresPassword, setRequiresPassword] = useState(false);
|
||||
const [versionId, setVersionId] = useState("");
|
||||
|
||||
const currentFrame = useReviewStore((s) => s.currentFrame);
|
||||
|
||||
@@ -101,23 +104,39 @@ export default function ClientReviewPage({
|
||||
const { toast } = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
params.then(({ token: t, versionId }) => {
|
||||
params.then(({ token: t, versionId: vId }) => {
|
||||
setToken(t);
|
||||
fetch(`/api/client/${t}/versions/${versionId}`)
|
||||
.then((r) => {
|
||||
if (!r.ok) throw new Error("Invalid or expired review link");
|
||||
return r.json();
|
||||
})
|
||||
.then((data) => {
|
||||
setVersion(data.version);
|
||||
setComments(data.comments);
|
||||
setCurrentApprovalStatus(data.version.approvalStatus);
|
||||
})
|
||||
.catch((e) => setError(e.message))
|
||||
.finally(() => setLoading(false));
|
||||
setVersionId(vId);
|
||||
loadVersion(t, vId);
|
||||
});
|
||||
}, [params]);
|
||||
|
||||
const loadVersion = (t: string, vId: string) => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
fetch(`/api/client/${t}/versions/${vId}`)
|
||||
.then(async (r) => {
|
||||
if (r.status === 401) {
|
||||
const data = await r.json().catch(() => ({}));
|
||||
if (data.requiresPassword) {
|
||||
setRequiresPassword(true);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!r.ok) throw new Error("Invalid or expired review link");
|
||||
return r.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (!data) return;
|
||||
setVersion(data.version);
|
||||
setComments(data.comments);
|
||||
setCurrentApprovalStatus(data.version.approvalStatus);
|
||||
setRequiresPassword(false);
|
||||
})
|
||||
.catch((e) => setError(e.message))
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
const refreshComments = useCallback(async (t: string, vId: string) => {
|
||||
const res = await fetch(`/api/client/${t}/versions/${vId}`);
|
||||
if (res.ok) {
|
||||
@@ -201,6 +220,15 @@ export default function ClientReviewPage({
|
||||
);
|
||||
}
|
||||
|
||||
if (requiresPassword) {
|
||||
return (
|
||||
<ReviewPasswordGate
|
||||
token={token}
|
||||
onUnlocked={() => loadVersion(token, versionId)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !version) {
|
||||
return (
|
||||
<div className="min-h-screen bg-zinc-950 flex flex-col items-center justify-center gap-4 text-center px-4">
|
||||
|
||||
Reference in New Issue
Block a user