diff --git a/apps/cs/app/(with-base-layout)/bbs/register/[id]/page.tsx b/apps/cs/app/(with-base-layout)/bbs/register/[id]/page.tsx
new file mode 100644
index 000000000..07cc78b6f
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/register/[id]/page.tsx
@@ -0,0 +1,10 @@
+import { ModifyPage as VModifyPage } from "@/pages/bbs";
+
+export default async function ModifyPage({
+ params,
+}: {
+ params: Promise<{ id: string }>;
+}) {
+ const { id } = await params;
+ return ;
+}
diff --git a/apps/cs/app/(with-base-layout)/bbs/register/page.tsx b/apps/cs/app/(with-base-layout)/bbs/register/page.tsx
new file mode 100644
index 000000000..3e74aef97
--- /dev/null
+++ b/apps/cs/app/(with-base-layout)/bbs/register/page.tsx
@@ -0,0 +1,2 @@
+import { CreatePage } from "@/pages/bbs";
+export default CreatePage;
diff --git a/apps/cs/src/entities/board/api/board-service.ts b/apps/cs/src/entities/board/api/board-service.ts
index 2ba0f55fd..150ff677a 100644
--- a/apps/cs/src/entities/board/api/board-service.ts
+++ b/apps/cs/src/entities/board/api/board-service.ts
@@ -1,6 +1,8 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type {
+ Board,
+ BoardFormData,
BoardList,
BoardParams,
BoardPopupList,
@@ -26,6 +28,33 @@ export class BoardApiService implements BoardService {
);
return response.data;
}
+
+ public async getBoardInfo(bbsId: string): Promise {
+ const response = await client.get(
+ `${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`,
+ );
+ return response.data;
+ }
+
+ public async createBoard(data: BoardFormData): Promise {
+ const response = await client.post(
+ `${ENDPOINT.BOARD_SERVICE.BBS}`,
+ data,
+ );
+ return response.data;
+ }
+
+ public async updateBoard(bbsId: string, data: BoardFormData): Promise {
+ const response = await client.put(
+ `${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`,
+ data,
+ );
+ return response.data;
+ }
+
+ public async deleteBoard(bbsId: string): Promise {
+ await client.delete(`${ENDPOINT.BOARD_SERVICE.BBS}/${bbsId}`);
+ }
}
export const BoardApi = new BoardApiService();
diff --git a/apps/cs/src/entities/board/index.ts b/apps/cs/src/entities/board/index.ts
index 73229695f..f9ef1b610 100644
--- a/apps/cs/src/entities/board/index.ts
+++ b/apps/cs/src/entities/board/index.ts
@@ -1,6 +1,8 @@
export { BoardApi } from "./api/board-service";
export {
+ boardFormSchema,
type Board,
+ type BoardFormData,
type BoardParams,
type BoardPopup,
} from "./model/board-interface";
diff --git a/apps/cs/src/entities/board/model/board-interface.ts b/apps/cs/src/entities/board/model/board-interface.ts
index ccfebdaed..1ed8f1d9f 100644
--- a/apps/cs/src/entities/board/model/board-interface.ts
+++ b/apps/cs/src/entities/board/model/board-interface.ts
@@ -1,3 +1,4 @@
+import { z } from "zod";
import type { PageableList, PageableParams } from "@/shared/model";
export const BOARD_TYPE = {
@@ -62,10 +63,34 @@ export interface BoardPopup extends Board {
pstCnt: number;
}
+export const boardFormSchema = z.object({
+ bbsTypeCd: z.string(),
+ bbsNm: z.string(),
+ bbsExpln: z.string(),
+ rfrncUseYn: z.string(),
+ atflUseYn: z.string(),
+ atflMaxCnt: z.number().nullish(),
+ atflMaxFileSz: z.number().nullish(),
+ ansUseYn: z.string(),
+ ansUseAuthrt: z.string().nullish(),
+ cmntUseYn: z.string(),
+ dgstfnEvlUseYn: z.string(),
+ smsUseYn: z.string(),
+ upndFixUseYn: z.string(),
+ pstgPrdUseYn: z.string(),
+ popupUseYn: z.string(),
+ useYn: z.string(),
+});
+
export type BoardList = PageableList;
export type BoardPopupList = PageableList;
+export type BoardFormData = z.infer;
export interface BoardService {
getBoardList: (params: BoardParams) => Promise;
getBoardPopupList: (params: BoardPopupParams) => Promise;
+ getBoardInfo: (bbsId: string) => Promise;
+ createBoard: (data: BoardFormData) => Promise;
+ updateBoard: (bbsId: string, data: BoardFormData) => Promise;
+ deleteBoard: (bbsId: string) => Promise;
}
diff --git a/apps/cs/src/pages/bbs/index.ts b/apps/cs/src/pages/bbs/index.ts
index acdf5e213..bed839012 100644
--- a/apps/cs/src/pages/bbs/index.ts
+++ b/apps/cs/src/pages/bbs/index.ts
@@ -1 +1,3 @@
export { BbsPage } from "./ui/bbs-page";
+export { CreatePage } from "./ui/create-page";
+export { ModifyPage } from "./ui/modify-page";
diff --git a/apps/cs/src/pages/bbs/ui/bbs-form.tsx b/apps/cs/src/pages/bbs/ui/bbs-form.tsx
new file mode 100644
index 000000000..ac2b5ebd5
--- /dev/null
+++ b/apps/cs/src/pages/bbs/ui/bbs-form.tsx
@@ -0,0 +1,447 @@
+"use client";
+
+import type { UseFormReturn } from "react-hook-form";
+import {
+ Input,
+ Label,
+ RadioGroup,
+ RadioGroupItem,
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+} from "@common/components";
+import { FormWrapper } from "@/widgets/form-wrapper";
+import { CodeSelect } from "@/entities/code";
+import type { Board, BoardFormData } from "@/entities/board";
+import { FormControl, FormField, FormItem } from "@/shared/ui/form";
+
+type BbsFormProps = {
+ form: UseFormReturn;
+ bbsId?: string;
+ handleSave: (data: BoardFormData) => Promise;
+};
+
+function BbsForm({ form, bbsId, ...props }: BbsFormProps) {
+ return (
+
+
+
+
+
+
+
+
+
+ 게시판명
+
+ (
+
+
+
+
+
+ )}
+ />
+
+
+
+ 게시판 설명
+
+ (
+
+
+
+
+
+ )}
+ />
+
+
+
+ 게시판 유형
+
+ (
+
+
+
+
+
+ )}
+ />
+
+
+
+ 참조 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 첨부파일 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 첨부파일 최대 개수
+
+ (
+
+
+ {
+ const value = e.target.value;
+ if (isNaN(Number(value))) return;
+ field.onChange(value === "" ? null : Number(value));
+ }}
+ className="w-[12rem] !text-[1.3rem]"
+ placeholder="최대 개수 입력"
+ disabled={form.watch("atflUseYn") === "N"}
+ />
+
+
+ )}
+ />
+
+
+
+ 첨부파일 최대 크기
+
+ (
+
+
+ {
+ const value = e.target.value;
+ if (isNaN(Number(value))) return;
+ field.onChange(value === "" ? null : Number(value));
+ }}
+ className="w-[12rem] !text-[1.3rem]"
+ placeholder="최대 크기 입력"
+ disabled={form.watch("atflUseYn") === "N"}
+ />
+
+
+ )}
+ />
+
+
+
+ 답글 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 답글 사용 권한
+
+ (
+
+
+
+
+
+ )}
+ />
+
+
+
+ 댓글 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 게시물평가 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 팝업 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ SMS알림 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 상단고정 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 게시기간 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+ 사용 여부
+
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+ />
+
+
+
+
+
+
+ );
+}
+
+export { BbsForm };
diff --git a/apps/cs/src/pages/bbs/ui/bbs-page.tsx b/apps/cs/src/pages/bbs/ui/bbs-page.tsx
index 393ee957b..89562cb9c 100644
--- a/apps/cs/src/pages/bbs/ui/bbs-page.tsx
+++ b/apps/cs/src/pages/bbs/ui/bbs-page.tsx
@@ -70,7 +70,9 @@ function BbsPage() {
refetch();
};
- const handleRowClick = (row: Board) => {};
+ const handleRowClick = (row: Board) => {
+ router.push(`/bbs/register/${row.bbsId}`);
+ };
useEffect(() => {
refetch();
diff --git a/apps/cs/src/pages/bbs/ui/create-page.tsx b/apps/cs/src/pages/bbs/ui/create-page.tsx
new file mode 100644
index 000000000..bb710c33b
--- /dev/null
+++ b/apps/cs/src/pages/bbs/ui/create-page.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { useMutation } from "@tanstack/react-query";
+import { useAlertStore } from "@/shared/lib/use-alert-store";
+import {
+ BoardApi,
+ boardFormSchema,
+ type BoardFormData,
+} from "@/entities/board";
+import { BbsForm } from "./bbs-form";
+
+function CreatePage() {
+ const router = useRouter();
+ const { setMessage: alert } = useAlertStore((state) => state);
+
+ const { mutateAsync: createBoard } = useMutation({
+ mutationFn: (data: BoardFormData) => BoardApi.createBoard(data),
+ onSuccess: () => {
+ alert("등록되었습니다.", router.back);
+ },
+ });
+
+ const form = useForm({
+ resolver: zodResolver(boardFormSchema),
+ defaultValues: {
+ bbsTypeCd: "",
+ bbsNm: "",
+ bbsExpln: "",
+ rfrncUseYn: "Y",
+ atflUseYn: "Y",
+ ansUseYn: "Y",
+ cmntUseYn: "Y",
+ dgstfnEvlUseYn: "Y",
+ smsUseYn: "Y",
+ upndFixUseYn: "Y",
+ pstgPrdUseYn: "Y",
+ popupUseYn: "Y",
+ useYn: "Y",
+ },
+ });
+
+ return (
+
+ );
+}
+
+export { CreatePage };
diff --git a/apps/cs/src/pages/bbs/ui/modify-page.tsx b/apps/cs/src/pages/bbs/ui/modify-page.tsx
new file mode 100644
index 000000000..f411cbd5c
--- /dev/null
+++ b/apps/cs/src/pages/bbs/ui/modify-page.tsx
@@ -0,0 +1,45 @@
+"use client";
+
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { useMutation, useQuery } from "@tanstack/react-query";
+import { useAlertStore } from "@/shared/lib/use-alert-store";
+import { ENDPOINT } from "@/shared/config";
+import {
+ BoardApi,
+ boardFormSchema,
+ type BoardFormData,
+} from "@/entities/board";
+import { BbsForm } from "./bbs-form";
+
+function ModifyPage({ bbsId }: { bbsId: string }) {
+ const { setMessage: alert } = useAlertStore((state) => state);
+
+ const { data: boardInfo } = useQuery({
+ queryKey: [ENDPOINT.BOARD_SERVICE.BBS, bbsId],
+ queryFn: () => BoardApi.getBoardInfo(bbsId),
+ });
+
+ const { mutateAsync: updateBoard } = useMutation({
+ mutationFn: (data: BoardFormData) => BoardApi.updateBoard(bbsId, data),
+ onSuccess: () => {
+ alert("수정되었습니다.");
+ },
+ });
+
+ const form = useForm({
+ resolver: zodResolver(boardFormSchema),
+ values: boardInfo,
+ });
+
+ return (
+
+ );
+}
+
+export { ModifyPage };
diff --git a/apps/cs/src/widgets/form-wrapper/ui/form-wrapper.tsx b/apps/cs/src/widgets/form-wrapper/ui/form-wrapper.tsx
index 5b6edb3bc..071b299ee 100644
--- a/apps/cs/src/widgets/form-wrapper/ui/form-wrapper.tsx
+++ b/apps/cs/src/widgets/form-wrapper/ui/form-wrapper.tsx
@@ -54,7 +54,7 @@ function FormWrapper({
- {isModifyMode && (
+ {isModifyMode && handleDelete && (