feat(web): bibliothèque et lecteur — grilles de livres bornées à 5 colonnes (max-width calc sur .book-grid et .home-book-grid), retrait du bandeau « API absente ou incomplete » de l'accueil, et véritables pages d'erreur « Livre introuvable » sur fiche et lecteur (suppression de getApiFallback, retour à l'accueil + réessayer — évolution #46)
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import { Component, useCallback, useEffect, useMemo, useState, type ErrorInfo, type ReactNode } from "react";
|
||||
import type { BookDto } from "@readabook/shared";
|
||||
import { api, getApiFallback } from "../api/client";
|
||||
import { api } from "../api/client";
|
||||
import { CbzReader } from "../reader/CbzReader";
|
||||
import { EpubReader } from "../reader/EpubReader";
|
||||
import { pageLocator, parseCbrPageLocator, parseCbzPageLocator, parsePdfPageLocator, pdfPagePercent } from "../reader/locators";
|
||||
@ -11,6 +11,7 @@ import { majorityVisiblePage, type ReaderMode } from "../reader/readerScroll";
|
||||
import { useReaderPreferences } from "../reader/useReaderPreferences";
|
||||
import { useReaderProgress } from "../reader/useReaderProgress";
|
||||
import { navigate } from "../router";
|
||||
import { EmptyState, LoadingState, Panel } from "../components/ui";
|
||||
|
||||
const idleControls: ReaderControls = {
|
||||
canPrevious: false,
|
||||
@ -74,10 +75,9 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
setError(undefined);
|
||||
try {
|
||||
setBook(await api.book(bookId));
|
||||
} catch (loadError) {
|
||||
const fallback = getApiFallback<BookDto>(loadError);
|
||||
setBook(fallback ?? null);
|
||||
setError(fallback ? "Lecteur ouvert en mode secours." : "Ouvrage indisponible.");
|
||||
} catch {
|
||||
setBook(null);
|
||||
setError("Ce livre n'existe pas dans le catalogue.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@ -206,6 +206,26 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
[changeMode, mode, supportsMode]
|
||||
);
|
||||
|
||||
if (loading && !book) return <LoadingState />;
|
||||
|
||||
if (!book) {
|
||||
return (
|
||||
<section className="reader-missing-page" role="alert">
|
||||
<Panel>
|
||||
<EmptyState title="Livre introuvable" detail={error ?? "Le serveur n'a pas renvoye cet ouvrage."} />
|
||||
<div className="reader-error-actions">
|
||||
<button className="ghost-button" onClick={() => navigate("/home")}>
|
||||
Retour à l'accueil
|
||||
</button>
|
||||
<button className="ghost-button" onClick={() => void loadBook()}>
|
||||
Réessayer
|
||||
</button>
|
||||
</div>
|
||||
</Panel>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ReaderShell
|
||||
title={book?.title ?? "Ouverture du lecteur"}
|
||||
@ -251,14 +271,7 @@ export function ReaderPage({ bookId }: { bookId: number }) {
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
{!book ? (
|
||||
<div className="reader-fallback">
|
||||
<span>{error ?? "Chargement du livre."}</span>
|
||||
<button className="ghost-button" onClick={() => void loadBook()}>
|
||||
Reessayer
|
||||
</button>
|
||||
</div>
|
||||
) : book.format === "pdf" ? (
|
||||
{book.format === "pdf" ? (
|
||||
<PdfReader
|
||||
url={fileUrl}
|
||||
page={page}
|
||||
|
||||
Reference in New Issue
Block a user