feat: 게시판 관리 페이지 작업

This commit is contained in:
2025-04-28 11:23:54 +09:00
parent 4284ed87ea
commit 44b820c62e
7 changed files with 234 additions and 4 deletions
@@ -0,0 +1,2 @@
import { BbsPage } from "@/pages/bbs";
export default BbsPage;
@@ -1,12 +1,22 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type {
BoardList,
BoardParams,
BoardPopupList,
BoardPopupParams,
BoardService,
} from "../model/board-interface";
export class BoardApiService implements BoardService {
public async getBoardList(params: BoardParams): Promise<BoardList> {
const response = await client.get<BoardList>(
`${ENDPOINT.BOARD_SERVICE.BBS}`,
{ params },
);
return response.data;
}
public async getBoardPopupList(
params: BoardPopupParams,
): Promise<BoardPopupList> {
+5 -1
View File
@@ -1,2 +1,6 @@
export { BoardApi } from "./api/board-service";
export { type BoardPopup } from "./model/board-interface";
export {
type Board,
type BoardParams,
type BoardPopup,
} from "./model/board-interface";
@@ -9,13 +9,34 @@ export const BOARD_TYPE = {
export type BoardType = (typeof BOARD_TYPE)[keyof typeof BOARD_TYPE];
export interface BoardParams extends PageableParams {
keywordType?: string;
keyword?: string;
bbsId?: number;
bbsTypeCd?: string;
bbsNm?: string;
bbsExpln?: string;
rfrncUseYn?: string;
atflUseYn?: string;
atflMaxCnt?: number;
atflMaxFileSz?: number;
ansUseYn?: string;
cmntUseYn?: string;
dgstfnEvlUseYn?: string;
smsUseYn?: string;
upndFixUseYn?: string;
pstgPrdUseYn?: string;
popupUseYn?: string;
delYn?: string;
}
export interface BoardPopupParams extends PageableParams {
bbsNm?: string;
}
export interface BoardPopup {
export interface Board {
bbsId: number;
bbsTypeCd: BoardType;
bbsTypeCd: string;
bbsTypeNm: string;
bbsNm: string;
bbsExpln: string;
@@ -24,6 +45,7 @@ export interface BoardPopup {
atflMaxCnt: number;
atflMaxFileSz: number;
ansUseYn: string;
ansUseAuthrt: string;
cmntUseYn: string;
dgstfnEvlUseYn: string;
smsUseYn: string;
@@ -31,12 +53,19 @@ export interface BoardPopup {
pstgPrdUseYn: string;
popupUseYn: string;
delYn: string;
regDt: string;
useYn: string;
mdfcnDt: string;
mdfrNm: string;
}
export interface BoardPopup extends Board {
pstCnt: number;
}
export type BoardList = PageableList<Board>;
export type BoardPopupList = PageableList<BoardPopup>;
export interface BoardService {
getBoardList: (params: BoardParams) => Promise<BoardList>;
getBoardPopupList: (params: BoardPopupParams) => Promise<BoardPopupList>;
}
+1
View File
@@ -0,0 +1 @@
export { BbsPage } from "./ui/bbs-page";
@@ -0,0 +1,41 @@
import dayjs from "dayjs";
import type { ColumnDef } from "@tanstack/react-table";
import { Button } from "@common/components/ui";
import type { Board } from "@/entities/board/model/board-interface";
export const columns: ColumnDef<Board>[] = [
{
id: "no",
header: "NO",
cell: ({ row }) => row.index + 1,
},
{
accessorKey: "bbsNm",
header: "게시판명",
},
{
accessorKey: "bbsTypeNm",
header: "게시판유형",
},
{
accessorKey: "mdfrNm",
header: "최종수정자",
},
{
accessorKey: "mdfcnDt",
header: "최종수정일",
cell: ({ row }) =>
row.original.mdfcnDt
? dayjs(row.original.mdfcnDt).format("YYYY-MM-DD")
: "",
},
{
accessorKey: "useYn",
header: "사용여부",
},
{
id: "actions",
header: "관리",
cell: () => <Button size="sm">관리</Button>,
},
];
+143
View File
@@ -0,0 +1,143 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import {
getCoreRowModel,
useReactTable,
type PaginationState,
type RowSelectionState,
} from "@tanstack/react-table";
import {
Button,
DataTable,
Input,
Label,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@common/components";
import { CodeSelect } from "@/entities/code";
import { BoardApi, type BoardParams } from "@/entities/board";
import { ENDPOINT } from "@/shared/config";
import { type Board } from "@/entities/board";
import { columns } from "../model/table-columns";
function BbsPage() {
const router = useRouter();
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [boardParams, setBoardParams] = useState<BoardParams>({
bbsTypeCd: "",
bbsNm: "",
});
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const { data: boardList, refetch } = useQuery({
queryKey: [ENDPOINT.BOARD_SERVICE.BBS],
queryFn: () =>
BoardApi.getBoardList({
...boardParams,
page: pagination.pageIndex,
size: pagination.pageSize,
}),
enabled: false,
});
const table = useReactTable({
data: boardList?.content ?? [],
columns,
state: {
pagination,
rowSelection,
},
rowCount: boardList?.totalElements ?? 0,
manualPagination: true,
enableMultiRowSelection: true,
getCoreRowModel: getCoreRowModel(),
onPaginationChange: setPagination,
onRowSelectionChange: setRowSelection,
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
refetch();
};
const handleRowClick = (row: Board) => {};
useEffect(() => {
refetch();
}, [pagination]);
return (
<div className="card card-border !mt-6">
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex items-center gap-2 p-2">
<Label htmlFor="bbsType" className="mr-2 text-label">
게시판 유형
</Label>
<CodeSelect
upCd="BBSTYPE"
value={boardParams.bbsTypeCd}
onValueChange={(value) =>
setBoardParams({ ...boardParams, bbsTypeCd: value })
}
/>
<Label htmlFor="bbsNm" className="ml-4 mr-2 text-label">
게시판명
</Label>
<Input
id="bbsNm"
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
value={boardParams.bbsNm}
onChange={(e) =>
setBoardParams({ ...boardParams, bbsNm: e.target.value })
}
/>
<Button className="h-[3.2rem]" type="submit">
조회
</Button>
</form>
</div>
<div className="card card-border">
<div className="card-header">
<div className="flex w-full items-center justify-between">
<h3 className="text-2xl font-medium text-label">게시판 목록</h3>
<div className="flex gap-2">
<Button onClick={() => router.push("/bbs/register")}>등록</Button>
<Select
value={table.getState().pagination.pageSize.toString()}
onValueChange={(value) => {
table.setPageSize(Number(value));
}}
>
<SelectTrigger className="h-[3.2rem] w-[12rem]">
<SelectValue placeholder="페이지 크기" />
</SelectTrigger>
<SelectContent>
{[10, 20, 30, 40, 50].map((pageSize) => (
<SelectItem key={pageSize} value={pageSize.toString()}>
{pageSize}개씩 보기
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
</div>
<div className="card !m-[1.2rem] h-full overflow-auto !p-0">
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
</div>
</div>
</div>
);
}
export { BbsPage };