feat: 템플릿 관리 페이지 생성

This commit is contained in:
2025-04-09 13:06:44 +09:00
parent dc1abe83fa
commit ec4b7db2f3
9 changed files with 254 additions and 55 deletions
@@ -0,0 +1,2 @@
import { TemplatePage } from "@/pages/template";
export default TemplatePage;
@@ -1,31 +1,30 @@
import { createColumnHelper } from "@tanstack/react-table";
import type { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@common/components/ui";
import type { BoardPopup } from "@/entities/board";
const columnHelper = createColumnHelper<BoardPopup>();
const columns = [
columnHelper.accessor((_, index) => index + 1, {
export const columns: ColumnDef<BoardPopup>[] = [
{
id: "no",
header: "NO",
}),
columnHelper.accessor("bbsNm", {
id: "bbsNm",
cell: ({ row }) => row.index + 1,
},
{
accessorKey: "bbsNm",
header: "게시판명",
}),
columnHelper.accessor("bbsTypeNm", {
id: "bbsTypeNm",
},
{
accessorKey: "bbsTypeNm",
header: "게시판유형",
}),
columnHelper.accessor("regDt", {
id: "regDt",
},
{
accessorKey: "regDt",
header: "최초생성일",
}),
columnHelper.accessor("pstCnt", {
id: "pstCnt",
},
{
accessorKey: "pstCnt",
header: "게시물건수",
}),
columnHelper.display({
},
{
id: "select",
header: "선택",
cell: ({ row }) => {
@@ -37,7 +36,5 @@ const columns = [
/>
);
},
}),
},
];
export { columns };
+28 -33
View File
@@ -1,48 +1,43 @@
import dayjs from "dayjs";
import { createColumnHelper } from "@tanstack/react-table";
import { type ColumnDef } from "@tanstack/react-table";
import type { Site } from "@/entities/site";
const columnHelper = createColumnHelper<Site>();
const columns = [
columnHelper.accessor((_, index) => index + 1, {
export const columns: ColumnDef<Site>[] = [
{
id: "no",
header: "NO",
}),
columnHelper.accessor("siteId", {
id: "siteId",
cell: ({ row }) => row.index + 1,
},
{
accessorKey: "siteId",
header: "사이트코드",
}),
columnHelper.accessor("siteNm", {
id: "siteNm",
},
{
accessorKey: "siteNm",
header: "사이트명",
}),
columnHelper.accessor("dmnAddr", {
id: "dmnAddr",
},
{
accessorKey: "dmnAddr",
header: "대표 URL",
}),
columnHelper.accessor("bscSiteYn", {
id: "bscSiteYn",
},
{
accessorKey: "bscSiteYn",
header: "기본 사이트 여부",
cell: (info) => (info.getValue() ? "Y" : "N"),
}),
columnHelper.accessor("useYn", {
id: "useYn",
},
{
accessorKey: "useYn",
header: "사용 여부",
cell: (info) => (info.getValue() ? "Y" : "N"),
}),
columnHelper.accessor("rgTrNm", {
id: "rgTrNm",
},
{
accessorKey: "rgTrNm",
header: "등록자",
}),
columnHelper.accessor("regDt", {
id: "regDt",
},
{
accessorKey: "regDt",
header: "등록일",
cell: (info) => {
const date = dayjs(info.getValue());
cell: ({ row }) => {
const date = dayjs(row.original.regDt);
return date.format("YYYY-MM-DD");
},
}),
},
];
export { columns };
@@ -0,0 +1,19 @@
import { client } from "@/shared/api";
import { ENDPOINT } from "@/shared/config";
import type {
TemplateService,
TemplateList,
TemplateParams,
} from "../model/template-interface";
export class TemplateApiService implements TemplateService {
public async getTemplateList(params?: TemplateParams): Promise<TemplateList> {
const response = await client.get<TemplateList>(
`${ENDPOINT.CMS_SERVICE.TEMPLATE}`,
{ params },
);
return response.data;
}
}
export const TemplateApi = new TemplateApiService();
+1
View File
@@ -0,0 +1 @@
export { TemplatePage } from "./ui/template-page";
@@ -0,0 +1,25 @@
import type { PageableParams, PageableList } from "@/shared/model";
export interface TemplateParams extends PageableParams {
keywordType?: string;
keyword?: string;
tmpltSeCd?: string;
useYn?: string;
}
export interface Template {
tmpltSn: number;
tmpltNm: string;
tmpltSeCd: string;
tmpltSeNm: string;
useYn: string;
mdfcnDt: string;
mdfr: string;
mdfrNm: string;
}
export type TemplateList = PageableList<Template>;
export interface TemplateService {
getTemplateList(params: TemplateParams): Promise<TemplateList>;
}
@@ -0,0 +1,35 @@
import type { ColumnDef } from "@tanstack/react-table";
import type { Template } from "./template-interface";
import dayjs from "dayjs";
export const columns: ColumnDef<Template>[] = [
{
id: "no",
header: "NO",
cell: ({ row }) => row.index + 1,
},
{
accessorKey: "tmpltNm",
header: "템플릿명",
},
{
accessorKey: "tmpltSeNm",
header: "템플릿분류",
},
{
accessorKey: "useYn",
header: "사용여부",
},
{
accessorKey: "mdfrNm",
header: "최종수정자",
},
{
accessorKey: "mdfcnDt",
header: "최종수정일",
cell: ({ row }) => {
const date = row.getValue("mdfcnDt") as string;
return date ? dayjs(date).format("YYYY-MM-DD") : "";
},
},
];
@@ -0,0 +1,124 @@
"use client";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import {
getCoreRowModel,
useReactTable,
type PaginationState,
} from "@tanstack/react-table";
import { Button, DataTable, Input, Label } from "@common/components";
import { CodeSelect } from "@/entities/code/ui/code-select";
import { ENDPOINT } from "@/shared/config";
import { TemplateApi } from "../api/template-service";
import { columns } from "../model/template-table-columns";
import type { Template } from "../model/template-interface";
function TemplatePage() {
const router = useRouter();
const [templateQuery, setTemplateQuery] = useState({
tmpltSeCd: "",
keyword: "",
});
const [pagination, setPagination] = useState<PaginationState>({
pageIndex: 0,
pageSize: 5,
});
const { data: templateList, refetch } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.TEMPLATE],
queryFn: () =>
TemplateApi.getTemplateList({
...templateQuery,
page: pagination.pageIndex,
size: pagination.pageSize,
}),
placeholderData: keepPreviousData,
enabled: false,
});
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
refetch();
};
const handleRowClick = (row: Template) => {
router.push(`/template/register/${row.tmpltSn}`);
};
const table = useReactTable({
data: templateList?.content ?? [],
columns,
rowCount: templateList?.totalElements ?? 0,
state: {
pagination,
},
onPaginationChange: setPagination,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
});
useEffect(() => {
refetch();
}, []);
useEffect(() => {
refetch();
}, [pagination]);
return (
<div className="card card-border !mt-6">
<div className="card card-border">
<form onSubmit={handleSubmit} className="flex gap-2 p-2">
<div className="flex space-x-6">
<div className="flex items-center gap-2">
<Label htmlFor="" className="text-label">
템플릿분류
</Label>
<CodeSelect
upCd="TMPLTCLCD"
value={templateQuery.tmpltSeCd}
onValueChange={(value) =>
setTemplateQuery({ ...templateQuery, tmpltSeCd: value })
}
/>
</div>
<div className="flex items-center gap-2">
<Label htmlFor="" className="text-label">
템플릿명
</Label>
<Input
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
value={templateQuery.keyword}
onChange={(e) =>
setTemplateQuery({
...templateQuery,
keyword: e.target.value,
})
}
/>
</div>
</div>
<Button className="h-[3.2rem]" type="submit">
조회
</Button>
</form>
</div>
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">템플릿 목록</h3>
<Button onClick={() => router.push("/template/register")}>
등록
</Button>
</div>
<div className="card !m-[1.2rem] h-[29.2rem] overflow-auto !p-0">
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
</div>
</div>
</div>
);
}
export { TemplatePage };
+1
View File
@@ -25,6 +25,7 @@ export const ENDPOINT = {
USER_ORGANIZATION: "/cms-service/api/v1/user-ognz",
IMAGES: "/cms-service/api/v1/images",
BANNERS: "/cms-service/api/v1/bnrs",
TEMPLATE: "/cms-service/api/v1/tmplt",
},
BOARD_SERVICE: {
BBS: "/board-service/api/v1/bbs",