Review page: add upload zone when latest revision has no asset
Surface the AssetUploadZone directly on the deliverable review page when the latest revision is asset-less, plus a "Replace asset" toggle when one is already uploaded. CLIENT_VIEWER stays read-only. Closes the gap where producers were stuck on "No asset uploaded yet for V0.2" with no way to upload from this page (they had to go back to the deliverable detail panel). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
45dfdcad23
commit
98ebe4796d
1 changed files with 50 additions and 12 deletions
|
|
@ -1,13 +1,16 @@
|
|||
"use client";
|
||||
|
||||
import { use } from "react";
|
||||
import { use, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ArrowLeft, AlertCircle } from "lucide-react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useDeliverable } from "@/hooks/use-deliverables";
|
||||
import { useRevisions } from "@/hooks/use-revisions";
|
||||
import { useCurrentUser } from "@/hooks/use-current-user";
|
||||
import { formatRevisionLabel } from "@/lib/format-revision-label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { AssetUploadZone } from "@/components/review/asset-upload-zone";
|
||||
|
||||
// Phase 5 transitional page. The HP-style annotation surface is being
|
||||
// rebuilt against the single-asset revision model. For now, this page
|
||||
|
|
@ -46,6 +49,17 @@ export default function DeliverableReviewPage({ params, searchParams }: PageProp
|
|||
const revisions = (revData as RevisionLike[] | undefined) ?? [];
|
||||
const latest = revisions[0];
|
||||
|
||||
const { data: me } = useCurrentUser();
|
||||
const canEdit = !!me && (me as any).role !== "CLIENT_VIEWER";
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const [showReplace, setShowReplace] = useState(false);
|
||||
const refreshRevisions = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ["revisions", stageId] });
|
||||
queryClient.invalidateQueries({ queryKey: ["deliverable", projectId, deliverableId] });
|
||||
setShowReplace(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4 p-6">
|
||||
<Link
|
||||
|
|
@ -70,21 +84,28 @@ export default function DeliverableReviewPage({ params, searchParams }: PageProp
|
|||
</div>
|
||||
|
||||
{!latest ? (
|
||||
<div className="flex items-start gap-2 rounded-md border border-dashed border-[var(--border)] bg-[var(--accent)]/30 p-4 text-sm">
|
||||
<AlertCircle className="mt-0.5 h-4 w-4 shrink-0 text-[var(--muted-foreground)]" />
|
||||
<div>
|
||||
No revision yet on this stage. Open the deliverable page and use
|
||||
the in-row review panel to create one.
|
||||
</div>
|
||||
<div className="rounded-md border border-dashed border-[var(--border)] bg-[var(--accent)]/30 p-4 text-sm text-[var(--muted-foreground)]">
|
||||
No revision yet on this stage. Open the deliverable page and use
|
||||
the in-row review panel to create one.
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="outline">{formatRevisionLabel(latest)}</Badge>
|
||||
<Badge variant="outline">{latest.status}</Badge>
|
||||
{canEdit && latest.asset && !showReplace && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="ml-auto h-7"
|
||||
onClick={() => setShowReplace(true)}
|
||||
>
|
||||
Replace asset
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{latest.asset ? (
|
||||
{latest.asset && !showReplace ? (
|
||||
<div className="rounded-md border bg-[var(--card)] p-2">
|
||||
{latest.asset.kind === "image" ? (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
|
|
@ -101,6 +122,23 @@ export default function DeliverableReviewPage({ params, searchParams }: PageProp
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
) : canEdit ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<AssetUploadZone
|
||||
stageId={stageId}
|
||||
revisionId={latest.id}
|
||||
onUploaded={refreshRevisions}
|
||||
/>
|
||||
{showReplace && (
|
||||
<button
|
||||
type="button"
|
||||
className="self-start text-[12px] text-[var(--muted-foreground)] underline-offset-2 hover:underline"
|
||||
onClick={() => setShowReplace(false)}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-md border border-dashed border-[var(--border)] bg-[var(--accent)]/30 p-4 text-sm text-[var(--muted-foreground)]">
|
||||
No asset uploaded yet for {formatRevisionLabel(latest)}.
|
||||
|
|
@ -117,9 +155,9 @@ export default function DeliverableReviewPage({ params, searchParams }: PageProp
|
|||
|
||||
<p className="text-[12px] italic text-[var(--muted-foreground)]">
|
||||
Full annotation + comparison surface is being rebuilt against the
|
||||
new single-asset revision model. For now, all review actions
|
||||
(Approve, Request changes, Send to client, New revision) live in
|
||||
the in-row panel on the deliverable detail page.
|
||||
new single-asset revision model. For now, the in-row panel on the
|
||||
deliverable detail page is where Approve / Request changes / Send
|
||||
to client / New revision live.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue