Storyboard Feature
Deploy / deploy (push) Successful in 2m53s

This commit is contained in:
twotalesanimation
2026-07-22 12:19:19 +02:00
parent c968b8a46a
commit 77a3161f0c
6 changed files with 906 additions and 4 deletions
+20 -4
View File
@@ -7,6 +7,7 @@ import { TakeListPanel } from "./TakeListPanel";
import { TakeEditorPanel, type FullTake } from "./TakeEditorPanel";
import { NewShootDayDialog } from "./NewShootDayDialog";
import { NewSetupDialog } from "./NewSetupDialog";
import { cn } from "@/lib/utils";
// ─── Types ────────────────────────────────────────────────────────────────────
@@ -28,6 +29,8 @@ export function ShootLogClient({ projects }: Props) {
const [projectId, setProjectId] = useState<string>(projects[0]?.id ?? "");
const [selectedTakeId, setSelectedTakeId] = useState<string | null>(null);
const [selectedSetupId, setSelectedSetupId] = useState<string | null>(null);
// Controls which panel is visible on mobile (< md)
const [mobileView, setMobileView] = useState<"list" | "editor">("list");
// Which day to auto-expand in the left panel after creation
const [expandDayId, setExpandDayId] = useState<string | null>(null);
@@ -92,6 +95,7 @@ export function ShootLogClient({ projects }: Props) {
invalidateDays();
setSelectedTakeId(newTake.id);
setSelectedSetupId(setupId);
setMobileView("editor");
},
[invalidateDays]
);
@@ -122,6 +126,7 @@ export function ShootLogClient({ projects }: Props) {
setExpandDayId(day.id);
setSelectedTakeId(newTake.id);
setSelectedSetupId(setup.id);
setMobileView("editor");
} catch {
// Day was created but setup/take failed — still refresh
invalidateDays();
@@ -158,6 +163,7 @@ export function ShootLogClient({ projects }: Props) {
if (!confirm("Delete this take? This cannot be undone.")) return;
await fetch(`/api/shoot-log/takes/${selectedTakeId}`, { method: "DELETE" });
setSelectedTakeId(null);
setMobileView("list");
invalidateDays();
}, [selectedTakeId, invalidateDays]);
@@ -186,6 +192,7 @@ export function ShootLogClient({ projects }: Props) {
setSelectedTakeId(null);
setSelectedSetupId(null);
setExpandDayId(null);
setMobileView("list");
}}
className="bg-zinc-800 border border-zinc-700 rounded-lg text-sm text-white px-3 py-1.5 focus:outline-none focus:border-amber-600"
>
@@ -207,8 +214,12 @@ export function ShootLogClient({ projects }: Props) {
{/* Split layout */}
<div className="flex flex-1 overflow-hidden min-h-0">
{/* Left panel */}
<div className="w-72 xl:w-80 shrink-0 border-r border-zinc-800 overflow-hidden flex flex-col">
{/* Left panel — full width on mobile, fixed sidebar on md+ */}
<div className={cn(
"shrink-0 border-r border-zinc-800 overflow-hidden flex-col",
"w-full md:w-72 xl:w-80",
mobileView === "editor" ? "hidden md:flex" : "flex"
)}>
<TakeListPanel
projectId={projectId}
selectedTakeId={selectedTakeId}
@@ -216,6 +227,7 @@ export function ShootLogClient({ projects }: Props) {
onSelectTake={(takeId, setupId) => {
setSelectedTakeId(takeId);
setSelectedSetupId(setupId);
setMobileView("editor");
}}
onNewDay={() => setNewDayOpen(true)}
onNewSetup={(dayId) => setNewSetupDayId(dayId)}
@@ -223,8 +235,11 @@ export function ShootLogClient({ projects }: Props) {
/>
</div>
{/* Right panel */}
<div className="flex-1 overflow-hidden flex flex-col">
{/* Right panel — hidden on mobile when list is showing */}
<div className={cn(
"flex-1 overflow-hidden flex-col",
mobileView === "list" ? "hidden md:flex" : "flex"
)}>
{takeLoading ? (
<div className="flex items-center justify-center h-full">
<Loader2 className="h-6 w-6 animate-spin text-zinc-500" />
@@ -240,6 +255,7 @@ export function ShootLogClient({ projects }: Props) {
onNewTake={() => createTake(take.setupId)}
onDelete={handleDelete}
onAttachmentsChange={invalidateDays}
onBack={() => setMobileView("list")}
/>
) : (
<div className="flex flex-col items-center justify-center h-full gap-3 text-zinc-600">
+9
View File
@@ -498,6 +498,7 @@ interface Props {
onNewTake: () => void;
onDelete: () => void;
onAttachmentsChange: () => void;
onBack?: (() => void) | null;
}
export function TakeEditorPanel({
@@ -509,6 +510,7 @@ export function TakeEditorPanel({
onNewTake,
onDelete,
onAttachmentsChange,
onBack,
}: Props) {
const { status, queue } = useAutosave(take.id);
@@ -550,6 +552,13 @@ export function TakeEditorPanel({
<div className="flex flex-col h-full overflow-hidden">
{/* ── Nav bar ── */}
<div className="flex items-center gap-2 px-4 py-3 border-b border-zinc-800 shrink-0 flex-wrap">
{/* Back to list — mobile only */}
{onBack && (
<Button size="sm" variant="ghost" className="md:hidden -ml-2 text-zinc-400 shrink-0" onClick={onBack}>
<ChevronLeft className="h-4 w-4" />
List
</Button>
)}
<div className="flex items-center gap-1">
<Button size="icon-sm" variant="ghost" disabled={!onPrev} onClick={onPrev ?? undefined} title="Previous take (←)">
<ChevronLeft className="h-4 w-4" />