feat: enhance service worker caching strategies and implement offline accessibility checks for books

This commit is contained in:
Julien Froidefond
2025-10-19 20:23:37 +02:00
parent d3860ce7cc
commit bc3da12fbb
8 changed files with 417 additions and 240 deletions

View File

@@ -5,6 +5,7 @@ import { BookCover } from "@/components/ui/book-cover";
import { useState, useEffect } from "react";
import { useTranslate } from "@/hooks/useTranslate";
import { cn } from "@/lib/utils";
import { useBookOfflineStatus } from "@/hooks/useBookOfflineStatus";
interface BookGridProps {
books: KomgaBook[];
@@ -12,6 +13,53 @@ interface BookGridProps {
isCompact?: boolean;
}
interface BookCardProps {
book: KomgaBook;
onBookClick: (book: KomgaBook) => void;
onSuccess: (book: KomgaBook, action: "read" | "unread") => void;
isCompact: boolean;
}
function BookCard({ book, onBookClick, onSuccess, isCompact }: BookCardProps) {
const { t } = useTranslate();
const { isAccessible } = useBookOfflineStatus(book.id);
const handleClick = () => {
// Ne pas permettre le clic si le livre n'est pas accessible
if (!isAccessible) return;
onBookClick(book);
};
return (
<div
className={cn(
"group relative aspect-[2/3] overflow-hidden rounded-lg bg-muted",
isCompact ? "hover:scale-105 transition-transform" : "",
!isAccessible ? "cursor-not-allowed" : ""
)}
>
<div
onClick={handleClick}
className={cn(
"w-full h-full hover:opacity-100 transition-all",
isAccessible ? "cursor-pointer" : "cursor-not-allowed"
)}
>
<BookCover
book={book}
alt={t("books.coverAlt", {
title: book.metadata.title ||
(book.metadata.number
? t("navigation.volume", { number: book.metadata.number })
: ""),
})}
onSuccess={(book, action) => onSuccess(book, action)}
/>
</div>
</div>
);
}
export function BookGrid({ books, onBookClick, isCompact = false }: BookGridProps) {
const [localBooks, setLocalBooks] = useState(books);
const { t } = useTranslate();
@@ -69,33 +117,15 @@ export function BookGrid({ books, onBookClick, isCompact = false }: BookGridProp
: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-5"
)}
>
{localBooks.map((book) => {
return (
<div
key={book.id}
className={cn(
"group relative aspect-[2/3] overflow-hidden rounded-lg bg-muted",
isCompact ? "hover:scale-105 transition-transform" : ""
)}
>
<div
onClick={() => onBookClick(book)}
className="w-full h-full hover:opacity-100 transition-all cursor-pointer"
>
<BookCover
book={book}
alt={t("books.coverAlt", {
title: book.metadata.title ||
(book.metadata.number
? t("navigation.volume", { number: book.metadata.number })
: ""),
})}
onSuccess={(book, action) => handleOnSuccess(book, action)}
/>
</div>
</div>
);
})}
{localBooks.map((book) => (
<BookCard
key={book.id}
book={book}
onBookClick={onBookClick}
onSuccess={handleOnSuccess}
isCompact={isCompact}
/>
))}
</div>
);
}