Files
soul/app/chapters/page.tsx
v0 6afb9a143a refactor: redesign homepage and navigation based on trends
Update homepage layout and navigation to match current trends.

#VERCEL_SKIP

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2026-01-14 07:32:08 +00:00

197 lines
9.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { ChevronRight, Lock, Unlock, Book, BookOpen, Home, List, Sparkles, User } from "lucide-react"
import { useStore } from "@/lib/store"
import { bookData, getTotalSectionCount, specialSections } from "@/lib/book-data"
export default function ChaptersPage() {
const router = useRouter()
const { user, hasPurchased } = useStore()
const [expandedPart, setExpandedPart] = useState<string | null>("part-1")
const totalSections = getTotalSectionCount()
const hasFullBook = user?.hasFullBook || false
const handleSectionClick = (sectionId: string) => {
router.push(`/read/${sectionId}`)
}
return (
<div className="min-h-screen bg-black text-white pb-24">
<header className="sticky top-0 z-40 bg-black/90 backdrop-blur-xl border-b border-white/5">
<div className="px-4 py-3 flex items-center justify-center">
<h1 className="text-lg font-semibold text-[#00CED1]"></h1>
</div>
</header>
<div className="mx-4 mt-4 p-4 rounded-2xl bg-gradient-to-br from-[#1c1c1e] to-[#2c2c2e] border border-[#00CED1]/20">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-gradient-to-br from-[#00CED1] to-[#20B2AA] flex items-center justify-center">
<Book className="w-6 h-6 text-white" />
</div>
<div className="flex-1">
<h2 className="text-white font-semibold">SOUL的创业实验场</h2>
<p className="text-gray-500 text-xs mt-0.5">Soul派对房的真实商业故事</p>
</div>
<div className="text-right">
<div className="text-xl font-bold text-[#00CED1]">{totalSections}</div>
<div className="text-[10px] text-gray-500"></div>
</div>
</div>
</div>
{/* 目录内容 */}
<main className="px-4 py-4">
<button
onClick={() => handleSectionClick("preface")}
className="w-full mb-3 p-3 rounded-xl bg-[#1c1c1e] flex items-center justify-between active:bg-[#2c2c2e] transition-colors border border-white/5"
>
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-lg bg-[#00CED1]/20 flex items-center justify-center">
<BookOpen className="w-4 h-4 text-[#00CED1]" />
</div>
<span className="text-sm font-medium text-white">6Soul开播?</span>
</div>
<div className="flex items-center gap-2">
<span className="text-xs text-[#00CED1]"></span>
<ChevronRight className="w-4 h-4 text-gray-500" />
</div>
</button>
{bookData.map((part) => (
<div key={part.id} className="mb-3">
<button
onClick={() => setExpandedPart(expandedPart === part.id ? null : part.id)}
className="w-full p-3 rounded-xl bg-[#1c1c1e] flex items-center justify-between active:bg-[#2c2c2e] transition-colors border border-white/5"
>
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-[#00CED1] to-[#20B2AA] flex items-center justify-center text-sm font-bold text-white">
{part.number}
</div>
<div className="text-left">
<div className="text-sm font-semibold text-white">{part.title}</div>
<div className="text-[10px] text-gray-500">{part.subtitle}</div>
</div>
</div>
<div className="flex items-center gap-2">
<span className="text-xs text-gray-500">
{part.chapters.reduce((acc, ch) => acc + ch.sections.length, 0)}
</span>
<ChevronRight
className={`w-4 h-4 text-gray-500 transition-transform ${expandedPart === part.id ? "rotate-90" : ""}`}
/>
</div>
</button>
{expandedPart === part.id && (
<div className="mt-2 ml-2 space-y-1">
{part.chapters.map((chapter) => (
<div key={chapter.id} className="rounded-lg bg-[#1c1c1e]/50 overflow-hidden border border-white/5">
<div className="px-3 py-2 text-xs font-medium text-gray-400 border-b border-white/5">
{chapter.title}
</div>
{chapter.sections.map((section) => {
const isPurchased = hasFullBook || hasPurchased(section.id)
const canRead = section.isFree || isPurchased
return (
<button
key={section.id}
onClick={() => handleSectionClick(section.id)}
className="w-full px-3 py-2.5 flex items-center justify-between border-b border-white/5 last:border-0 active:bg-white/5 transition-colors"
>
<div className="flex items-center gap-2 flex-1 min-w-0">
{canRead ? (
<Unlock className="w-3.5 h-3.5 text-[#00CED1] flex-shrink-0" />
) : (
<Lock className="w-3.5 h-3.5 text-gray-500 flex-shrink-0" />
)}
<span className={`text-xs truncate ${canRead ? "text-white" : "text-gray-400"}`}>
{section.id} {section.title}
</span>
</div>
<div className="flex items-center gap-2 flex-shrink-0 ml-2">
{section.isFree ? (
<span className="text-[10px] text-[#00CED1] px-1.5 py-0.5 rounded bg-[#00CED1]/10">
</span>
) : isPurchased ? (
<span className="text-[10px] text-[#00CED1]"></span>
) : (
<span className="text-[10px] text-gray-500">¥{section.price}</span>
)}
<ChevronRight className="w-3.5 h-3.5 text-gray-600" />
</div>
</button>
)
})}
</div>
))}
</div>
)}
</div>
))}
<button
onClick={() => handleSectionClick("epilogue")}
className="w-full mb-3 p-3 rounded-xl bg-[#1c1c1e] flex items-center justify-between active:bg-[#2c2c2e] transition-colors border border-white/5"
>
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-lg bg-[#00CED1]/20 flex items-center justify-center">
<BookOpen className="w-4 h-4 text-[#00CED1]" />
</div>
<span className="text-sm font-medium text-white"></span>
</div>
<div className="flex items-center gap-2">
<span className="text-xs text-[#00CED1]"></span>
<ChevronRight className="w-4 h-4 text-gray-500" />
</div>
</button>
{/* 附录 */}
<div className="mb-3 p-3 rounded-xl bg-[#1c1c1e] border border-white/5">
<div className="text-xs font-medium text-gray-400 mb-2"></div>
{specialSections.appendix.map((item) => (
<button
key={item.id}
onClick={() => handleSectionClick(item.id)}
className="w-full py-2 flex items-center justify-between border-b border-white/5 last:border-0 active:bg-white/5"
>
<span className="text-xs text-gray-300">{item.title}</span>
<ChevronRight className="w-3.5 h-3.5 text-gray-600" />
</button>
))}
</div>
</main>
<nav className="fixed bottom-0 left-0 right-0 bg-[#1c1c1e]/95 backdrop-blur-xl border-t border-white/5 pb-safe-bottom">
<div className="px-4 py-2">
<div className="flex items-center justify-around">
<button onClick={() => router.push("/")} className="flex flex-col items-center py-2 px-4">
<Home className="w-5 h-5 text-gray-500 mb-1" />
<span className="text-gray-500 text-xs"></span>
</button>
<button className="flex flex-col items-center py-2 px-4">
<List className="w-5 h-5 text-[#00CED1] mb-1" />
<span className="text-[#00CED1] text-xs font-medium"></span>
</button>
{/* 匹配按钮 - 更大更突出 */}
<button onClick={() => router.push("/match")} className="flex flex-col items-center py-2 px-6 -mt-4">
<div className="w-14 h-14 rounded-full bg-gradient-to-br from-[#00CED1] to-[#20B2AA] flex items-center justify-center shadow-lg shadow-[#00CED1]/30">
<Sparkles className="w-6 h-6 text-white" />
</div>
<span className="text-gray-500 text-xs mt-1"></span>
</button>
<button onClick={() => router.push("/my")} className="flex flex-col items-center py-2 px-4">
<User className="w-5 h-5 text-gray-500 mb-1" />
<span className="text-gray-500 text-xs"></span>
</button>
</div>
</div>
</nav>
</div>
)
}