"use client"; import { useState } from "react"; import Image from "next/image"; import Link from "next/link"; import { BookDto, ReadingStatus } from "../../lib/api"; import { useTranslation } from "../../lib/i18n/context"; const readingStatusOverlayClasses: Record = { unread: null, reading: "bg-amber-500/90 text-white", read: "bg-green-600/90 text-white", }; interface BookCardProps { book: BookDto & { coverUrl?: string }; readingStatus?: ReadingStatus; } function BookImage({ src, alt }: { src: string; alt: string }) { const [isLoaded, setIsLoaded] = useState(false); const [hasError, setHasError] = useState(false); if (hasError) { return (
); } return (
{/* Skeleton */}
{/* Image */} {alt} setIsLoaded(true)} onError={() => setHasError(true)} unoptimized />
); } export function BookCard({ book, readingStatus }: BookCardProps) { const { t } = useTranslation(); const coverUrl = book.coverUrl || `/api/books/${book.id}/thumbnail`; const status = readingStatus ?? book.reading_status; const overlayClass = status ? readingStatusOverlayClasses[status] : null; const statusLabels: Record = { unread: t("status.unread"), reading: t("status.reading"), read: t("status.read"), }; const isRead = status === "read"; return (
{overlayClass && status && ( {statusLabels[status]} )}
{/* Book Info */}

{book.title}

{book.author && (

{book.author}

)} {book.series && (

{book.series} {book.volume && #{book.volume}}

)} {/* Meta Tags */}
{(book.format ?? book.kind) && ( {book.format ?? book.kind} )} {book.language && ( {book.language} )}
); } interface BooksGridProps { books: (BookDto & { coverUrl?: string })[]; } export function BooksGrid({ books }: BooksGridProps) { return (
{books.map((book) => ( ))}
); } interface EmptyStateProps { message: string; } export function EmptyState({ message }: EmptyStateProps) { return (

{message}

); }