diff --git a/apps/cs/app/(with-base-layout)/file/page.tsx b/apps/cs/app/(with-base-layout)/file/page.tsx new file mode 100644 index 000000000..6b03fe11d --- /dev/null +++ b/apps/cs/app/(with-base-layout)/file/page.tsx @@ -0,0 +1,2 @@ +import { FilePage } from "@/pages/file"; +export default FilePage; diff --git a/apps/cs/src/entities/attachment/api/attachment-service.ts b/apps/cs/src/entities/attachment/api/attachment-service.ts index c930b7012..f956f6580 100644 --- a/apps/cs/src/entities/attachment/api/attachment-service.ts +++ b/apps/cs/src/entities/attachment/api/attachment-service.ts @@ -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 { + public async getAttachmentsList( + params: AttachmentParams, + ): Promise { + const response = await client.get( + `${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}`, + { params }, + ); + return response.data; + } + + public async getAttachmentsInfo(atflCd: string): Promise { const response = await client.get( `${ENDPOINT.ATTACH_SERVICE.ATTACHMENTS}/${atflCd}`, ); diff --git a/apps/cs/src/entities/attachment/model/attachment-interface.ts b/apps/cs/src/entities/attachment/model/attachment-interface.ts index 5986a96d1..5133e4a72 100644 --- a/apps/cs/src/entities/attachment/model/attachment-interface.ts +++ b/apps/cs/src/entities/attachment/model/attachment-interface.ts @@ -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; + export interface AttachmentService { - getAttachments: (atflCd: string) => Promise; + getAttachmentsList: (params: AttachmentParams) => Promise; + getAttachmentsInfo: (atflCd: string) => Promise; deleteAttachment: (atflId: string) => Promise; deleteAttachmentByAtflCd: (atflCd: string) => Promise; getImageUrl: (atflId: string) => Promise; diff --git a/apps/cs/src/pages/banner/ui/banner-form.tsx b/apps/cs/src/pages/banner/ui/banner-form.tsx index 93c550de8..f4af75ffe 100644 --- a/apps/cs/src/pages/banner/ui/banner-form.tsx +++ b/apps/cs/src/pages/banner/ui/banner-form.tsx @@ -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, }); diff --git a/apps/cs/src/pages/file/index.ts b/apps/cs/src/pages/file/index.ts new file mode 100644 index 000000000..4c0093cfc --- /dev/null +++ b/apps/cs/src/pages/file/index.ts @@ -0,0 +1 @@ +export { FilePage } from "./ui/file-page"; diff --git a/apps/cs/src/pages/file/model/table-columns.tsx b/apps/cs/src/pages/file/model/table-columns.tsx new file mode 100644 index 000000000..c3a5385f0 --- /dev/null +++ b/apps/cs/src/pages/file/model/table-columns.tsx @@ -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[] => [ + { + 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 }) => ( + + ), + }, +]; diff --git a/apps/cs/src/pages/file/ui/file-page.tsx b/apps/cs/src/pages/file/ui/file-page.tsx new file mode 100644 index 000000000..a331c6648 --- /dev/null +++ b/apps/cs/src/pages/file/ui/file-page.tsx @@ -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({ + keyword: "", + }); + const [pagination, setPagination] = useState({ + 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) => { + e.preventDefault(); + refetch(); + }; + + useEffect(() => { + refetch(); + }, [pagination]); + + return ( +
+
+
+
+
+ + + handleAttachmentQueryChange("keyword")(e.target.value) + } + placeholder="파일명을 입력하세요" + /> +
+
+ +
+
+
+
+

파일 목록

+
+
+ +
+
+
+ ); +} + +export { FilePage }; diff --git a/apps/cs/src/pages/image/ui/image-form.tsx b/apps/cs/src/pages/image/ui/image-form.tsx index ac3d13832..b334f1858 100644 --- a/apps/cs/src/pages/image/ui/image-form.tsx +++ b/apps/cs/src/pages/image/ui/image-form.tsx @@ -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, });