diff --git a/apps/cs/src/pages/popup/model/posting-table-columns.tsx b/apps/cs/src/pages/popup/model/posting-table-columns.tsx new file mode 100644 index 000000000..d9de20543 --- /dev/null +++ b/apps/cs/src/pages/popup/model/posting-table-columns.tsx @@ -0,0 +1,42 @@ +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[] = [ + { + id: "select", + header: ({ table }) => ( + e.stopPropagation()} + onCheckedChange={(checked) => + table.toggleAllPageRowsSelected(!!checked) + } + className="h-4 w-4 rounded border-gray-300" + /> + ), + cell: ({ row }) => ( + e.stopPropagation()} + onCheckedChange={(checked) => row.toggleSelected(!!checked)} + className="h-4 w-4 rounded border-gray-300" + /> + ), + }, + { + 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")})`; + }, + }, +]; diff --git a/apps/cs/src/pages/popup/model/table-columns.tsx b/apps/cs/src/pages/popup/model/table-columns.tsx index ad3938e2b..b223f689b 100644 --- a/apps/cs/src/pages/popup/model/table-columns.tsx +++ b/apps/cs/src/pages/popup/model/table-columns.tsx @@ -1,8 +1,30 @@ import dayjs from "dayjs"; import { type ColumnDef } from "@tanstack/react-table"; import type { Popup } from "./popup-interface"; +import { Checkbox } from "@common/components"; export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + e.stopPropagation()} + onCheckedChange={(checked) => + table.toggleAllPageRowsSelected(!!checked) + } + className="h-4 w-4 rounded border-gray-300" + /> + ), + cell: ({ row }) => ( + e.stopPropagation()} + onCheckedChange={(checked) => row.toggleSelected(!!checked)} + className="h-4 w-4 rounded border-gray-300" + /> + ), + }, { id: "no", header: "NO", diff --git a/apps/cs/src/pages/popup/ui/modify-page.tsx b/apps/cs/src/pages/popup/ui/modify-page.tsx index db556a53b..69d1171b5 100644 --- a/apps/cs/src/pages/popup/ui/modify-page.tsx +++ b/apps/cs/src/pages/popup/ui/modify-page.tsx @@ -1,29 +1,49 @@ "use client"; +import { useState } from "react"; import { useRouter } from "next/navigation"; import { useForm } from "react-hook-form"; -import { useMutation, useQuery } from "@tanstack/react-query"; import { zodResolver } from "@hookform/resolvers/zod"; +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 { DataTable } from "@common/components"; +import { AuthorityButton } from "@/entities/menu-authority"; +import { PostingApi, type PostPayload } from "@/entities/posting"; import { useAlertStore, useUserStore } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; import { popupUpdateFormSchema, type PopupUpdateFormData, } from "../model/popup-interface"; +import { columns } from "../model/posting-table-columns"; import { PopupApi } from "../api/popup-service"; import { PopupForm } from "./popup-form"; function ModifyPage({ popupSn }: { popupSn: number }) { const router = useRouter(); + const queryClient = useQueryClient(); + const { confirm } = useConfirm(); const { userInfo } = useUserStore((state) => state); const { setMessage: alert } = useAlertStore((state) => state); + const [rowSelection, setRowSelection] = useState({}); + const { data: popupInfo } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.POPUPS, popupSn], queryFn: () => PopupApi.getPopupInfo(popupSn), enabled: !!popupSn, }); + const { data: postHistory } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.POSTINGS, popupSn], + queryFn: () => PostingApi.getPostingHistory({ pstgTrgtNo: popupSn }), + }); + const { mutateAsync: updatePopup } = useMutation({ mutationFn: (data: PopupUpdateFormData) => PopupApi.updatePopup(popupSn, data), @@ -32,6 +52,16 @@ function ModifyPage({ popupSn }: { popupSn: number }) { }, }); + const { mutateAsync: savePostingHistory } = useMutation({ + mutationFn: (data: PostPayload[]) => PostingApi.savePosting(data), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.CMS_SERVICE.POSTINGS, popupSn], + }); + alert("삭제되었습니다."); + }, + }); + const form = useForm({ resolver: zodResolver(popupUpdateFormSchema), values: { @@ -40,12 +70,56 @@ function ModifyPage({ popupSn }: { popupSn: number }) { }, }); + 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 ( -
-
-

팝업 수정

+
+
+
+

팝업 수정

+
+ +
+
+
+

사이트 게시 이력

+
+
+
+ + 이력삭제 + +
+ +
-
); } diff --git a/apps/cs/src/pages/popup/ui/popup-page.tsx b/apps/cs/src/pages/popup/ui/popup-page.tsx index ced5bd80c..3c9b4fddd 100644 --- a/apps/cs/src/pages/popup/ui/popup-page.tsx +++ b/apps/cs/src/pages/popup/ui/popup-page.tsx @@ -1,19 +1,27 @@ "use client"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import { keepPreviousData, useQuery } from "@tanstack/react-query"; import { getCoreRowModel, useReactTable, type PaginationState, + type RowSelectionState, } from "@tanstack/react-table"; import { Button, DataTable, Input, Label } from "@common/components"; +import { AuthorityButton } from "@/entities/menu-authority"; +import { POSTING_TYPE, PostingDialog } from "@/entities/posting"; import { ENDPOINT } from "@/shared/config"; import { PopupApi } from "../api/popup-service"; import { columns } from "../model/table-columns"; import type { Popup, PopupParams } from "../model/popup-interface"; +type PostingTarget = { + pstgTrgtNm: string; + pstgTrgtNo: number; +}; + function PopupPage() { const router = useRouter(); @@ -24,6 +32,8 @@ function PopupPage() { pageIndex: 0, pageSize: 10, }); + const [rowSelection, setRowSelection] = useState({}); + const [postingTargets, setPostingTargets] = useState([]); const { data: popupList, refetch } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.POPUPS], @@ -51,12 +61,30 @@ function PopupPage() { rowCount: popupList?.totalElements ?? 0, state: { pagination, + rowSelection, }, - onPaginationChange: setPagination, - getCoreRowModel: getCoreRowModel(), manualPagination: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + onRowSelectionChange: setRowSelection, }); + useEffect(() => { + const postingTargets = table + .getFilteredSelectedRowModel() + .rows.map((row) => ({ + pstgTrgtNm: row.original.popupTtl, + pstgTrgtNo: row.original.popupSn, + })); + + if (!postingTargets.length) { + setPostingTargets([]); + return; + } + + setPostingTargets(postingTargets); + }, [rowSelection]); + return (
@@ -79,7 +107,18 @@ function PopupPage() {

팝업 목록

- +
+ + router.push("/popup/register")} + > + 등록 + +