feat: 사이트 게시 이력 api 작업
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type { PageableList } from "@/shared/model";
|
||||
import type {
|
||||
PostService,
|
||||
PostingParams,
|
||||
Post,
|
||||
WithModePostData,
|
||||
} from "../model/posting-interface";
|
||||
|
||||
export class PostingApiService implements PostService {
|
||||
public async getPostingHistory(
|
||||
params: PostingParams,
|
||||
): Promise<PageableList<Post>> {
|
||||
const response = await client.get<PageableList<Post>>(
|
||||
`${ENDPOINT.CMS_SERVICE.SITE_PSTGS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async requestPosting(data: WithModePostData[]): Promise<Post[]> {
|
||||
const response = await client.post<Post[]>(
|
||||
`${ENDPOINT.CMS_SERVICE.SITE_PSTGS}`,
|
||||
data,
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const PostingApi = new PostingApiService();
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface PostingParams extends PageableParams {
|
||||
pstgTrgtNo: number;
|
||||
}
|
||||
|
||||
export interface Post {
|
||||
siteId: string;
|
||||
siteNm: string;
|
||||
pstgTypeCd: string;
|
||||
pstgTypeNm: string;
|
||||
pstgTrgtNo: number;
|
||||
pstgBgngDt: string;
|
||||
pstgEndDt: string;
|
||||
pstgPrdSeCd: string;
|
||||
pstgPrdSeNm: string;
|
||||
delYn: string;
|
||||
}
|
||||
|
||||
export interface WithModePostData extends Post {
|
||||
mode: string;
|
||||
}
|
||||
|
||||
export interface PostService {
|
||||
getPostingHistory: (params: PostingParams) => Promise<PageableList<Post>>;
|
||||
requestPosting: (data: WithModePostData[]) => Promise<Post[]>;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import { Checkbox } from "@common/components/ui";
|
||||
import { type Post } from "./posting-interface";
|
||||
|
||||
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")})`;
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { ImageApi } from "../api/image-service";
|
||||
import { columns } from "../model/table-columns";
|
||||
import { columns } from "../model/image-table-columns";
|
||||
import { type Image, type ImageParams } from "../model/image-interface";
|
||||
|
||||
function ImagePage() {
|
||||
|
||||
@@ -1,24 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
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/ui";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { imageFormSchema, type ImageFormData } from "../model/image-interface";
|
||||
import { ImageApi } from "../api/image-service";
|
||||
import { ImageForm } from "./image-form";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { ConfirmDialog } from "@/shared/ui/confirm-dialog";
|
||||
import { imageFormSchema, type ImageFormData } from "../model/image-interface";
|
||||
import type { WithModePostData } from "../model/posting-interface";
|
||||
import { columns } from "../model/posting-table-columns";
|
||||
import { ImageApi } from "../api/image-service";
|
||||
import { PostingApi } from "../api/posting-service";
|
||||
import { ImageForm } from "./image-form";
|
||||
|
||||
function ModifyPage({ serial }: { serial: string }) {
|
||||
const router = useRouter();
|
||||
const { confirm } = useConfirm();
|
||||
const queryClient = useQueryClient();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const [onConfirm, setOnConfirm] = useState(false);
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
|
||||
const { data: imageDetail } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.IMAGES, serial],
|
||||
queryFn: () => ImageApi.getImageInfo(serial),
|
||||
});
|
||||
|
||||
const { data: postHistory } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.SITE_PSTGS, serial],
|
||||
queryFn: () => PostingApi.getPostingHistory({ pstgTrgtNo: Number(serial) }),
|
||||
});
|
||||
|
||||
const { mutateAsync: updateImage } = useMutation({
|
||||
mutationFn: (data: ImageFormData) => ImageApi.updateImage(serial, data),
|
||||
onSuccess: () => {
|
||||
@@ -33,23 +55,83 @@ function ModifyPage({ serial }: { serial: string }) {
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: requestPosting } = useMutation({
|
||||
mutationFn: (data: WithModePostData[]) => PostingApi.requestPosting(data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.SITE_PSTGS, serial],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<ImageFormData>({
|
||||
resolver: zodResolver(imageFormSchema),
|
||||
values: imageDetail,
|
||||
});
|
||||
|
||||
const table = useReactTable({
|
||||
data: postHistory?.content ?? [],
|
||||
columns,
|
||||
state: {
|
||||
rowSelection,
|
||||
},
|
||||
enableMultiRowSelection: true,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
onRowSelectionChange: setRowSelection,
|
||||
});
|
||||
|
||||
const handleDeletePostingHistory = async () => {
|
||||
const data = table.getFilteredSelectedRowModel().flatRows.map((row) => ({
|
||||
...row.original,
|
||||
mode: "D",
|
||||
}));
|
||||
|
||||
setOnConfirm(true);
|
||||
if (await confirm("삭제하시겠습니까?")) {
|
||||
setOnConfirm(false);
|
||||
await requestPosting(data);
|
||||
alert("삭제되었습니다.");
|
||||
}
|
||||
setOnConfirm(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="card card-border !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">
|
||||
<div className="card-header">
|
||||
<h3 className="text-2xl font-medium text-label">이미지 수정</h3>
|
||||
</div>
|
||||
<ImageForm
|
||||
form={form}
|
||||
imgSn={serial}
|
||||
handleSave={updateImage}
|
||||
handleDelete={deleteImage}
|
||||
/>
|
||||
</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().flatRows.length}
|
||||
onClick={handleDeletePostingHistory}
|
||||
>
|
||||
이력삭제
|
||||
</Button>
|
||||
</div>
|
||||
<DataTable table={table} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ImageForm
|
||||
form={form}
|
||||
imgSn={serial}
|
||||
handleSave={updateImage}
|
||||
handleDelete={deleteImage}
|
||||
/>
|
||||
</div>
|
||||
<ConfirmDialog open={onConfirm} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,7 @@ function ContentSearchDialog({
|
||||
|
||||
const { data: contentList, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.CONTENTS],
|
||||
queryFn: () =>
|
||||
ContentApi.getContentList({ contsTtl, useYn: "Y", page: 0, size: 100 }),
|
||||
queryFn: () => ContentApi.getContentList({ contsTtl }),
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ function MenuPage() {
|
||||
setOnConfirm(false);
|
||||
deleteMenu(selectedMenu!.menuCd!);
|
||||
}
|
||||
setOnConfirm(false);
|
||||
};
|
||||
|
||||
const handleAddMenu = () => {
|
||||
|
||||
@@ -90,6 +90,7 @@ function IPManagementDialog({
|
||||
await mutateAsync(data.ips);
|
||||
alert("저장되었습니다.");
|
||||
}
|
||||
setOnConfirm(false);
|
||||
};
|
||||
|
||||
const handleAddIP = () => {
|
||||
|
||||
@@ -21,6 +21,7 @@ export const ENDPOINT = {
|
||||
CONTENTS: "/cms-service/api/v1/contents",
|
||||
USER_OGNZ: "/cms-service/api/v1/user-ognz",
|
||||
IMAGES: "/cms-service/api/v1/images",
|
||||
SITE_PSTGS: "/cms-service/api/v1/site-pstgs",
|
||||
},
|
||||
BOARD_SERVICE: {
|
||||
BBS: "/board-service/api/v1/bbs",
|
||||
|
||||
Reference in New Issue
Block a user