Files
dhkatzandClaude Opus 5.5 51d5bb5ff3 Website: products, library, catalogs and their console page
/products (search), product pages with revisions, getting and staying on a
revision, retracting; /products/:id/edit; /create and new revisions upload
from the browser straight to the catalog with a token from the hub;
/library; /catalogs (directory, registering with a once-shown key);
/console/catalogs to approve or reject. Every page now sends a nonce-based
CSP (proxy.ts), so product descriptions can't run scripts.

buttonVariants now merges classes, so outline links get their border.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-29 19:06:08 -07:00

47 lines
1.7 KiB
TypeScript

import type { Metadata } from "next";
import Link from "next/link";
import { redirect } from "next/navigation";
import { ActionForm, SubmitButton } from "@/components/forms";
import { Empty, ProductCard } from "@/components/products";
import { PageHeader } from "@/components/status";
import { api, getMe, unwrap } from "@/lib/api";
import { libraryAction } from "../products/actions";
export const metadata: Metadata = { title: "Library" };
export default async function Library() {
const me = await getMe();
if (!me) redirect("/signin?next=/library");
const { library } = await api.library.get().then(unwrap);
return (
<>
<PageHeader title="Your library">Products your T5DE uses, on all your IMVU accounts.</PageHeader>
{library.length === 0 ? (
<Empty>
Nothing yet.{" "}
<Link href="/products" className="text-foreground underline underline-offset-4">
Browse products
</Link>
.
</Empty>
) : (
<ul className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{library.map(({ product, stayOn }) => (
<li key={product.id}>
<ProductCard product={product}>
{stayOn !== null && <p className="text-xs">Staying on revision {stayOn}</p>}
<ActionForm action={libraryAction} fields={{ id: product.id }} className="pt-1">
<SubmitButton size="sm" variant="outline" name="intent" value="remove" pendingLabel="Removing…">
Remove
</SubmitButton>
</ActionForm>
</ProductCard>
</li>
))}
</ul>
)}
</>
);
}