"use client"; import { useEffect, useState, useMemo } from "react"; import { useRouter } from "next/navigation"; import { motion, LayoutGroup } from "framer-motion"; import { Plus } from "lucide-react"; import Link from "next/link"; import { SnippetCard } from "@/components/snippet-card"; import { SearchBar } from "@/components/search-bar"; import { ViewToggle } from "@/components/view-toggle"; import { EmptyState } from "@/components/empty-state"; import { Button } from "@/components/ui/button"; import { api } from "@/lib/api-client"; import { Snippet } from "@/lib/types"; const containerVariants = { hidden: {}, visible: { transition: { staggerChildren: 0.06 } }, }; export default function SnippetsPage() { const router = useRouter(); const [snippets, setSnippets] = useState([]); const [search, setSearch] = useState(""); const [view, setView] = useState<"grid" | "list">("grid"); const [loading, setLoading] = useState(true); const [authRequired, setAuthRequired] = useState(false); useEffect(() => { api.listSnippets() .then(({ snippets }) => { setSnippets(snippets); setAuthRequired(false); }) .catch(() => { setAuthRequired(true); router.push("/login"); }) .finally(() => setLoading(false)); }, [router]); const filtered = useMemo(() => { if (!search.trim()) return snippets; const q = search.toLowerCase(); return snippets.filter( (s) => s.title.toLowerCase().includes(q) || s.language.toLowerCase().includes(q) || s.tags.some((t) => t.toLowerCase().includes(q)) || s.code.toLowerCase().includes(q) ); }, [snippets, search]); return (

Snippets

{snippets.length} snippet{snippets.length !== 1 ? "s" : ""} saved

{loading ? (
{[0, 1, 2].map((item) => (
))}
) : authRequired ? ( ) : filtered.length === 0 ? ( ) : ( {filtered.map((snippet, i) => ( ))} )}
); }