43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { notFound } from "next/navigation";
|
||
|
||
import { BackendDownNotice } from "@/components/BackendDownNotice";
|
||
import { ForeshadowBoard } from "@/components/foreshadow/ForeshadowBoard";
|
||
import { fetchForeshadow, fetchProject } from "@/lib/api/server";
|
||
import type { ForeshadowView, ProjectResponse } from "@/lib/api/types";
|
||
|
||
interface PageProps {
|
||
params: Promise<{ id: string }>;
|
||
}
|
||
|
||
// 伏笔看板页(UX §6.8)。Server Component 取项目 + 全量伏笔(GET .../foreshadow);
|
||
// ForeshadowBoard(Client)按 status 分四泳道并承载登记/状态变更交互。
|
||
export default async function ForeshadowPage({ params }: PageProps) {
|
||
const { id } = await params;
|
||
|
||
// 仅当项目确实不存在(404)才判 notFound;后端不可用等其它失败降级为「后端不可达」提示,
|
||
// 不把整页变成「找不到页面」。
|
||
let project: ProjectResponse;
|
||
try {
|
||
project = await fetchProject(id);
|
||
} catch (err) {
|
||
if (isNotFoundError(err)) notFound();
|
||
return <BackendDownNotice className="m-6" />;
|
||
}
|
||
|
||
// 伏笔看板(GET .../foreshadow)。瞬时错误降级为空看板,不阻塞进页。
|
||
let initialItems: ForeshadowView[] = [];
|
||
try {
|
||
const board = await fetchForeshadow(id);
|
||
initialItems = board.foreshadow ?? [];
|
||
} catch {
|
||
initialItems = [];
|
||
}
|
||
|
||
return <ForeshadowBoard project={project} initialItems={initialItems} />;
|
||
}
|
||
|
||
// fetchProject 抛错信息形如「请求失败 404: ...」;据此区分「项目不存在」与「后端不可用」。
|
||
function isNotFoundError(err: unknown): boolean {
|
||
return err instanceof Error && err.message.includes("请求失败 404");
|
||
}
|