"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { History, RotateCcw, ChevronDown } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; type VersionSummary = { id: string; version: number; title: string; createdAt: string; }; type SnapshotData = { ingredients: unknown[]; steps: unknown[]; }; type VersionDetail = { id: string; version: number; title: string; createdAt: string; snapshotData: SnapshotData; }; function formatDate(dateStr: string): string { const date = new Date(dateStr); return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }); } export function VersionHistoryButton({ recipeId }: { recipeId: string }) { const router = useRouter(); const [open, setOpen] = useState(false); const [versions, setVersions] = useState([]); const [loading, setLoading] = useState(false); const [expandedId, setExpandedId] = useState(null); const [expandedData, setExpandedData] = useState>({}); const [restoringId, setRestoringId] = useState(null); async function handleOpen(isOpen: boolean) { setOpen(isOpen); if (isOpen) { setLoading(true); try { const res = await fetch(`/api/v1/recipes/${recipeId}/versions`); if (res.ok) { const data = await res.json() as VersionSummary[]; setVersions(data); } } finally { setLoading(false); } } } async function handleExpand(version: VersionSummary) { if (expandedId === version.id) { setExpandedId(null); return; } setExpandedId(version.id); if (!expandedData[version.id]) { const res = await fetch(`/api/v1/recipes/${recipeId}/versions/${version.id}`); if (res.ok) { const data = await res.json() as VersionDetail; setExpandedData((prev) => ({ ...prev, [version.id]: data })); } } } async function handleRestore(version: VersionSummary) { setRestoringId(version.id); try { const res = await fetch(`/api/v1/recipes/${recipeId}/versions/${version.id}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ action: "restore" }), }); if (res.ok) { toast.success(`Recipe restored to version ${version.version}`); setOpen(false); router.refresh(); } else { toast.error("Failed to restore version"); } } finally { setRestoringId(null); } } return ( History } /> Version History
{loading && (

Loading versions...

)} {!loading && versions.length === 0 && (

No versions yet. Versions are saved automatically when you edit this recipe.

)} {versions.map((v) => { const isExpanded = expandedId === v.id; const detail = expandedData[v.id]; return (
{isExpanded && (
{!detail ? (

Loading...

) : (

{(detail.snapshotData.ingredients as unknown[]).length} ingredient{(detail.snapshotData.ingredients as unknown[]).length !== 1 ? "s" : ""},{" "} {(detail.snapshotData.steps as unknown[]).length} step{(detail.snapshotData.steps as unknown[]).length !== 1 ? "s" : ""}

)}
)}
); })}
); }