feat: 팝업 사이트 반영 기능 작업
This commit is contained in:
@@ -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<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"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
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")})`;
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -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<Popup>[] = [
|
||||
{
|
||||
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"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
|
||||
@@ -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<RowSelectionState>({});
|
||||
|
||||
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<PopupUpdateFormData>({
|
||||
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 (
|
||||
<div className="card card-border !mb-0 !mt-6">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">팝업 수정</h3>
|
||||
<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>
|
||||
<PopupForm form={form} handleSave={updatePopup} />
|
||||
</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">
|
||||
<AuthorityButton
|
||||
authority="mngAuthrtYn"
|
||||
size="sm"
|
||||
color="red"
|
||||
disabled={!table.getFilteredSelectedRowModel().rows.length}
|
||||
onClick={handleDeletePostingHistory}
|
||||
>
|
||||
이력삭제
|
||||
</AuthorityButton>
|
||||
</div>
|
||||
<DataTable table={table} />
|
||||
</div>
|
||||
</div>
|
||||
<PopupForm form={form} handleSave={updatePopup} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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<RowSelectionState>({});
|
||||
const [postingTargets, setPostingTargets] = useState<PostingTarget[]>([]);
|
||||
|
||||
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 (
|
||||
<div className="card card-border !mt-6">
|
||||
<div className="card card-border">
|
||||
@@ -79,7 +107,18 @@ function PopupPage() {
|
||||
<div className="card card-border">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">팝업 목록</h3>
|
||||
<Button onClick={() => router.push("/popup/register")}>등록</Button>
|
||||
<div className="flex items-center gap-2">
|
||||
<PostingDialog
|
||||
postingType={POSTING_TYPE.POPUP}
|
||||
postingTargets={postingTargets}
|
||||
/>
|
||||
<AuthorityButton
|
||||
authority="regAuthrtYn"
|
||||
onClick={() => router.push("/popup/register")}
|
||||
>
|
||||
등록
|
||||
</AuthorityButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] h-[29.2rem] overflow-auto !p-0">
|
||||
<DataTable table={table} onRowClick={handleRowClick} viewPagination />
|
||||
|
||||
Reference in New Issue
Block a user