From 0b0d56707232b82d3917c3a0827a4fea9e9f052c Mon Sep 17 00:00:00 2001 From: bicochan Date: Wed, 30 Apr 2025 18:44:00 +0900 Subject: [PATCH 001/218] =?UTF-8?q?WIP:=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbsnotice/[bbsId]/[pstNo]/modify/page.tsx | 10 + .../src/entities/post/api/post-service.ts | 23 ++ .../features/src/entities/post/index.ts | 14 +- .../src/entities/post/model/post-interface.ts | 30 ++ .../common/features/src/pages/notice/index.ts | 1 + .../src/pages/notice/ui/create-page.tsx | 45 +++ .../src/pages/notice/ui/modify-page.tsx | 49 ++++ .../src/pages/notice/ui/notice-form.tsx | 262 ++++++++++++++++++ .../src/widgets/post/ui/post-action.tsx | 10 +- apps/common/features/tailwind.config.ts | 4 +- apps/cs/src/app/styles/base.css | 1 + apps/cs/tailwind.config.ts | 4 +- 12 files changed, 442 insertions(+), 11 deletions(-) create mode 100644 apps/common/features/app/(with-base-layout)/pst/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx create mode 100644 apps/common/features/src/pages/notice/ui/create-page.tsx create mode 100644 apps/common/features/src/pages/notice/ui/modify-page.tsx create mode 100644 apps/common/features/src/pages/notice/ui/notice-form.tsx diff --git a/apps/common/features/app/(with-base-layout)/pst/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx b/apps/common/features/app/(with-base-layout)/pst/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx new file mode 100644 index 000000000..86f0ca871 --- /dev/null +++ b/apps/common/features/app/(with-base-layout)/pst/bbsnotice/[bbsId]/[pstNo]/modify/page.tsx @@ -0,0 +1,10 @@ +import { ModifyPage } from "@/pages/notice"; + +export default async function PstBbsNoticePostModifyPage({ + params, +}: { + params: Promise<{ bbsId: string; pstNo: string }>; +}) { + const { bbsId, pstNo } = await params; + return ; +} diff --git a/apps/common/features/src/entities/post/api/post-service.ts b/apps/common/features/src/entities/post/api/post-service.ts index 04034bc78..96c0377fc 100644 --- a/apps/common/features/src/entities/post/api/post-service.ts +++ b/apps/common/features/src/entities/post/api/post-service.ts @@ -1,10 +1,13 @@ import { client } from "@/shared/api"; import { ENDPOINT } from "@/shared/config"; import type { + Post, PostInfo, PostList, PostParams, PostService, + PostFormData, + PostUpdateFormData, } from "../model/post-interface"; export class PostApiService implements PostService { @@ -22,6 +25,26 @@ export class PostApiService implements PostService { return response.data; } + public async createPost(data: PostFormData): Promise { + const response = await client.post( + `${ENDPOINT.BOARD_SERVICE.POSTS}`, + data, + ); + return response.data; + } + + public async updatePost( + bbsId: string, + pstNo: string, + data: PostUpdateFormData, + ): Promise { + const response = await client.put( + `${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`, + data, + ); + return response.data; + } + public async deletePost(bbsId: string, pstNo: string): Promise { await client.delete(`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`); } diff --git a/apps/common/features/src/entities/post/index.ts b/apps/common/features/src/entities/post/index.ts index 933fb0a51..d2b94ba84 100644 --- a/apps/common/features/src/entities/post/index.ts +++ b/apps/common/features/src/entities/post/index.ts @@ -1,7 +1,11 @@ export { PostApi } from "./api/post-service"; -export type { - Post, - PostList, - PostParams, - PostService, +export { + postFormSchema, + postUpdateFormSchema, + type Post, + type PostList, + type PostParams, + type PostService, + type PostFormData, + type PostUpdateFormData, } from "./model/post-interface"; diff --git a/apps/common/features/src/entities/post/model/post-interface.ts b/apps/common/features/src/entities/post/model/post-interface.ts index ec9021fad..7a7f95108 100644 --- a/apps/common/features/src/entities/post/model/post-interface.ts +++ b/apps/common/features/src/entities/post/model/post-interface.ts @@ -1,3 +1,4 @@ +import { z } from "zod"; import { type PageableList, type PageableParams, @@ -38,10 +39,39 @@ export interface PostInfo extends Post { mdfr: string; } +export const postFormSchema = z.object({ + bbsId: z.number(), + pstTtl: z.string(), + pstCn: z.string().nullish(), + rfrncUrl: z.string().nullish(), + popupYn: z.string().nullish(), + upndFixYn: z.string().nullish(), + prdPstgYn: z.string().nullish(), + pstPswd: z.string(), + wrtrNm: z.string().nullish(), + wrtrCplc: z.string().nullish(), + atflCd: z.string().nullish(), + parentPstNo: z.number().nullish(), +}); + +export const postUpdateFormSchema = postFormSchema.omit({ + bbsId: true, + pstPswd: true, + parentPstNo: true, +}); + export type PostList = PageableList; +export type PostFormData = z.infer; +export type PostUpdateFormData = z.infer; export interface PostService { getPostList(params: PostParams): Promise; getPostInfo(bbsId: string, pstNo: string): Promise; + createPost(data: PostFormData): Promise; + updatePost( + bbsId: string, + pstNo: string, + data: PostUpdateFormData, + ): Promise; deletePost(bbsId: string, pstNo: string): Promise; } diff --git a/apps/common/features/src/pages/notice/index.ts b/apps/common/features/src/pages/notice/index.ts index c75abbdc8..f904f2695 100644 --- a/apps/common/features/src/pages/notice/index.ts +++ b/apps/common/features/src/pages/notice/index.ts @@ -1,2 +1,3 @@ export { NoticePage } from "./ui/notice-page"; export { NoticePost } from "./ui/notice-post"; +export { ModifyPage } from "./ui/modify-page"; diff --git a/apps/common/features/src/pages/notice/ui/create-page.tsx b/apps/common/features/src/pages/notice/ui/create-page.tsx new file mode 100644 index 000000000..7e49ac6f4 --- /dev/null +++ b/apps/common/features/src/pages/notice/ui/create-page.tsx @@ -0,0 +1,45 @@ +"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 { postFormSchema, type PostFormData } from "@/entities/post"; +import { PostApi } from "@/entities/post"; +import { NoticeForm } from "./notice-form"; +import { NoticeLayout } from "./notice-layout"; + +function CreatePage() { + const router = useRouter(); + const { setMessage: alert } = useAlertStore((state) => state); + + const { mutateAsync: createPost } = useMutation({ + mutationFn: (data: PostFormData) => PostApi.createPost(data), + onSuccess: () => { + alert("등록되었습니다.", router.back); + }, + }); + + const form = useForm({ + resolver: zodResolver(postFormSchema), + defaultValues: { + bbsId: 0, + pstTtl: "", + pstPswd: "", + }, + }); + + return ( + +
+
+

게시글 등록

+
+ +
+
+ ); +} + +export { CreatePage }; diff --git a/apps/common/features/src/pages/notice/ui/modify-page.tsx b/apps/common/features/src/pages/notice/ui/modify-page.tsx new file mode 100644 index 000000000..590485f36 --- /dev/null +++ b/apps/common/features/src/pages/notice/ui/modify-page.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useMutation, useQuery } from "@tanstack/react-query"; +import { + PostApi, + postUpdateFormSchema, + type PostUpdateFormData, +} from "@/entities/post"; +import { ENDPOINT } from "@/shared/config"; +import { useAlertStore } from "@/shared/lib/use-alert-store"; +import { NoticeForm } from "./notice-form"; +import { NoticeLayout } from "./notice-layout"; + +function ModifyPage({ bbsId, pstNo }: { bbsId: string; pstNo: string }) { + const { setMessage: alert } = useAlertStore((state) => state); + + const { data: postInfo } = useQuery({ + queryKey: [ENDPOINT.BOARD_SERVICE.POSTS, bbsId, pstNo], + queryFn: () => PostApi.getPostInfo(bbsId, pstNo), + }); + + const { mutateAsync: updatePost } = useMutation({ + mutationFn: (data: PostUpdateFormData) => + PostApi.updatePost(bbsId, pstNo, data), + onSuccess: () => { + alert("수정되었습니다."); + }, + }); + + const form = useForm({ + resolver: zodResolver(postUpdateFormSchema), + values: postInfo, + }); + + return ( + +
+
+

게시글 수정

+
+ +
+
+ ); +} + +export { ModifyPage }; diff --git a/apps/common/features/src/pages/notice/ui/notice-form.tsx b/apps/common/features/src/pages/notice/ui/notice-form.tsx new file mode 100644 index 000000000..cacc68787 --- /dev/null +++ b/apps/common/features/src/pages/notice/ui/notice-form.tsx @@ -0,0 +1,262 @@ +import type { UseFormReturn, FieldPath } from "react-hook-form"; +import type { Post, PostFormData, PostUpdateFormData } from "@/entities/post"; +import { + Input, + Label, + RadioGroup, + RadioGroupItem, + Table, + TableBody, + TableCell, + TableHead, + TableRow, + Textarea, + Button, +} from "@common/components"; +import { Form, FormControl, FormField, FormItem } from "@/shared/ui/form"; + +type NoticeFormProps = { + form: UseFormReturn; + handleSave: (data: T) => Promise; +}; + +function NoticeForm({ + form, + handleSave, +}: NoticeFormProps) { + const onSubmit = async (data: T) => { + await handleSave(data); + }; + + return ( +
+ +
+ + + + + + + + + + 제목 + + } + render={({ field }) => ( + + + + + + )} + /> + + + + 작성자 + + } + render={({ field }) => ( + + + + + + )} + /> + + 비밀번호 + + } + render={({ field }) => ( + + + + + + )} + /> + + + + 내용 + + } + render={({ field }) => ( + + +