import { notFound } from "next/navigation" import Link from "next/link" import { BookOpen, Eye, BookMarked, User, Clock, Layers } from "lucide-react" import { formatViews } from "@/lib/utils" import { GenreBadge } from "@/components/genre-badge" import { StarRating } from "@/components/star-rating" import { ChapterList } from "@/components/chapter-list" import { CommentSection } from "@/components/comment-section" import { NovelDetailActions } from "./novel-detail-actions" import { getNovelStatusBadgeClass } from "@/lib/novel-status" import { readerApiFetch, readerApiFetchNullable } from "@/lib/server-api" export const dynamic = "force-dynamic" type NovelGenre = { id: string name: string slug: string } type SeriesNovel = { id: string slug: string title: string status: string totalChapters: number coverUrl: string | null } type NovelDetail = { id: string title: string slug: string originalTitle: string | null authorName: string originalAuthorName: string | null description: string | null coverUrl: string | null status: string totalChapters: number views: number ratingCount: number bookmarkCount: number seriesId: string | null genres: NovelGenre[] series: { id: string name: string slug: string novels: SeriesNovel[] } | null } type ChaptersResponse = { chapters: Array<{ id: string number: number title: string views: number createdAt: string | null volumeNumber?: number | null volumeTitle?: string | null volumeChapterNumber?: number | null }> totalChapters: number totalPages: number } type CommentsResponse = { comments: Array<{ id: string userId: string username: string content: string chapterId?: string | null createdAt: string | null }> } export default async function NovelDetailPage({ params, searchParams }: { params: Promise<{ slug: string }>, searchParams: Promise<{ page?: string }> }) { const { slug } = await params const { page } = await searchParams const currentPage = Math.max(1, parseInt(page || "1", 10) || 1) const limit = 20 const novel = await readerApiFetchNullable(`/api/novels/${encodeURIComponent(slug)}`) if (!novel) { notFound() } let formattedChapters: any[] = [] let totalChapters = 0 let totalPages = 1 let firstChapterNumber: number | undefined let seriesVolumes: Array<{ id: string slug: string title: string status: string totalChapters: number coverUrl: string | null }> = [] const [firstChapterData, commentsData, chapterCommentsData, chaptersData] = await Promise.all([ readerApiFetch(`/api/truyen/${encodeURIComponent(novel.id)}/chapters?page=1&limit=1`), readerApiFetch(`/api/truyen/${encodeURIComponent(novel.id)}/comments?page=1&limit=50`), readerApiFetch(`/api/truyen/${encodeURIComponent(novel.id)}/comments?scope=chapter&page=1&limit=50`), novel.seriesId ? Promise.resolve(null) : readerApiFetch(`/api/truyen/${encodeURIComponent(novel.id)}/chapters?page=${currentPage}&limit=${limit}`), ]) firstChapterNumber = firstChapterData.chapters[0]?.number if (novel.seriesId) { seriesVolumes = novel.series?.novels || [] } else if (chaptersData) { totalChapters = chaptersData.totalChapters totalPages = Math.max(1, chaptersData.totalPages || 1) formattedChapters = chaptersData.chapters.map((chapter) => ({ id: chapter.id, novelId: novel.id, number: chapter.number, volumeNumber: chapter.volumeNumber ?? null, volumeTitle: chapter.volumeTitle ?? null, volumeChapterNumber: chapter.volumeChapterNumber ?? null, title: chapter.title, createdAt: chapter.createdAt ? chapter.createdAt.split("T")[0] : "", views: chapter.views || 0, content: "", })) } const comments = commentsData.comments.map((comment) => ({ id: comment.id, userId: comment.userId, username: comment.username || "User", avatarColor: "bg-primary", novelId: novel.id, content: comment.content, createdAt: comment.createdAt ? comment.createdAt.split("T")[0] : "", })) const chapterComments = chapterCommentsData.comments.map((comment) => ({ id: comment.id, userId: comment.userId, username: comment.username || "User", avatarColor: "bg-primary", novelId: novel.id, content: comment.content, createdAt: comment.createdAt ? comment.createdAt.split("T")[0] : "", })) const novelGenres = novel.genres || [] return (
{/* Novel Header */}
{/* Cover */} {novel.title} {/* Info */}

{novel.title}

Tác giả: {novel.authorName} {novel.originalAuthorName && ({novel.originalAuthorName})}
{novel.originalTitle &&
Tên gốc: {novel.originalTitle}
}
Trạng thái: {novel.status}
{novelGenres.map((g, i) => ( {g.name} ))}
{/* Stats Row */}
{novel.totalChapters} Chương
{novel.views} Lượt đọc
{novel.bookmarkCount} Cất giữ
{novel.ratingCount} Đề cử
{/* Description */}

Giới Thiệu

{novel.description || ""}
{/* Chapter list or series volumes */} {novel.seriesId ? (

Danh Sách Quyển

{seriesVolumes.map((volume, idx) => ( {idx + 1} {volume.title}

{volume.title}

{volume.totalChapters} chương

{volume.status} ))}
) : (

Danh Sách Chương

)} {/* Comments */}
) }