188 lines
6.2 KiB
TypeScript
188 lines
6.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { useParams, useRouter } from "next/navigation";
|
|
import Image from "next/image";
|
|
import { ArrowLeft, ChevronLeft, ChevronRight, Home } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ThemeToggle } from "@/components/theme-toggle";
|
|
import { useGetMangaChapterImages, useMarkAsRead } from "@/api/mangamochi";
|
|
|
|
export default function ChapterReaderPage() {
|
|
const params = useParams();
|
|
const router = useRouter();
|
|
const mangaId = Number(params.id);
|
|
const chapterNumber = Number(params.chapterNumber);
|
|
|
|
const { data, isLoading } = useGetMangaChapterImages(chapterNumber);
|
|
|
|
const { mutate } = useMarkAsRead();
|
|
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
|
|
useEffect(() => {
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
if (currentPage === data.chapterImageKeys.length) {
|
|
mutate({ chapterId: chapterNumber });
|
|
}
|
|
}, [data, mutate, currentPage]);
|
|
|
|
if (!data) {
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-background">
|
|
<div className="text-center">
|
|
<h1 className="text-2xl font-bold text-foreground">
|
|
Manga not found
|
|
</h1>
|
|
<Button onClick={() => router.push("/")} className="mt-4">
|
|
Go back home
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const goToNextPage = () => {
|
|
if (currentPage < data?.chapterImageKeys.length) {
|
|
setCurrentPage(currentPage + 1);
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
}
|
|
};
|
|
|
|
const goToPreviousPage = () => {
|
|
if (currentPage > 1) {
|
|
setCurrentPage(currentPage - 1);
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background">
|
|
{/* Header */}
|
|
<header className="sticky top-0 z-50 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
<div className="px-4 py-4 sm:px-8">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-4">
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => router.push(`/manga/${mangaId}`)}
|
|
className="gap-2"
|
|
>
|
|
<ArrowLeft className="h-4 w-4" />
|
|
<span className="hidden sm:inline">Back</span>
|
|
</Button>
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={() => router.push("/")}
|
|
className="gap-2"
|
|
>
|
|
<Home className="h-4 w-4" />
|
|
<span className="hidden sm:inline">Home</span>
|
|
</Button>
|
|
<div className="hidden sm:block">
|
|
<h1 className="text-sm font-semibold text-foreground">
|
|
{data.mangaTitle}
|
|
</h1>
|
|
<p className="text-xs text-muted-foreground">
|
|
Chapter {chapterNumber}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-4">
|
|
<span className="text-sm text-muted-foreground">
|
|
Page {currentPage} / {data.chapterImageKeys.length}
|
|
</span>
|
|
<ThemeToggle />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
{/* Reader Content */}
|
|
<main className="mx-auto max-w-4xl px-4 py-8">
|
|
{/* Mobile title */}
|
|
<div className="mb-4 sm:hidden">
|
|
<h1 className="text-lg font-semibold text-foreground">
|
|
{data.mangaTitle}
|
|
</h1>
|
|
<p className="text-sm text-muted-foreground">
|
|
Chapter {chapterNumber}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Manga Page */}
|
|
<div className="relative mx-auto mb-8 overflow-hidden rounded-lg border border-border bg-muted">
|
|
<Image
|
|
src={
|
|
"http://omv.badger-pirarucu.ts.net:9000/mangamochi/" +
|
|
data.chapterImageKeys[currentPage - 1] || "/placeholder.svg"
|
|
}
|
|
alt={`Page ${currentPage}`}
|
|
width={1000}
|
|
height={1400}
|
|
className="h-auto w-full"
|
|
priority
|
|
/>
|
|
</div>
|
|
|
|
{/* Navigation Controls */}
|
|
<div className="space-y-4">
|
|
{/* Page Navigation */}
|
|
<div className="flex items-center justify-center gap-4">
|
|
<Button
|
|
onClick={goToPreviousPage}
|
|
disabled={currentPage === 1}
|
|
variant="outline"
|
|
className="gap-2 bg-transparent"
|
|
>
|
|
<ChevronLeft className="h-4 w-4" />
|
|
Previous Page
|
|
</Button>
|
|
<span className="text-sm font-medium text-foreground">
|
|
{currentPage} / {data.chapterImageKeys.length}
|
|
</span>
|
|
<Button
|
|
onClick={goToNextPage}
|
|
disabled={currentPage === data.chapterImageKeys.length}
|
|
variant="outline"
|
|
className="gap-2 bg-transparent"
|
|
>
|
|
Next Page
|
|
<ChevronRight className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
|
|
{/*/!* Chapter Navigation *!/*/}
|
|
{/*{(currentPage === data.chapterImageKeys.length || currentPage === 1) && (*/}
|
|
{/* <div className="flex items-center justify-center gap-4 border-t border-border pt-4">*/}
|
|
{/* <Button*/}
|
|
{/* onClick={goToPreviousChapter}*/}
|
|
{/* disabled={chapterNumber === 1}*/}
|
|
{/* variant="secondary"*/}
|
|
{/* className="gap-2"*/}
|
|
{/* >*/}
|
|
{/* <ChevronLeft className="h-4 w-4" />*/}
|
|
{/* Previous Chapter*/}
|
|
{/* </Button>*/}
|
|
{/* <Button*/}
|
|
{/* onClick={goToNextChapter}*/}
|
|
{/* disabled={chapterNumber === manga.chapters}*/}
|
|
{/* variant="secondary"*/}
|
|
{/* className="gap-2"*/}
|
|
{/* >*/}
|
|
{/* Next Chapter*/}
|
|
{/* <ChevronRight className="h-4 w-4" />*/}
|
|
{/* </Button>*/}
|
|
{/* </div>*/}
|
|
{/*)}*/}
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|