66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
import Link from "next/link";
|
||
import { BookOpen, Plus } from "lucide-react";
|
||
|
||
import { AppShell } from "@/components/AppShell";
|
||
import { ProjectLibrary } from "@/components/projects/ProjectLibrary";
|
||
import { EmptyState } from "@/components/ui/EmptyState";
|
||
import { PageHeader } from "@/components/ui/PageHeader";
|
||
import { fetchProjects } from "@/lib/api/server";
|
||
import type { ProjectResponse } from "@/lib/api/types";
|
||
import { buttonClass } from "@/lib/ui/variants";
|
||
|
||
// 作品库(Dashboard 入口,UX §6.1)。Server Component 读取。
|
||
export default async function DashboardPage() {
|
||
let projects: ProjectResponse[] = [];
|
||
let loadError = false;
|
||
try {
|
||
const data = await fetchProjects();
|
||
projects = data.projects ?? [];
|
||
} catch {
|
||
loadError = true;
|
||
}
|
||
|
||
return (
|
||
<AppShell>
|
||
<div className="mx-auto max-w-5xl px-6 py-10 sm:px-8">
|
||
<PageHeader
|
||
title="我的作品"
|
||
description="从一个灵感进入正文、设定、审稿与验收闭环。"
|
||
actions={
|
||
<Link
|
||
href="/projects/new"
|
||
className={buttonClass({ variant: "primary" })}
|
||
>
|
||
<Plus className="h-4 w-4" aria-hidden="true" />
|
||
新建作品
|
||
</Link>
|
||
}
|
||
/>
|
||
|
||
{loadError ? (
|
||
<p className="rounded border border-conflict bg-panel p-6 text-conflict">
|
||
无法连接后端服务,请确认 API 已启动后刷新。
|
||
</p>
|
||
) : projects.length === 0 ? (
|
||
<EmptyState
|
||
icon={BookOpen}
|
||
title="还没有作品"
|
||
description="从一句灵感开始,后续的设定库、大纲、写章和审稿都会围绕这本书展开。"
|
||
action={
|
||
<Link
|
||
href="/projects/new"
|
||
className={buttonClass({ variant: "primary" })}
|
||
>
|
||
<Plus className="h-4 w-4" aria-hidden="true" />
|
||
新建作品
|
||
</Link>
|
||
}
|
||
/>
|
||
) : (
|
||
<ProjectLibrary projects={projects} />
|
||
)}
|
||
</div>
|
||
</AppShell>
|
||
);
|
||
}
|