feat: 설문 사이트 게시 이력 관리 작업

This commit is contained in:
2025-05-28 16:17:35 +09:00
parent a42b7249ee
commit f06a8e9637
4 changed files with 153 additions and 34 deletions
@@ -0,0 +1,45 @@
import dayjs from "dayjs";
import type { ColumnDef } from "@tanstack/react-table";
import { Checkbox } from "@common/components";
import type { Post } from "@/entities/posting";
export const columns: ColumnDef<Post>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected()}
onClick={(e) => e.stopPropagation()}
onCheckedChange={(checked) =>
table.toggleAllPageRowsSelected(!!checked)
}
className="h-4 w-4 rounded border-gray-300"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onClick={(e) => e.stopPropagation()}
onCheckedChange={(checked) => row.toggleSelected(!!checked)}
className="h-4 w-4 rounded border-gray-300"
/>
),
meta: {
width: 50,
},
},
{
accessorKey: "siteNm",
header: "사이트",
},
{
accessorKey: "pstgPrdSeNm",
header: "게시기간",
cell: ({ row }) => {
const pstgPrdSeNm = row.original.pstgPrdSeNm;
const pstgBgngDt = row.original.pstgBgngDt;
const pstgEndDt = row.original.pstgEndDt;
return `${pstgPrdSeNm} (${dayjs(pstgBgngDt).format("YYYY-MM-DD")} ~ ${dayjs(pstgEndDt).format("YYYY-MM-DD")})`;
},
},
];
+107 -33
View File
@@ -1,54 +1,128 @@
"use client";
import { useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { Button } from "@common/components";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
getCoreRowModel,
useReactTable,
type RowSelectionState,
} from "@tanstack/react-table";
import { useConfirm } from "@frontend-opensource/use-react-hooks";
import { Button, DataTable } from "@common/components";
import { PostingApi, type PostPayload } from "@/entities/posting";
import { ENDPOINT } from "@/shared/config";
import { useAlertStore } from "@/shared/lib";
import { SurveyApi } from "../api/survey-service";
import { columns } from "../model/posting-table-columns";
function DetailPage({ srvySn }: { srvySn: string }) {
const router = useRouter();
const pathname = usePathname();
const { confirm } = useConfirm();
const queryClient = useQueryClient();
const alert = useAlertStore((state) => state.setMessage);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const { data: surveyInfo } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.SURVEY, srvySn],
queryFn: () => SurveyApi.getSurveyInfo(parseInt(srvySn)),
});
const { data: postHistory } = useQuery({
queryKey: [ENDPOINT.CMS_SERVICE.POSTINGS, srvySn],
queryFn: () =>
PostingApi.getPostingHistory({ pstgTrgtNo: parseInt(srvySn) }),
});
const { mutateAsync: savePostingHistory } = useMutation({
mutationFn: (data: PostPayload[]) => PostingApi.savePosting(data),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [ENDPOINT.CMS_SERVICE.POSTINGS, srvySn],
});
alert("삭제되었습니다.");
},
});
const table = useReactTable({
data: postHistory?.content ?? [],
columns,
state: {
rowSelection,
},
enableMultiRowSelection: true,
getCoreRowModel: getCoreRowModel(),
onRowSelectionChange: setRowSelection,
});
const handleDeletePostingHistory = async () => {
const data = table.getFilteredSelectedRowModel().rows.map((row) => ({
...row.original,
mode: "D",
}));
if (await confirm("삭제하시겠습니까?")) {
savePostingHistory(data);
setRowSelection({});
}
};
return (
<div className="card card-border !mb-0 !mt-6">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">설문 상세</h3>
<div className="flex gap-2">
<Button color="white" onClick={() => router.back()}>
목록
</Button>
<Button onClick={() => router.push(`${pathname}/modify`)}>
수정
</Button>
<Button color="red">삭제</Button>
<div className="mt-6 flex flex-col">
<div className="card card-border !mb-0 !mt-6">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">설문 상세</h3>
<div className="flex gap-2">
<Button color="white" onClick={() => router.back()}>
목록
</Button>
<Button onClick={() => router.push(`${pathname}/modify`)}>
수정
</Button>
<Button color="red">삭제</Button>
</div>
</div>
<ul className="flex flex-col">
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">설문 제목</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyTtl}</p>
</li>
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">설문 목적</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyPrps}</p>
</li>
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">
설문 작성 안내 내용
</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyWrtGdCn}</p>
</li>
<li className="flex items-center gap-8 py-6">
<span className="w-[16rem] text-right text-label">설문 대상</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyTrgt}</p>
</li>
</ul>
</div>
<div className="card card-border">
<div className="card-header">
<h3 className="text-2xl font-medium text-label">사이트 게시 이력</h3>
</div>
<div className="card">
<div className="mb-4 flex justify-end">
<Button
size="sm"
color="red"
disabled={!table.getFilteredSelectedRowModel().rows.length}
onClick={handleDeletePostingHistory}
>
이력삭제
</Button>
</div>
<DataTable table={table} />
</div>
</div>
<ul className="flex flex-col">
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">설문 제목</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyTtl}</p>
</li>
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">설문 목적</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyPrps}</p>
</li>
<li className="flex items-center gap-8 border-b border-border py-6">
<span className="w-[16rem] text-right text-label">
설문 작성 안내 내용
</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyWrtGdCn}</p>
</li>
<li className="flex items-center gap-8 py-6">
<span className="w-[16rem] text-right text-label">설문 대상</span>
<p className="text-2xl font-bold">{surveyInfo?.srvyTrgt}</p>
</li>
</ul>
</div>
);
}
+1 -1
View File
@@ -15,7 +15,7 @@ import { AuthorityButton } from "@/entities/menu-authority";
import { ENDPOINT } from "@/shared/config";
import { SurveyApi } from "../api/survey-service";
import type { Survey, SurveyParams } from "../model/survey-interface";
import { columns } from "../model/table-columns";
import { columns } from "../model/survey-table-columns";
type PostingTarget = {
pstgTrgtNm: string;