import Link from "next/link"; import { Layers, Plus, ArrowDownAZ, Hash, RectangleVertical, RectangleHorizontal } from "lucide-react"; import { listAllTagCategories, type CategorySort } from "@/lib/db/queries"; import { createTagCategoryAction } from "@/app/actions/tagCategories"; import { CategoryGridCard } from "@/components/categories/CategoryGridCard"; import { cn } from "@/lib/utils"; export const dynamic = "force-dynamic"; type View = "portrait" | "landscape"; export default async function CategoriesPage({ searchParams, }: { searchParams: Promise>; }) { const sp = await searchParams; const sort: CategorySort = sp.sort === "count" ? "count" : "az"; const view: View = sp.view === "landscape" ? "landscape" : "portrait"; const qs = (overrides: Partial<{ sort: CategorySort; view: View }>) => { const params = new URLSearchParams(); const finalSort = overrides.sort ?? sort; const finalView = overrides.view ?? view; if (finalSort === "count") params.set("sort", "count"); if (finalView === "landscape") params.set("view", "landscape"); const s = params.toString(); return s ? `/category?${s}` : "/category"; }; const cats = listAllTagCategories(sort); return (

Categories

Umbrellas that group related tags. A category like BDSM can collect{" "} bondage,{" "} shibari,{" "} cuffs, etc. Each tag belongs to at most one category.

{cats.length} categor{cats.length === 1 ? "y" : "ies"}

A-Z Count
P L
{cats.length === 0 ? (

No categories yet. Create one above to start grouping tags.

) : view === "portrait" ? ( // Target 7 per row at full desktop width; scale down responsively.
{cats.map((c) => ( ))}
) : ( // Landscape: 3 per row at desktop; 1-2 on smaller screens.
{cats.map((c) => ( ))}
)}
); }