import { useMemo, useState, type FC } from "hono/jsx/dom"; import { StatusSelect, RatingSelect, DeleteButton, BookCover, DateInput, STATUS_LABELS, updateBook, deleteBook, } from "./bookActions"; type LibraryBook = { hiveId: string; title: string; authors: string; cover?: string | null; thumbnail?: string | null; status: string | null; stars: number | null; startedAt: string | null; finishedAt: string | null; createdAt: string; owned: number; review: string | null; }; const FINISHED = "buzz.bookhive.defs#finished"; // --- Desktop row --- const TableRow: FC<{ book: LibraryBook; onUpdate: (fields: Partial) => void; onDelete: () => void; }> = ({ book, onUpdate, onDelete }) => ( (window.location.href = `/books/${book.hiveId}`)} >

{book.title}

{book.authors.split("\t").join(", ")}

e.stopPropagation()}> { onUpdate({ status }); void updateBook(book.hiveId, { status }); }} /> e.stopPropagation()}> { onUpdate({ stars }); void updateBook(book.hiveId, { stars }); }} /> e.stopPropagation()}>
{ onUpdate({ startedAt }); void updateBook(book.hiveId, { startedAt }); }} />
{ onUpdate({ finishedAt }); void updateBook(book.hiveId, { finishedAt }); }} />
e.stopPropagation()}> { onDelete(); void deleteBook(book.hiveId); }} /> ); // --- Mobile card --- const MobileCard: FC<{ book: LibraryBook; onUpdate: (fields: Partial) => void; onDelete: () => void; }> = ({ book, onUpdate, onDelete }) => (
{book.title}
{book.authors.split("\t").join(", ")}
{book.status && (
{STATUS_LABELS[book.status] || book.status}
)}
e.stopPropagation()}> { onUpdate({ status }); void updateBook(book.hiveId, { status }); }} />
{ onUpdate({ startedAt }); void updateBook(book.hiveId, { startedAt }); }} />
{ onUpdate({ finishedAt }); void updateBook(book.hiveId, { finishedAt }); }} />
); // --- Main component --- export const LibraryTable: FC<{ initialBooks: LibraryBook[] }> = ({ initialBooks }) => { const [books, setBooks] = useState(initialBooks); const sortedBooks = useMemo(() => { return [...books].sort((a, b) => { const aIsFinished = a.status === FINISHED; const bIsFinished = b.status === FINISHED; if (aIsFinished && bIsFinished) { if (!a.finishedAt && !b.finishedAt) return 0; if (!a.finishedAt) return 1; if (!b.finishedAt) return -1; return new Date(b.finishedAt).getTime() - new Date(a.finishedAt).getTime(); } return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); }); }, [books]); const updateBook_ = (hiveId: string, fields: Partial) => { setBooks((prev) => prev.map((b) => (b.hiveId === hiveId ? { ...b, ...fields } : b))); }; const deleteBook_ = (hiveId: string) => { setBooks((prev) => prev.filter((b) => b.hiveId !== hiveId)); }; if (!books.length) { return (

No books in your library yet. Start adding books to see them here!

); } return ( <> {/* Desktop: table view */}
{sortedBooks.map((book) => ( updateBook_(book.hiveId, fields)} onDelete={() => deleteBook_(book.hiveId)} /> ))}
Book Status Rating Dates Actions
{/* Mobile: card view */}
{sortedBooks.map((book) => ( updateBook_(book.hiveId, fields)} onDelete={() => deleteBook_(book.hiveId)} /> ))}
); };