import { fetchAllSeries, fetchLibraries, fetchSeriesStatuses, LibraryDto, SeriesDto, SeriesPageDto, getBookCoverUrl } from "../../lib/api"; import { MarkSeriesReadButton } from "../components/MarkSeriesReadButton"; import { LiveSearchForm } from "../components/LiveSearchForm"; import { Card, CardContent, OffsetPagination } from "../components/ui"; import Image from "next/image"; import Link from "next/link"; export const dynamic = "force-dynamic"; export default async function SeriesPage({ searchParams, }: { searchParams: Promise<{ [key: string]: string | string[] | undefined }>; }) { const searchParamsAwaited = await searchParams; const libraryId = typeof searchParamsAwaited.library === "string" ? searchParamsAwaited.library : undefined; const searchQuery = typeof searchParamsAwaited.q === "string" ? searchParamsAwaited.q : ""; const readingStatus = typeof searchParamsAwaited.status === "string" ? searchParamsAwaited.status : undefined; const sort = typeof searchParamsAwaited.sort === "string" ? searchParamsAwaited.sort : undefined; const seriesStatus = typeof searchParamsAwaited.series_status === "string" ? searchParamsAwaited.series_status : undefined; const hasMissing = searchParamsAwaited.has_missing === "true"; const page = typeof searchParamsAwaited.page === "string" ? parseInt(searchParamsAwaited.page) : 1; const limit = typeof searchParamsAwaited.limit === "string" ? parseInt(searchParamsAwaited.limit) : 20; const [libraries, seriesPage, dbStatuses] = await Promise.all([ fetchLibraries().catch(() => [] as LibraryDto[]), fetchAllSeries(libraryId, searchQuery || undefined, readingStatus, page, limit, sort, seriesStatus, hasMissing).catch( () => ({ items: [] as SeriesDto[], total: 0, page: 1, limit }) as SeriesPageDto ), fetchSeriesStatuses().catch(() => [] as string[]), ]); const series = seriesPage.items; const totalPages = Math.ceil(seriesPage.total / limit); const sortOptions = [ { value: "", label: "Titre" }, { value: "latest", label: "Ajout récent" }, ]; const hasFilters = searchQuery || libraryId || readingStatus || sort || seriesStatus || hasMissing; const libraryOptions = [ { value: "", label: "Toutes les bibliothèques" }, ...libraries.map((lib) => ({ value: lib.id, label: lib.name })), ]; const statusOptions = [ { value: "", label: "Tous" }, { value: "unread", label: "Non lu" }, { value: "reading", label: "En cours" }, { value: "read", label: "Lu" }, ]; const KNOWN_STATUSES: Record = { ongoing: "En cours", ended: "Terminée", hiatus: "Hiatus", cancelled: "Annulée", upcoming: "À paraître", }; const seriesStatusOptions = [ { value: "", label: "Tous les statuts" }, ...dbStatuses.map((s) => ({ value: s, label: KNOWN_STATUSES[s] || s })), ]; const missingOptions = [ { value: "", label: "Tous" }, { value: "true", label: "Livres manquants" }, ]; return ( <>

Séries

{/* Results count */}

{seriesPage.total} séries {searchQuery && <> correspondant à "{searchQuery}"}

{/* Series Grid */} {series.length > 0 ? ( <>
{series.map((s) => (
= s.book_count ? "opacity-50" : "" }`} >
{`Couverture

{s.name === "unclassified" ? "Non classé" : s.name}

{s.books_read_count}/{s.book_count} lu{s.book_count !== 1 ? "s" : ""}

{s.series_status && ( {s.series_status === "ongoing" ? "En cours" : s.series_status === "ended" ? "Terminée" : s.series_status === "hiatus" ? "Hiatus" : s.series_status === "cancelled" ? "Annulée" : s.series_status === "upcoming" ? "À paraître" : s.series_status} )} {s.missing_count != null && s.missing_count > 0 && ( {s.missing_count} manquant{s.missing_count > 1 ? "s" : ""} )}
))}
) : (

{hasFilters ? "Aucune série trouvée correspondant à vos filtres" : "Aucune série disponible"}

)} ); }