Add EPUB upload + DB integration
Add server-side EPUB import and integrate Prisma + Mongo for novels/chapters. Introduces a new moderator API route (app/api/mod/epub/route.ts) that parses .epub files, creates a novel record in Prisma, and inserts chapter documents into MongoDB via the Chapter Mongoose model. Frontend: novel management UI now supports EPUB upload (app/mod/truyen/novel-client.tsx) with progress/toasts and preserves the manual 'Add novel' dialog. Convert app pages to fetch real data from Prisma and Mongo (app/page.tsx, app/truyen/[slug]/page.tsx, app/truyen/[slug]/[chapterId]/page.tsx), adapt types/props to use authorName, and adjust chapter/comment IDs to use Mongo _id strings. Minor fixes: TTS player logs playback errors, UI text fixes (e.g. "Chương"), and novel-card/other components updated for authorName. package.json updated with epub2, html-to-text and types; pnpm lock updated. Adds tsconfig.tsbuildinfo.
This commit is contained in:
@@ -1,10 +1,21 @@
|
||||
import Link from "next/link"
|
||||
import { BookOpen, Eye, Star } from "lucide-react"
|
||||
import type { Novel } from "@/lib/types"
|
||||
import { formatViews } from "@/lib/data"
|
||||
|
||||
export interface CardNovel {
|
||||
id: string
|
||||
slug: string
|
||||
title: string
|
||||
authorName: string
|
||||
coverColor: string | null
|
||||
rating: number
|
||||
views: number
|
||||
totalChapters: number
|
||||
status: string
|
||||
}
|
||||
|
||||
interface NovelCardProps {
|
||||
novel: Novel
|
||||
novel: CardNovel
|
||||
variant?: "default" | "compact"
|
||||
}
|
||||
|
||||
@@ -22,7 +33,7 @@ export function NovelCard({ novel, variant = "default" }: NovelCardProps) {
|
||||
<h3 className="truncate text-sm font-semibold text-foreground group-hover:text-primary transition-colors">
|
||||
{novel.title}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground">{novel.author}</p>
|
||||
<p className="text-xs text-muted-foreground">{novel.authorName}</p>
|
||||
<div className="mt-1 flex items-center gap-3 text-xs text-muted-foreground">
|
||||
<span className="flex items-center gap-0.5">
|
||||
<Star className="h-3 w-3 fill-primary text-primary" />
|
||||
@@ -52,7 +63,7 @@ export function NovelCard({ novel, variant = "default" }: NovelCardProps) {
|
||||
<h3 className="line-clamp-1 text-sm font-semibold text-foreground group-hover:text-primary transition-colors text-balance">
|
||||
{novel.title}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground">{novel.author}</p>
|
||||
<p className="text-xs text-muted-foreground">{novel.authorName}</p>
|
||||
<div className="mt-auto flex items-center gap-3 pt-2 text-xs text-muted-foreground">
|
||||
<span className="flex items-center gap-0.5">
|
||||
<Star className="h-3 w-3 fill-primary text-primary" />
|
||||
|
||||
@@ -166,6 +166,7 @@ export function TTSPlayer({ paragraphs, novelSlug, currentChapter, maxChapter, c
|
||||
}
|
||||
|
||||
utterance.onerror = (e) => {
|
||||
console.error("TTS Playback Error:", e.error, e)
|
||||
if (e.error !== "canceled" && e.error !== "interrupted") {
|
||||
setIsPlaying(false)
|
||||
releaseWakeLock()
|
||||
|
||||
Reference in New Issue
Block a user