diff --git a/src/app/boards/[id]/page.tsx b/src/app/boards/[id]/page.tsx
new file mode 100644
index 0000000..1c7aa9f
--- /dev/null
+++ b/src/app/boards/[id]/page.tsx
@@ -0,0 +1,16 @@
+import { PostList } from "@/app/components/PostList";
+
+export default async function BoardDetail({ params, searchParams }: { params: { id: string }; searchParams?: { sort?: "recent" | "popular" } }) {
+ const sort = searchParams?.sort ?? "recent";
+ return (
+
+ );
+}
+
+
diff --git a/src/app/boards/page.tsx b/src/app/boards/page.tsx
new file mode 100644
index 0000000..a5ea9a4
--- /dev/null
+++ b/src/app/boards/page.tsx
@@ -0,0 +1,16 @@
+export default async function BoardsPage() {
+ const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL ?? ""}/api/boards`, { cache: "no-store" });
+ const { boards } = await res.json();
+ return (
+
+
게시판
+
+ {boards?.map((b: any) => (
+ - {b.name}
+ ))}
+
+
+ );
+}
+
+
diff --git a/src/app/components/PostForm.tsx b/src/app/components/PostForm.tsx
new file mode 100644
index 0000000..9e22da7
--- /dev/null
+++ b/src/app/components/PostForm.tsx
@@ -0,0 +1,44 @@
+"use client";
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+import { useToast } from "@/app/components/ui/ToastProvider";
+import { UploadButton } from "@/app/components/UploadButton";
+
+type Values = { title: string; content: string };
+
+export function PostForm({
+ initial,
+ onSubmit,
+ submitText = "등록",
+}: {
+ initial?: Partial;
+ onSubmit: (values: Values) => Promise<{ id: string } | void>;
+ submitText?: string;
+}) {
+ const router = useRouter();
+ const { show } = useToast();
+ const [form, setForm] = useState({ title: initial?.title ?? "", content: initial?.content ?? "" });
+ const [loading, setLoading] = useState(false);
+ async function handleSubmit() {
+ try {
+ setLoading(true);
+ const res = await onSubmit(form);
+ show("저장되었습니다");
+ if (res && res.id) router.push(`/posts/${res.id}`);
+ } catch (e) {
+ show("저장 실패");
+ } finally {
+ setLoading(false);
+ }
+ }
+ return (
+
+ setForm({ ...form, title: e.target.value })} />
+
+ );
+}
+
+
diff --git a/src/app/posts/new/page.tsx b/src/app/posts/new/page.tsx
index db975e6..2e2ce87 100644
--- a/src/app/posts/new/page.tsx
+++ b/src/app/posts/new/page.tsx
@@ -4,10 +4,10 @@ import { useRouter } from "next/navigation";
import { useToast } from "@/app/components/ui/ToastProvider";
import { UploadButton } from "@/app/components/UploadButton";
-export default function NewPostPage() {
+export default function NewPostPage({ searchParams }: { searchParams?: { boardId?: string } }) {
const router = useRouter();
const { show } = useToast();
- const [form, setForm] = useState({ boardId: "", title: "", content: "" });
+ const [form, setForm] = useState({ boardId: searchParams?.boardId ?? "", title: "", content: "" });
const [loading, setLoading] = useState(false);
async function submit() {
try {
diff --git a/todolist.txt b/todolist.txt
index 881ec0e..eeffd9b 100644
--- a/todolist.txt
+++ b/todolist.txt
@@ -47,7 +47,7 @@
7.5 추천/신고, 조회수 카운트 o
7.6 익명/비밀댓글/비댓 해시 처리 o
7.7 신고→알림→블라인드 자동화 훅 o
-7.8 일반 게시판 공용 폼/라우트 템플릿 생성
+7.8 일반 게시판 공용 폼/라우트 템플릿 생성 o
7.9 일반 카테고리 설정 매핑(공지/가입인사/버그건의/이벤트/소통방/자유/무엇이든/마사지꿀팁/관리사찾아요/청와대/방문후기[승인])
7.10 제휴업소 일반(사진) 카테고리 전용 이미지 첨부/미리보기 규칙