"use client"; import { useState } from "react"; import Link from "next/link"; import type { PublishedBookEntry } from "@/lib/schemas/published-book"; // ── Theme maps ──────────────────────────────────────────────────────────────── const COVER_GRADIENT: Record = { amber: "from-amber-950 via-amber-900 to-amber-800", cyan: "from-cyan-950 via-cyan-900 to-cyan-800", emerald: "from-emerald-950 via-emerald-900 to-emerald-800", rose: "from-rose-950 via-rose-900 to-rose-800", violet: "from-violet-950 via-violet-900 to-violet-800", slate: "from-slate-900 via-slate-800 to-slate-700", }; const COVER_TITLE: Record = { amber: "text-amber-100", cyan: "text-cyan-100", emerald: "text-emerald-100", rose: "text-rose-100", violet: "text-violet-100", slate: "text-slate-100", }; const ACCENT_BADGE: Record = { amber: "bg-amber-500/20 text-amber-300 border-amber-500/30", cyan: "bg-cyan-500/20 text-cyan-300 border-cyan-500/30", emerald: "bg-emerald-500/20 text-emerald-300 border-emerald-500/30", rose: "bg-rose-500/20 text-rose-300 border-rose-500/30", violet: "bg-violet-500/20 text-violet-300 border-violet-500/30", slate: "bg-slate-500/20 text-slate-300 border-slate-500/30", }; // ── Book card ───────────────────────────────────────────────────────────────── function BookCard({ book }: { book: PublishedBookEntry }) { const accent = book.coverAccent ?? "amber"; const grad = COVER_GRADIENT[accent] ?? COVER_GRADIENT.amber; const title = COVER_TITLE[accent] ?? COVER_TITLE.amber; const badge = ACCENT_BADGE[accent] ?? ACCENT_BADGE.amber; const mins = Math.ceil(book.wordCount / 200); return ( {/* Book cover illustration */} {/* Book cover — real photo if available, gradient fallback */}
{book.coverImageUrl ? ( /* eslint-disable-next-line @next/next/no-img-element */ {`${book.title} ) : ( <> {/* Spine */}
{/* Page edges */}
{/* Bottom gradient */}
{/* Cover text */}

{book.authorName}

{book.title}

{book.subtitle && (

{book.subtitle}

)}
)}
{/* Below-cover metadata */}

{book.title}

{book.synopsis}

{book.chapterCount} ch {mins >= 60 ? `${Math.round(mins / 60)}h` : `${mins} min`} {book.wordCount.toLocaleString()} words
); } // ── Grid with search ────────────────────────────────────────────────────────── export default function LibraryGrid({ books }: { books: PublishedBookEntry[] }) { const [query, setQuery] = useState(""); const filtered = query.trim() ? books.filter((b) => { const q = query.toLowerCase(); return ( b.title.toLowerCase().includes(q) || b.authorName.toLowerCase().includes(q) || b.synopsis.toLowerCase().includes(q) ); }) : books; return (
{/* Search input */}
setQuery(e.target.value)} placeholder="Search books, authors…" className="w-full rounded-xl border border-slate-700/60 bg-slate-900/60 py-3 pl-11 pr-4 text-base text-slate-200 placeholder-slate-600 outline-none transition focus:border-slate-500 focus:ring-1 focus:ring-slate-600" />
{/* Book count */}

{filtered.length} {filtered.length === 1 ? "book" : "books"} {query ? ` matching "${query}"` : " published"}

{filtered.length === 0 ? (

No books match your search.

) : (
{filtered.map((book) => ( ))}
)}
); }