From e22095806dd3b5d32752a14a4313b18d0baa3ef9 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Fri, 14 Feb 2025 13:08:05 +0100 Subject: [PATCH] refacto: book page server side --- src/app/books/[bookId]/page.tsx | 168 ++------------------ src/components/reader/ClientBookReader.tsx | 45 ++++++ src/components/reader/ClientBookWrapper.tsx | 33 ++++ src/components/skeletons/BookSkeleton.tsx | 16 ++ 4 files changed, 108 insertions(+), 154 deletions(-) create mode 100644 src/components/reader/ClientBookReader.tsx create mode 100644 src/components/reader/ClientBookWrapper.tsx create mode 100644 src/components/skeletons/BookSkeleton.tsx diff --git a/src/app/books/[bookId]/page.tsx b/src/app/books/[bookId]/page.tsx index cbce58a..f9f103d 100644 --- a/src/app/books/[bookId]/page.tsx +++ b/src/app/books/[bookId]/page.tsx @@ -1,160 +1,20 @@ -"use client"; +import { Suspense } from "react"; +import { ClientBookWrapper } from "@/components/reader/ClientBookWrapper"; +import { BookSkeleton } from "@/components/skeletons/BookSkeleton"; +import { BookService } from "@/lib/services/book.service"; +import { notFound } from "next/navigation"; -import { useRouter } from "next/navigation"; -import { KomgaBook } from "@/types/komga"; -import { useEffect, useState } from "react"; -import { BookReader } from "@/components/reader/BookReader"; -import { ImageOff } from "lucide-react"; -import Image from "next/image"; -import { useToast } from "@/components/ui/use-toast"; +export default async function BookPage({ params }: { params: { bookId: string } }) { + try { + const data = await BookService.getBook(params.bookId); -interface BookData { - book: KomgaBook; - pages: number[]; -} - -export default function BookPage({ params }: { params: { bookId: string } }) { - const router = useRouter(); - const { toast } = useToast(); - const [data, setData] = useState(null); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); - const [imageError, setImageError] = useState(false); - const [isReading, setIsReading] = useState(false); - - useEffect(() => { - const fetchBookData = async () => { - try { - const response = await fetch(`/api/komga/books/${params.bookId}`); - if (!response.ok) { - const data = await response.json(); - throw new Error(data.error || "Erreur lors de la récupération du tome"); - } - const data = await response.json(); - - // Si le livre a une progression de lecture, on l'affiche dans un toast - if (data.book.readProgress?.page > 0) { - toast({ - title: "Reprise de la lecture", - description: `Reprise à la page ${data.book.readProgress.page}`, - }); - } - - setData(data); - setIsReading(true); - } catch (error) { - console.error("Erreur:", error); - setError(error instanceof Error ? error.message : "Une erreur est survenue"); - } finally { - setIsLoading(false); - } - }; - - fetchBookData(); - }, [params.bookId, toast]); - - const handleCloseReader = () => { - setIsReading(false); - router.back(); - }; - - if (isLoading) { return ( -
-
-
-
-
-
-
-
-
-
+ }> + + ); + } catch (error) { + console.error("Erreur:", error); + notFound(); } - - if (error || !data) { - return ( -
-
-

{error || "Données non disponibles"}

-
-
- ); - } - - const { book, pages } = data; - - if (isReading) { - return ; - } - - return ( -
- {/* En-tête du tome */} -
- {/* Couverture */} -
-
- {!imageError ? ( - {`Couverture setImageError(true)} - /> - ) : ( -
- -
- )} -
-
- - {/* Informations */} -
-
-

- {book.metadata.title || `Tome ${book.metadata.number}`} -

-

- {book.seriesTitle} - Tome {book.metadata.number} -

-
- - {book.metadata.summary && ( -

{book.metadata.summary}

- )} - -
- {book.metadata.releaseDate && ( -
- Date de sortie :{" "} - {new Date(book.metadata.releaseDate).toLocaleDateString()} -
- )} - {book.metadata.authors?.length > 0 && ( -
- Auteurs :{" "} - {book.metadata.authors - .map((author) => `${author.name} (${author.role})`) - .join(", ")} -
- )} - {book.size && ( -
- Taille : {book.size} -
- )} - {book.media.pagesCount > 0 && ( -
- Pages : {book.media.pagesCount} -
- )} -
-
-
-
- ); } diff --git a/src/components/reader/ClientBookReader.tsx b/src/components/reader/ClientBookReader.tsx new file mode 100644 index 0000000..279efa2 --- /dev/null +++ b/src/components/reader/ClientBookReader.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { KomgaBook } from "@/types/komga"; +import { BookReader } from "./BookReader"; +import { Button } from "@/components/ui/button"; +import { useToast } from "@/components/ui/use-toast"; + +interface ClientBookReaderProps { + book: KomgaBook; + pages: number[]; +} + +export function ClientBookReader({ book, pages }: ClientBookReaderProps) { + const router = useRouter(); + const { toast } = useToast(); + const [isReading, setIsReading] = useState(false); + + const handleStartReading = () => { + // Si le livre a une progression de lecture, on l'affiche dans un toast + if (book.readProgress && book.readProgress.page && book.readProgress.page > 0) { + toast({ + title: "Reprise de la lecture", + description: `Reprise à la page ${book.readProgress.page}`, + }); + } + setIsReading(true); + }; + + const handleCloseReader = () => { + setIsReading(false); + router.back(); + }; + + if (isReading) { + return ; + } + + return ( + + ); +} diff --git a/src/components/reader/ClientBookWrapper.tsx b/src/components/reader/ClientBookWrapper.tsx new file mode 100644 index 0000000..8862b09 --- /dev/null +++ b/src/components/reader/ClientBookWrapper.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { KomgaBook } from "@/types/komga"; +import { BookReader } from "./BookReader"; +import { useRouter } from "next/navigation"; +import { useEffect } from "react"; +import { useToast } from "@/components/ui/use-toast"; + +interface ClientBookWrapperProps { + book: KomgaBook; + pages: number[]; +} + +export function ClientBookWrapper({ book, pages }: ClientBookWrapperProps) { + const router = useRouter(); + const { toast } = useToast(); + + useEffect(() => { + // Si le livre a une progression de lecture, on l'affiche dans un toast + if (book.readProgress && book.readProgress.page && book.readProgress.page > 0) { + toast({ + title: "Reprise de la lecture", + description: `Reprise à la page ${book.readProgress.page}`, + }); + } + }, [book.readProgress, toast]); + + const handleCloseReader = () => { + router.back(); + }; + + return ; +} diff --git a/src/components/skeletons/BookSkeleton.tsx b/src/components/skeletons/BookSkeleton.tsx new file mode 100644 index 0000000..5ac7b66 --- /dev/null +++ b/src/components/skeletons/BookSkeleton.tsx @@ -0,0 +1,16 @@ +export function BookSkeleton() { + return ( +
+
+ {/* Barre de navigation */} +
+ + {/* Page du livre */} +
+ + {/* Barre de contrôles */} +
+
+
+ ); +}