feat: 게시판 상세 및 삭제 기능 작업
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import { NoticePost } from "@/pages/notice";
|
||||
|
||||
export default async function PstBbsNoticePostPage({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ bbsId: string; pstNo: string }>;
|
||||
}) {
|
||||
const { bbsId, pstNo } = await params;
|
||||
return <NoticePost bbsId={bbsId} pstNo={pstNo} />;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
PostInfo,
|
||||
PostList,
|
||||
PostParams,
|
||||
PostService,
|
||||
@@ -13,6 +14,17 @@ export class PostApiService implements PostService {
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getPostInfo(bbsId: string, pstNo: string): Promise<PostInfo> {
|
||||
const response = await client.get<PostInfo>(
|
||||
`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async deletePost(bbsId: string, pstNo: string): Promise<void> {
|
||||
await client.delete(`${ENDPOINT.BOARD_SERVICE.POSTS}/${bbsId}/${pstNo}`);
|
||||
}
|
||||
}
|
||||
|
||||
export const PostApi = new PostApiService();
|
||||
|
||||
@@ -31,8 +31,17 @@ export interface Post {
|
||||
rgtrNm: string;
|
||||
}
|
||||
|
||||
export interface PostInfo extends Post {
|
||||
pstCn: string;
|
||||
rgtr: string;
|
||||
mdfcnDt: string;
|
||||
mdfr: string;
|
||||
}
|
||||
|
||||
export type PostList = PageableList<Post>;
|
||||
|
||||
export interface PostService {
|
||||
getPostList(params: PostParams): Promise<PostList>;
|
||||
getPostInfo(bbsId: string, pstNo: string): Promise<PostInfo>;
|
||||
deletePost(bbsId: string, pstNo: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { NoticePage } from "./ui/notice-page";
|
||||
export { NoticePost } from "./ui/notice-post";
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import type { Board } from "@/entities/board";
|
||||
import { PageLayout } from "@/shared/ui/page-layout";
|
||||
import { useLocalStorage } from "@frontend-opensource/use-react-hooks";
|
||||
|
||||
function NoticeLayout({ children }: { children: React.ReactNode }) {
|
||||
const [bbsInfo, setBbsInfo] = useState<Board | null>(null);
|
||||
const [storedBbsInfo] = useLocalStorage("bbs-info", "");
|
||||
|
||||
useEffect(() => {
|
||||
if (storedBbsInfo) setBbsInfo(JSON.parse(storedBbsInfo));
|
||||
}, [storedBbsInfo]);
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
title={bbsInfo?.bbsNm ?? ""}
|
||||
menuPaths={["서비스관리", "게시판관리"]}
|
||||
>
|
||||
{children}
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export { NoticeLayout };
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
type PaginationState,
|
||||
type RowSelectionState,
|
||||
} from "@tanstack/react-table";
|
||||
import { useLocalStorage } from "@frontend-opensource/use-react-hooks";
|
||||
import {
|
||||
Button,
|
||||
DataTable,
|
||||
@@ -21,16 +20,14 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@common/components/ui";
|
||||
import type { Board } from "@/entities/board";
|
||||
import { PostApi, type Post, type PostParams } from "@/entities/post";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { PageLayout } from "@/shared/ui/page-layout";
|
||||
import { columns } from "../model/notice-table-columns";
|
||||
import { NoticeLayout } from "./notice-layout";
|
||||
|
||||
function NoticePage({ bbsId }: { bbsId: string }) {
|
||||
const router = useRouter();
|
||||
const [storedBbsInfo] = useLocalStorage("bbs-info", "");
|
||||
const [bbsInfo, setBbsInfo] = useState<Board | null>(null);
|
||||
const pathname = usePathname();
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
const [postParams, setPostParams] = useState<PostParams>({
|
||||
keywordType: "title",
|
||||
@@ -75,22 +72,15 @@ function NoticePage({ bbsId }: { bbsId: string }) {
|
||||
};
|
||||
|
||||
const handleRowClick = (row: Post) => {
|
||||
router.push(`/bbs/register/${row.bbsId}`);
|
||||
router.push(`${pathname}/${row.pstNo}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, [pagination]);
|
||||
|
||||
useEffect(() => {
|
||||
if (storedBbsInfo) setBbsInfo(JSON.parse(storedBbsInfo));
|
||||
}, [storedBbsInfo]);
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
title={bbsInfo?.bbsNm ?? ""}
|
||||
menuPaths={["서비스관리", "게시판관리"]}
|
||||
>
|
||||
<NoticeLayout>
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
|
||||
@@ -175,7 +165,7 @@ function NoticePage({ bbsId }: { bbsId: string }) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
</NoticeLayout>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { Post } from "@/widgets/post";
|
||||
import { NoticeLayout } from "./notice-layout";
|
||||
|
||||
function NoticePost({ bbsId, pstNo }: { bbsId: string; pstNo: string }) {
|
||||
return (
|
||||
<NoticeLayout>
|
||||
<Post bbsId={bbsId} pstNo={pstNo} />
|
||||
</NoticeLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export { NoticePost };
|
||||
@@ -0,0 +1 @@
|
||||
export { Post } from "./ui/post";
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { Button } from "@common/components/ui";
|
||||
import { PostApi } from "@/entities/post";
|
||||
|
||||
type PostActionProps = {
|
||||
bbsId: string;
|
||||
pstNo: string;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
function PostAction({ children, bbsId, pstNo }: PostActionProps) {
|
||||
const router = useRouter();
|
||||
const { confirm } = useConfirm();
|
||||
|
||||
const { mutate: deletePost } = useMutation({
|
||||
mutationFn: () => PostApi.deletePost(bbsId, pstNo),
|
||||
onSuccess: () => {
|
||||
router.back();
|
||||
},
|
||||
});
|
||||
|
||||
const onDelete = async () => {
|
||||
if (await confirm("삭제하시겠습니까?")) deletePost();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{children}
|
||||
<div className="flex justify-center gap-4 pb-12 pt-10">
|
||||
<Button
|
||||
size="lg"
|
||||
color="white"
|
||||
type="button"
|
||||
onClick={() => router.back()}
|
||||
>
|
||||
목록
|
||||
</Button>
|
||||
<Button size="lg" type="submit">
|
||||
수정
|
||||
</Button>
|
||||
<Button size="lg" color="red" type="button" onClick={onDelete}>
|
||||
삭제
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { PostAction };
|
||||
@@ -0,0 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { PostApi } from "@/entities/post";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { PostAction } from "./post-action";
|
||||
|
||||
function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) {
|
||||
const { data: postData } = useQuery({
|
||||
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
|
||||
queryFn: () => PostApi.getPostInfo(bbsId, pstNo),
|
||||
});
|
||||
|
||||
return (
|
||||
<PostAction bbsId={bbsId} pstNo={pstNo}>
|
||||
<div className="card card-border !p-8">
|
||||
<h3 className="text-[2rem] font-bold">{postData?.pstTtl}</h3>
|
||||
<div className="card !m-0 !mt-8 bg-accent">
|
||||
<ul className="flex gap-8 p-4 text-xl text-label">
|
||||
<li>
|
||||
작성자: <b>{postData?.wrtrNm}</b>
|
||||
</li>
|
||||
<li>
|
||||
등록일: <b>{dayjs(postData?.regDt).format("YYYY-MM-DD")}</b>
|
||||
</li>
|
||||
<li>
|
||||
조회수: <b>{postData?.inqNocs}</b>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<hr className="mt-8" />
|
||||
<div
|
||||
className="min-h-[40rem] p-8"
|
||||
dangerouslySetInnerHTML={{ __html: postData?.pstCn ?? "" }}
|
||||
/>
|
||||
<hr className="mt-8" />
|
||||
<div className="flex items-center gap-4 p-8">
|
||||
<span>첨부파일</span>
|
||||
</div>
|
||||
</div>
|
||||
</PostAction>
|
||||
);
|
||||
}
|
||||
|
||||
export { Post };
|
||||
Reference in New Issue
Block a user