From 99d1c46b7f5537f398a397a2d36731031debe71d Mon Sep 17 00:00:00 2001
From: twotalesanimation <80506065+twotalesanimation@users.noreply.github.com>
Date: Sun, 12 Jul 2026 10:36:29 +0200
Subject: [PATCH] reference support
---
components/shoot-log/TakeEditorPanel.tsx | 187 ++++++++++++++++++-----
1 file changed, 151 insertions(+), 36 deletions(-)
diff --git a/components/shoot-log/TakeEditorPanel.tsx b/components/shoot-log/TakeEditorPanel.tsx
index e28076d..98ec018 100644
--- a/components/shoot-log/TakeEditorPanel.tsx
+++ b/components/shoot-log/TakeEditorPanel.tsx
@@ -213,7 +213,88 @@ interface LinkedShot {
references: { id: string; fileUrl: string; fileName: string; label: string | null }[];
}
+interface LightboxItem {
+ url: string;
+ label: string;
+}
+
+function ShotLightbox({
+ items,
+ index,
+ onClose,
+}: {
+ items: LightboxItem[];
+ index: number;
+ onClose: () => void;
+}) {
+ const [current, setCurrent] = useState(index);
+ const item = items[current];
+
+ // Keyboard navigation
+ useEffect(() => {
+ function onKey(e: KeyboardEvent) {
+ if (e.key === "Escape") onClose();
+ if (e.key === "ArrowLeft") setCurrent((c) => Math.max(0, c - 1));
+ if (e.key === "ArrowRight") setCurrent((c) => Math.min(items.length - 1, c + 1));
+ }
+ window.addEventListener("keydown", onKey);
+ return () => window.removeEventListener("keydown", onKey);
+ }, [items.length, onClose]);
+
+ return (
+
+
+
+
e.stopPropagation()}
+ >
+ {/* eslint-disable-next-line @next/next/no-img-element */}
+

+
+
+
{item.label}
+
+ {items.length > 1 && (
+
e.stopPropagation()}>
+
+
+ {current + 1} / {items.length}
+
+
+
+ )}
+
+ );
+}
+
function LinkedShotPanel({ shotId }: { shotId: string }) {
+ const [lightboxIndex, setLightboxIndex] = useState(null);
+
const { data, isLoading } = useQuery<{ shot: LinkedShot }>({
queryKey: ["linked-shot", shotId],
queryFn: async () => {
@@ -239,46 +320,80 @@ function LinkedShotPanel({ shotId }: { shotId: string }) {
const hasContent = shot.thumbnailUrl || shot.references.length > 0;
if (!hasContent) return null;
+ // Build a flat list of lightbox items: thumbnail first, then references
+ const lightboxItems: LightboxItem[] = [
+ ...(shot.thumbnailUrl
+ ? [{ url: shot.thumbnailUrl, label: `${shot.shotCode} — Thumbnail` }]
+ : []),
+ ...shot.references.map((ref) => ({
+ url: ref.fileUrl,
+ label: ref.label ?? ref.fileName,
+ })),
+ ];
+
+ // Index offsets: thumbnail is 0 (if present), refs start at offset
+ const thumbLightboxIndex = shot.thumbnailUrl ? 0 : null;
+ const refLightboxOffset = shot.thumbnailUrl ? 1 : 0;
+
return (
-
-
-
- Shot Reference — {shot.shotCode}
+ <>
+
+
+
+ Shot Reference — {shot.shotCode}
+
+
+ {shot.thumbnailUrl && (
+
setLightboxIndex(thumbLightboxIndex!)}
+ >
+
+
+
+ )}
+
+ {shot.references.length > 0 && (
+
+ {shot.references.map((ref, i) => (
+
setLightboxIndex(refLightboxOffset + i)}
+ >
+
+
+ {ref.label && (
+
+ {ref.label}
+
+ )}
+
+ ))}
+
+ )}
- {shot.thumbnailUrl && (
-
-
-
+ {lightboxIndex !== null && (
+
setLightboxIndex(null)}
+ />
)}
-
- {shot.references.length > 0 && (
-
- {shot.references.map((ref) => (
-
-
- {ref.label && (
-
- {ref.label}
-
- )}
-
- ))}
-
- )}
-
+ >
);
}