feat: 파일관리 페이지 작업
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
import { FilePage } from "@/pages/file";
|
||||
export default FilePage;
|
||||
@@ -2,11 +2,23 @@ import { client } from "@/shared/api";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import type {
|
||||
Attachment,
|
||||
AttachmentList,
|
||||
AttachmentParams,
|
||||
AttachmentService,
|
||||
} from "../model/attachment-interface";
|
||||
|
||||
export class AttachmentApiService implements AttachmentService {
|
||||
public async getAttachments(atflCd: string): Promise<Attachment[]> {
|
||||
public async getAttachmentsList(
|
||||
params: AttachmentParams,
|
||||
): Promise<AttachmentList> {
|
||||
const response = await client.get<AttachmentList>(
|
||||
`${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}`,
|
||||
{ params },
|
||||
);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
public async getAttachmentsInfo(atflCd: string): Promise<Attachment[]> {
|
||||
const response = await client.get<Attachment[]>(
|
||||
`${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}/${atflCd}`,
|
||||
);
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
import type { PageableList, PageableParams } from "@/shared/model";
|
||||
|
||||
export interface AttachmentParams extends PageableParams {
|
||||
keywordType?: string;
|
||||
keyword?: string;
|
||||
atflCd?: string;
|
||||
atflSn?: number;
|
||||
atflId?: string;
|
||||
orgnlFileNm?: string;
|
||||
atflFlieSz?: number;
|
||||
atflType?: string;
|
||||
dwnldNocs?: number;
|
||||
delYn?: string;
|
||||
lnkgDmnId?: string;
|
||||
lnkgDmnNm?: string;
|
||||
}
|
||||
|
||||
export interface Attachment {
|
||||
atflCd: string;
|
||||
atflSn: number;
|
||||
@@ -13,8 +30,11 @@ export interface Attachment {
|
||||
regDt: string;
|
||||
}
|
||||
|
||||
export type AttachmentList = PageableList<Attachment>;
|
||||
|
||||
export interface AttachmentService {
|
||||
getAttachments: (atflCd: string) => Promise<Attachment[]>;
|
||||
getAttachmentsList: (params: AttachmentParams) => Promise<AttachmentList>;
|
||||
getAttachmentsInfo: (atflCd: string) => Promise<Attachment[]>;
|
||||
deleteAttachment: (atflId: string) => Promise<void>;
|
||||
deleteAttachmentByAtflCd: (atflCd: string) => Promise<void>;
|
||||
getImageUrl: (atflId: string) => Promise<string>;
|
||||
|
||||
@@ -44,7 +44,7 @@ function BannerForm({ form, bnrSn, ...props }: BannerFormProps) {
|
||||
|
||||
const { data: attachmentData } = useQuery({
|
||||
queryKey: [ENDPOINT.ATTACH_SERVICE.ATTACHMENTS, atflCd],
|
||||
queryFn: () => AttachmentApi.getAttachments(atflCd!),
|
||||
queryFn: () => AttachmentApi.getAttachmentsInfo(atflCd!),
|
||||
select: (data) => data?.[data.length - 1],
|
||||
enabled: !!atflCd,
|
||||
});
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { FilePage } from "./ui/file-page";
|
||||
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import dayjs from "dayjs";
|
||||
import { type ColumnDef } from "@tanstack/react-table";
|
||||
import { Button } from "@common/components";
|
||||
import type { Attachment } from "@/entities/attachment/model/attachment-interface";
|
||||
|
||||
export const columns = (
|
||||
handleDeleteAttachment: (atflId: string) => void,
|
||||
): ColumnDef<Attachment>[] => [
|
||||
{
|
||||
id: "no",
|
||||
header: "NO",
|
||||
cell: (info) => info.row.index + 1,
|
||||
},
|
||||
{
|
||||
accessorKey: "atflId",
|
||||
header: "파일ID",
|
||||
},
|
||||
{
|
||||
accessorKey: "atflSn",
|
||||
header: "파일순번",
|
||||
},
|
||||
{
|
||||
accessorKey: "orgnlFileNm",
|
||||
header: "파일명",
|
||||
},
|
||||
{
|
||||
accessorKey: "atflFlieSz",
|
||||
header: "파일크기",
|
||||
},
|
||||
|
||||
{
|
||||
accessorKey: "dwnldNocs",
|
||||
header: "다운로드수",
|
||||
},
|
||||
{
|
||||
accessorKey: "regDt",
|
||||
header: "등록일시",
|
||||
cell: ({ row }) => {
|
||||
const date = row.getValue("regDt") as string;
|
||||
return date ? dayjs(date).format("YYYY-MM-DD") : "";
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "delYn",
|
||||
header: "삭제여부",
|
||||
},
|
||||
{
|
||||
id: "delete",
|
||||
header: "삭제",
|
||||
cell: ({ row }) => (
|
||||
<Button
|
||||
size="sm"
|
||||
color="red"
|
||||
onClick={() => handleDeleteAttachment(row.original.atflId)}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,119 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { keepPreviousData, useMutation, useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
type PaginationState,
|
||||
} from "@tanstack/react-table";
|
||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||
import { Button, DataTable, Input, Label } from "@common/components";
|
||||
import type { AttachmentParams } from "@/entities/attachment/model/attachment-interface";
|
||||
import { AttachmentApi } from "@/entities/attachment/api/attachment-service";
|
||||
import { useAlertStore } from "@/shared/lib/use-alert-store";
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
import { columns } from "../model/table-columns";
|
||||
|
||||
function FilePage() {
|
||||
const { confirm } = useConfirm();
|
||||
const { setMessage: alert } = useAlertStore((state) => state);
|
||||
|
||||
const [attachmentQuery, setAttachmentQuery] = useState<AttachmentParams>({
|
||||
keyword: "",
|
||||
});
|
||||
const [pagination, setPagination] = useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const { data: attachmentsList, refetch } = useQuery({
|
||||
queryKey: [ENDPOINT.ATTACH_SERVICE.ATTACHMENTS],
|
||||
queryFn: () =>
|
||||
AttachmentApi.getAttachmentsList({
|
||||
...attachmentQuery,
|
||||
page: pagination.pageIndex,
|
||||
size: pagination.pageSize,
|
||||
}),
|
||||
placeholderData: keepPreviousData,
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
const { mutate: deleteAttachment } = useMutation({
|
||||
mutationFn: (atflId: string) => AttachmentApi.deleteAttachment(atflId),
|
||||
onSuccess: () => {
|
||||
refetch();
|
||||
alert("삭제되었습니다.");
|
||||
},
|
||||
});
|
||||
|
||||
const handleDeleteAttachment = async (atflId: string) => {
|
||||
if (await confirm("삭제하시겠습니까?")) {
|
||||
deleteAttachment(atflId);
|
||||
}
|
||||
};
|
||||
|
||||
const table = useReactTable({
|
||||
data: attachmentsList?.content ?? [],
|
||||
columns: columns(handleDeleteAttachment),
|
||||
rowCount: attachmentsList?.totalElements ?? 0,
|
||||
state: {
|
||||
pagination,
|
||||
},
|
||||
onPaginationChange: setPagination,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
manualPagination: true,
|
||||
});
|
||||
|
||||
const handleAttachmentQueryChange =
|
||||
(key: keyof AttachmentParams) => (value: string) => {
|
||||
setAttachmentQuery({ ...attachmentQuery, [key]: value });
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
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="keyword" className="text-label">
|
||||
파일명
|
||||
</Label>
|
||||
<Input
|
||||
id="keyword"
|
||||
className="h-[3.2rem] w-[24rem] rounded-sm !text-[1.3rem]"
|
||||
value={attachmentQuery.keyword || ""}
|
||||
onChange={(e) =>
|
||||
handleAttachmentQueryChange("keyword")(e.target.value)
|
||||
}
|
||||
placeholder="파일명을 입력하세요"
|
||||
/>
|
||||
</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>
|
||||
</div>
|
||||
<div className="card !m-[1.2rem] overflow-auto !p-0">
|
||||
<DataTable table={table} viewPagination />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { FilePage };
|
||||
@@ -49,7 +49,7 @@ function ImageForm({ form, imgSn, ...props }: ImageFormProps) {
|
||||
|
||||
const { data: attachmentData } = useQuery({
|
||||
queryKey: [ENDPOINT.ATTACH_SERVICE.ATTACHMENTS, atflCd],
|
||||
queryFn: () => AttachmentApi.getAttachments(atflCd!),
|
||||
queryFn: () => AttachmentApi.getAttachmentsInfo(atflCd!),
|
||||
select: (data) => data?.[data.length - 1],
|
||||
enabled: !!atflCd,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user