diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index d511eb0..7f71d45 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -124,7 +124,6 @@ model Board {
description String?
sortOrder Int @default(0)
status BoardStatus @default(active)
- requiresApproval Boolean @default(false) // 게시물 승인 필요 여부
allowAnonymousPost Boolean @default(false) // 익명 글 허용
allowSecretComment Boolean @default(false) // 비밀댓글 허용
isAdultOnly Boolean @default(false) // 성인 인증 필요 여부
diff --git a/prisma/seed.js b/prisma/seed.js
index 9e3f464..a2dd809 100644
--- a/prisma/seed.js
+++ b/prisma/seed.js
@@ -200,6 +200,10 @@ async function upsertBoards(admin, categoryMap) {
];
const created = [];
+ // 특수 랭킹 뷰 타입 ID 조회 (사전에 upsertViewTypes로 생성됨)
+ const mainSpecial = await prisma.boardViewType.findUnique({ where: { key: "main_special_rank" } });
+ const listSpecial = await prisma.boardViewType.findUnique({ where: { key: "list_special_rank" } });
+
for (const b of boards) {
// 카테고리 매핑 규칙 (트리 기준 상위 카테고리)
const mapBySlug = {
@@ -227,20 +231,22 @@ async function upsertBoards(admin, categoryMap) {
update: {
description: b.description,
sortOrder: b.sortOrder,
- requiresApproval: !!b.requiresApproval,
allowAnonymousPost: !!b.allowAnonymousPost,
readLevel: b.readLevel || undefined,
categoryId: category ? category.id : undefined,
+ ...(b.slug === "ranking" && mainSpecial ? { mainPageViewTypeId: mainSpecial.id } : {}),
+ ...(b.slug === "ranking" && listSpecial ? { listViewTypeId: listSpecial.id } : {}),
},
create: {
name: b.name,
slug: b.slug,
description: b.description,
sortOrder: b.sortOrder,
- requiresApproval: !!b.requiresApproval,
allowAnonymousPost: !!b.allowAnonymousPost,
readLevel: b.readLevel || undefined,
categoryId: category ? category.id : undefined,
+ ...(b.slug === "ranking" && mainSpecial ? { mainPageViewTypeId: mainSpecial.id } : {}),
+ ...(b.slug === "ranking" && listSpecial ? { listViewTypeId: listSpecial.id } : {}),
},
});
created.push(board);
diff --git a/public/uploads/1762025382776-83vifeqk7rk.webp b/public/uploads/1762025382776-83vifeqk7rk.webp
new file mode 100644
index 0000000..8373104
Binary files /dev/null and b/public/uploads/1762025382776-83vifeqk7rk.webp differ
diff --git a/src/app/admin/boards/page.tsx b/src/app/admin/boards/page.tsx
index e0f2a8f..f404a38 100644
--- a/src/app/admin/boards/page.tsx
+++ b/src/app/admin/boards/page.tsx
@@ -368,7 +368,6 @@ export default function AdminBoardsPage() {
쓰기 |
익명 |
비밀댓 |
- 승인 |
성인 |
대분류 이동 |
활성 |
@@ -501,7 +500,6 @@ function BoardRowCells({ b, onDirty, onDelete, allowMove, categories, onMove, ma
{ const v = { ...edit, allowAnonymousPost: e.target.checked }; setEdit(v); onDirty(b.id, v); }} /> |
{ const v = { ...edit, allowSecretComment: e.target.checked }; setEdit(v); onDirty(b.id, v); }} /> |
- { const v = { ...edit, requiresApproval: e.target.checked }; setEdit(v); onDirty(b.id, v); }} /> |
{ const v = { ...edit, isAdultOnly: e.target.checked }; setEdit(v); onDirty(b.id, v); }} /> |
{allowMove && categories && onMove ? (
diff --git a/src/app/api/admin/boards/[id]/route.ts b/src/app/api/admin/boards/[id]/route.ts
index 309dd72..deb1dcf 100644
--- a/src/app/api/admin/boards/[id]/route.ts
+++ b/src/app/api/admin/boards/[id]/route.ts
@@ -5,7 +5,7 @@ export async function PATCH(req: Request, context: { params: Promise<{ id: strin
const { id } = await context.params;
const body = await req.json().catch(() => ({}));
const data: any = {};
- for (const k of ["name", "slug", "description", "sortOrder", "readLevel", "writeLevel", "allowAnonymousPost", "allowSecretComment", "requiresApproval", "status", "isAdultOnly", "categoryId", "mainPageViewTypeId", "listViewTypeId"]) {
+ for (const k of ["name", "slug", "description", "sortOrder", "readLevel", "writeLevel", "allowAnonymousPost", "allowSecretComment", "status", "isAdultOnly", "categoryId", "mainPageViewTypeId", "listViewTypeId"]) {
if (k in body) data[k] = body[k];
}
if ("requiredTags" in body) {
diff --git a/src/app/api/admin/boards/route.ts b/src/app/api/admin/boards/route.ts
index d5c24bb..0cf87fa 100644
--- a/src/app/api/admin/boards/route.ts
+++ b/src/app/api/admin/boards/route.ts
@@ -16,7 +16,6 @@ export async function GET() {
writeLevel: true,
allowAnonymousPost: true,
allowSecretComment: true,
- requiresApproval: true,
status: true,
categoryId: true,
mainPageViewTypeId: true,
@@ -36,7 +35,6 @@ const createSchema = z.object({
writeLevel: z.string().optional(),
allowAnonymousPost: z.boolean().optional(),
allowSecretComment: z.boolean().optional(),
- requiresApproval: z.boolean().optional(),
status: z.string().optional(),
isAdultOnly: z.boolean().optional(),
categoryId: z.string().nullable().optional(),
diff --git a/src/app/api/boards/route.ts b/src/app/api/boards/route.ts
index d3e871c..64bfb48 100644
--- a/src/app/api/boards/route.ts
+++ b/src/app/api/boards/route.ts
@@ -20,7 +20,6 @@ export async function GET(req: Request) {
name: true,
slug: true,
description: true,
- requiresApproval: true,
allowAnonymousPost: true,
isAdultOnly: true,
category: { select: { id: true, name: true, slug: true } },
diff --git a/src/app/api/categories/route.ts b/src/app/api/categories/route.ts
index ae379f0..36e4721 100644
--- a/src/app/api/categories/route.ts
+++ b/src/app/api/categories/route.ts
@@ -10,7 +10,7 @@ export async function GET() {
boards: {
where: { status: "active" },
orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }],
- select: { id: true, name: true, slug: true, requiresApproval: true },
+ select: { id: true, name: true, slug: true },
},
},
});
diff --git a/src/app/api/posts/route.ts b/src/app/api/posts/route.ts
index 97230ef..139d97a 100644
--- a/src/app/api/posts/route.ts
+++ b/src/app/api/posts/route.ts
@@ -18,7 +18,6 @@ export async function POST(req: Request) {
}
const { boardId, authorId, title, content, isAnonymous } = parsed.data;
const board = await prisma.board.findUnique({ where: { id: boardId } });
- const requiresApproval = board?.requiresApproval ?? false;
// 사진형 보드 필수 이미지 검증: content 내 이미지 링크 최소 1개
const isImageOnly = (board?.requiredFields as any)?.imageOnly;
const minImages = (board?.requiredFields as any)?.minImages ?? 0;
@@ -35,7 +34,7 @@ export async function POST(req: Request) {
title,
content,
isAnonymous: !!isAnonymous,
- status: requiresApproval ? "hidden" : "published",
+ status: "published",
},
});
return NextResponse.json({ post }, { status: 201 });
diff --git a/src/app/boards/[id]/page.tsx b/src/app/boards/[id]/page.tsx
index 8f43d0a..b02a84b 100644
--- a/src/app/boards/[id]/page.tsx
+++ b/src/app/boards/[id]/page.tsx
@@ -7,7 +7,7 @@ import { headers } from "next/headers";
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 idOrSlug = p.id as string;
const sort = (sp?.sort as "recent" | "popular" | undefined) ?? "recent";
// 보드 slug 조회 (새 글 페이지 프리셋 전달)
const h = await headers();
@@ -16,7 +16,8 @@ export default async function BoardDetail({ params, searchParams }: { params: an
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 board = (boards || []).find((b: any) => b.slug === idOrSlug || b.id === idOrSlug);
+ const id = board?.id as string;
const siblingBoards = (boards || []).filter((b: any) => b.category?.id && b.category.id === board?.category?.id);
const categoryName = board?.category?.name ?? "";
return (
@@ -24,14 +25,14 @@ export default async function BoardDetail({ params, searchParams }: { params: an
{/* 상단 배너 (서브카테고리 표시) */}
({ id: b.id, name: b.name, href: `/boards/${b.id}` }))}
+ subItems={siblingBoards.map((b: any) => ({ id: b.id, name: b.name, href: `/boards/${b.slug}` }))}
activeSubId={id}
/>
{/* 검색/필터 툴바 + 리스트 */}
-
+
게시판
{boards?.map((b: any) => (
- - {b.name}
+ - {b.name}
))}
diff --git a/src/app/components/AppHeader.tsx b/src/app/components/AppHeader.tsx
index 65944f4..845af95 100644
--- a/src/app/components/AppHeader.tsx
+++ b/src/app/components/AppHeader.tsx
@@ -35,7 +35,7 @@ export function AppHeader() {
}, [pathname]);
const activeCategorySlug = React.useMemo(() => {
if (activeBoardId) {
- const found = categories.find((c) => c.boards.some((b) => b.id === activeBoardId));
+ const found = categories.find((c) => c.boards.some((b) => b.slug === activeBoardId));
return found?.slug ?? null;
}
if (pathname === "/boards") {
@@ -337,7 +337,7 @@ export function AppHeader() {
style={idx === categories.length - 1 ? { minWidth: 120 } : undefined}
>
(
{b.name}
@@ -416,7 +416,7 @@ export function AppHeader() {
{cat.name}
{cat.boards.map((b) => (
- setMobileOpen(false)} className="rounded px-2 py-1 text-neutral-700 hover:bg-neutral-100 hover:text-neutral-900">
+ setMobileOpen(false)} className="rounded px-2 py-1 text-neutral-700 hover:bg-neutral-100 hover:text-neutral-900">
{b.name}
))}
diff --git a/src/app/components/CategoryBoardBrowser.tsx b/src/app/components/CategoryBoardBrowser.tsx
index a3d959f..28c85b2 100644
--- a/src/app/components/CategoryBoardBrowser.tsx
+++ b/src/app/components/CategoryBoardBrowser.tsx
@@ -7,7 +7,7 @@ type ApiCategory = {
id: string;
name: string;
slug: string;
- boards: { id: string; name: string; slug: string; requiresApproval: boolean }[];
+ boards: { id: string; name: string; slug: string }[];
};
type PostItem = {
@@ -101,7 +101,7 @@ export default function CategoryBoardBrowser({ categoryName, categorySlug }: Pro
className="shrink-0 text-lg md:text-xl font-bold text-neutral-800 truncate"
onClick={() => {
const first = selectedCategory?.boards?.[0];
- if (first?.id) router.push(`/boards/${first.id}`);
+ if (first?.slug) router.push(`/boards/${first.slug}`);
}}
title={(selectedCategory?.name ?? categoryName ?? "").toString()}
>
@@ -113,7 +113,7 @@ export default function CategoryBoardBrowser({ categoryName, categorySlug }: Pro
className="shrink-0 w-6 h-6 rounded-full border border-neutral-300 text-neutral-500 hover:bg-neutral-50 flex items-center justify-center"
onClick={() => {
const first = selectedCategory?.boards?.[0];
- if (first?.id) router.push(`/boards/${first.id}`);
+ if (first?.slug) router.push(`/boards/${first.slug}`);
}}
>
|