68 lines
2.8 KiB
TypeScript
68 lines
2.8 KiB
TypeScript
import { PostList } from "@/app/components/PostList";
|
|
import { HeroBanner } from "@/app/components/HeroBanner";
|
|
import { headers } from "next/headers";
|
|
|
|
// Next 15: params/searchParams가 Promise가 될 수 있어 안전 언랩 처리합니다.
|
|
export default async function BoardDetail({ params, searchParams }: { params: any; searchParams: any }) {
|
|
const p = params?.then ? await params : params;
|
|
const sp = searchParams?.then ? await searchParams : searchParams;
|
|
const id = p.id as string;
|
|
const sort = (sp?.sort as "recent" | "popular" | undefined) ?? "recent";
|
|
// 보드 slug 조회 (새 글 페이지 프리셋 전달)
|
|
const h = await headers();
|
|
const host = h.get("host") ?? "localhost:3000";
|
|
const proto = h.get("x-forwarded-proto") ?? "http";
|
|
const base = process.env.NEXT_PUBLIC_BASE_URL || `${proto}://${host}`;
|
|
const res = await fetch(new URL("/api/boards", base).toString(), { cache: "no-store" });
|
|
const { boards } = await res.json();
|
|
const board = (boards || []).find((b: any) => b.id === id);
|
|
const siblingBoards = (boards || []).filter((b: any) => b.category?.id && b.category.id === board?.category?.id);
|
|
const categoryName = board?.category?.name ?? "";
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* 상단 배너 (홈과 동일) */}
|
|
<section>
|
|
<HeroBanner />
|
|
</section>
|
|
|
|
{/* 보드 탭 + 리스트 카드 */}
|
|
<section className="rounded-xl overflow-hidden bg-white">
|
|
{/* 상단 탭 영역 */}
|
|
<div className="px-4 py-2 border-b border-neutral-200">
|
|
<div className="flex items-center justify-between gap-3">
|
|
<div className="flex items-center gap-2 overflow-x-auto flex-1">
|
|
<span className="shrink-0 text-sm text-neutral-500">{categoryName}</span>
|
|
{siblingBoards.map((b: any) => (
|
|
<a
|
|
key={b.id}
|
|
href={`/boards/${b.id}`}
|
|
className={`shrink-0 whitespace-nowrap text-xs px-3 py-1 rounded-full border transition-colors ${
|
|
b.id === id
|
|
? "bg-neutral-900 text-white border-neutral-900"
|
|
: "bg-white text-neutral-700 border-neutral-300 hover:bg-neutral-100"
|
|
}`}
|
|
>
|
|
{b.name}
|
|
</a>
|
|
))}
|
|
</div>
|
|
<a
|
|
href={`/posts/new?boardId=${id}${board?.slug ? `&boardSlug=${board.slug}` : ""}`}
|
|
className="shrink-0"
|
|
>
|
|
<button className="h-9 px-4 rounded-md bg-neutral-900 text-white text-sm hover:bg-neutral-800">새 글</button>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 리스트 */}
|
|
<div className="p-0">
|
|
<PostList boardId={id} sort={sort} />
|
|
</div>
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
|