copy shot names
Deploy / deploy (push) Successful in 2m28s

This commit is contained in:
twotalesanimation
2026-06-19 12:00:04 +02:00
parent 4c64842be6
commit d04e0252f1
+76
View File
@@ -14,6 +14,8 @@ import {
Package,
RotateCcw,
ArrowUpDown,
Copy,
Check,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import { Montserrat } from 'next/font/google';
@@ -156,6 +158,15 @@ export default function ClientPortalPage({
setStatusFilter((prev) => (prev === filter ? null : filter));
};
const [copiedId, setCopiedId] = useState<string | null>(null);
const copyToClipboard = (text: string, id: string) => {
navigator.clipboard.writeText(text).then(() => {
setCopiedId(id);
setTimeout(() => setCopiedId(null), 1500);
});
};
useEffect(() => {
params.then(({ token: t }) => {
setToken(t);
@@ -458,6 +469,7 @@ export default function ClientPortalPage({
/>
</div>
)}
<div className="flex items-center gap-1.5 group/itemlabel">
<p className="font-mono text-xs text-zinc-500">
{item.label}
{item.description && (
@@ -466,6 +478,18 @@ export default function ClientPortalPage({
</span>
)}
</p>
<button
onClick={() => copyToClipboard(item.label, `label-${task.id}`)}
className="shrink-0 p-0.5 rounded opacity-0 group-hover/itemlabel:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy name"
>
{copiedId === `label-${task.id}` ? (
<Check className="h-3 w-3 text-emerald-400" />
) : (
<Copy className="h-3 w-3" />
)}
</button>
</div>
{ver?.createdAt && (
<p className="ml-auto text-xs text-zinc-600">
{formatDate(ver.createdAt)}
@@ -481,9 +505,22 @@ export default function ClientPortalPage({
)}
>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5">
<p className="text-sm font-medium text-white">
{task.title}
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (
<Check className="h-3 w-3 text-emerald-400" />
) : (
<Copy className="h-3 w-3" />
)}
</button>
</div>
<p className="text-xs text-zinc-500">
{TASK_TYPE_LABELS[task.type] ?? task.type}
</p>
@@ -597,6 +634,7 @@ export default function ClientPortalPage({
/>
</div>
)}
<div className="flex items-center gap-1.5 group/shotcode">
<p className="font-mono text-sm font-semibold text-zinc-300">
{shot.shotCode}
{shot.description && (
@@ -605,6 +643,18 @@ export default function ClientPortalPage({
</span>
)}
</p>
<button
onClick={() => copyToClipboard(shot.shotCode, `shot-${shot.id}`)}
className="shrink-0 p-0.5 rounded opacity-0 group-hover/shotcode:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy shot code"
>
{copiedId === `shot-${shot.id}` ? (
<Check className="h-3 w-3 text-emerald-400" />
) : (
<Copy className="h-3 w-3" />
)}
</button>
</div>
</div>
<div className="space-y-1.5 pl-3 border-l border-zinc-800">
{shot.tasks.map((task) => {
@@ -626,9 +676,22 @@ export default function ClientPortalPage({
)}
>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5">
<p className="text-sm font-medium text-white">
{task.title}
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (
<Check className="h-3 w-3 text-emerald-400" />
) : (
<Copy className="h-3 w-3" />
)}
</button>
</div>
<p className="text-xs text-zinc-500">
{TASK_TYPE_LABELS[task.type] ?? task.type}
</p>
@@ -719,9 +782,22 @@ export default function ClientPortalPage({
</p>
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5">
<p className="text-sm text-zinc-300 truncate">
{task.title}
</p>
<button
onClick={(e) => { e.preventDefault(); e.stopPropagation(); copyToClipboard(task.title, `task-${task.id}`); }}
className="shrink-0 p-0.5 rounded opacity-0 group-hover:opacity-100 text-zinc-600 hover:text-zinc-300 transition-all"
title="Copy task name"
>
{copiedId === `task-${task.id}` ? (
<Check className="h-3 w-3 text-emerald-400" />
) : (
<Copy className="h-3 w-3" />
)}
</button>
</div>
{ver?.notes && (
<p className="text-xs text-zinc-500 truncate italic mt-0.5">
&ldquo;{ver.notes}&rdquo;