From 59afe895e1794972291b375787f11a44f2db6894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=B2=A0?= Date: Fri, 27 Jun 2025 21:55:24 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B0=9C=EC=9D=B8=EC=A0=95=EB=B3=B4=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EA=B7=B8=EA=B7=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../privacylog/api/privacylog-service.ts | 20 ++ apps/cs/src/entities/privacylog/index.ts | 6 + .../privacylog/model/privacylog-interface.ts | 27 +++ .../src/pages/loginlog/ui/loginlog-page.tsx | 25 ++- apps/cs/src/pages/privacylog/index.ts | 1 + .../pages/privacylog/model/table-columns.tsx | 41 ++++ .../pages/privacylog/ui/privacylog-page.tsx | 206 ++++++++++++++++++ apps/cs/src/shared/config/api.ts | 2 + 8 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 apps/cs/src/entities/privacylog/api/privacylog-service.ts create mode 100644 apps/cs/src/entities/privacylog/index.ts create mode 100644 apps/cs/src/entities/privacylog/model/privacylog-interface.ts create mode 100644 apps/cs/src/pages/privacylog/index.ts create mode 100644 apps/cs/src/pages/privacylog/model/table-columns.tsx create mode 100644 apps/cs/src/pages/privacylog/ui/privacylog-page.tsx diff --git a/apps/cs/src/entities/privacylog/api/privacylog-service.ts b/apps/cs/src/entities/privacylog/api/privacylog-service.ts new file mode 100644 index 000000000..4082af038 --- /dev/null +++ b/apps/cs/src/entities/privacylog/api/privacylog-service.ts @@ -0,0 +1,20 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import type { + PrivacyLogList, + PrivacyLogParams, + PrivacyLogService, +} from "../model/privacylog-interface"; + +export class PrivacyLogPrivacyService implements PrivacyLogService { + public async getPrivacyLogList(params: PrivacyLogParams): Promise { + const response = await client.get( + `${ENDPOINT.USER_SERVICE.PRIVACYLOG}`, + { params }, + ); + return response.data; + } + +} + +export const PrivacyLogPrivacy = new PrivacyLogPrivacyService(); diff --git a/apps/cs/src/entities/privacylog/index.ts b/apps/cs/src/entities/privacylog/index.ts new file mode 100644 index 000000000..8f0898922 --- /dev/null +++ b/apps/cs/src/entities/privacylog/index.ts @@ -0,0 +1,6 @@ +export { PrivacyLogPrivacy } from "./api/privacylog-service"; +export type { + PrivacyLog, + PrivacyLogParams, +} from "./model/privacylog-interface"; + diff --git a/apps/cs/src/entities/privacylog/model/privacylog-interface.ts b/apps/cs/src/entities/privacylog/model/privacylog-interface.ts new file mode 100644 index 000000000..d28388445 --- /dev/null +++ b/apps/cs/src/entities/privacylog/model/privacylog-interface.ts @@ -0,0 +1,27 @@ +import type { PageableList, PageableParams } from "@/shared/model"; + +export interface PrivacyLogParams extends PageableParams { + siteId?: string; + rqstrIp?: string; + inqInfoKeywordType?: string; + inqInfoKeyword?: string; + inqDtStart?: string; + inqDtEnd?: string; +} + +export interface PrivacyLog { + inqSn: number; + siteId: string; + siteNm: string; + inqDt: string; + rqstrIp: string; + rqstrId: string; + rqstrNm: string; + inqInfoSummary: string; +} + +export type PrivacyLogList = PageableList; + +export interface PrivacyLogService { + getPrivacyLogList: (params: PrivacyLogParams) => Promise; +} diff --git a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx index 21a6acbcb..058c03db2 100644 --- a/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx +++ b/apps/cs/src/pages/loginlog/ui/loginlog-page.tsx @@ -17,6 +17,7 @@ import { SelectItem, SelectTrigger, SelectValue, + LoadingWithImage, } from "@common/components"; import { LoginlogApi } from "@/entities/loginlog"; import { type LoginlogParams} from "@/entities/loginlog/model/loginlog-interface"; @@ -40,6 +41,7 @@ function LoginlogPage({ }) { }; const [dateRange, setDateRange] = useState(defaultDateRange); + const [isManualLoading, setIsManualLoading] = useState(false); const [pagination, setPagination] = useState({ pageIndex: 0, @@ -89,7 +91,10 @@ function LoginlogPage({ }) { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - query.refetch(); + setIsManualLoading(true); + query.refetch().finally(() => { + setIsManualLoading(false); + }); }; const handleLoginlogParamsChange = @@ -178,8 +183,8 @@ function LoginlogPage({ }) { 오류 - @@ -208,7 +213,19 @@ function LoginlogPage({ }) { -
{tableComponent}
+
+ {/* Debug: 로딩 상태 표시 */} + {(query.isLoading || query.isPending || isManualLoading) && ( +
+
+
+ +
+
+
+ )} + {tableComponent} +
); diff --git a/apps/cs/src/pages/privacylog/index.ts b/apps/cs/src/pages/privacylog/index.ts new file mode 100644 index 000000000..7bbd75042 --- /dev/null +++ b/apps/cs/src/pages/privacylog/index.ts @@ -0,0 +1 @@ +export { PrivacyLogPage } from "./ui/privacylog-page"; diff --git a/apps/cs/src/pages/privacylog/model/table-columns.tsx b/apps/cs/src/pages/privacylog/model/table-columns.tsx new file mode 100644 index 000000000..a5b52d796 --- /dev/null +++ b/apps/cs/src/pages/privacylog/model/table-columns.tsx @@ -0,0 +1,41 @@ +import dayjs from "dayjs"; +import type { ColumnDef } from "@tanstack/react-table"; +import type { PrivacyLog } from "@/entities/privacylog"; + + +export const columns: ColumnDef[] = [ + { + id: "no", + header: "NO", + cell: ({ row, table }) => { + const totalRows = table.getRowCount(); + const { pageIndex, pageSize } = table.getState().pagination; + return totalRows - (pageIndex * pageSize + row.index); + }, + }, + { + accessorKey: "inqDt", + header: "요청일시", + cell: ({ row }) => { + const date = dayjs(row.original.inqDt); + return date.format("YYYY-MM-DD HH:mm:ss"); + }, + }, + { + accessorKey: "siteNm", + header: "사이트명", + }, + { + accessorKey: "rqstrNm", + header: "조회자명", + }, + { + accessorKey: "rqstrIp", + header: "조회IP", + }, + { + accessorKey: "inqInfoSummary", + header: "조회정보", + } +]; + diff --git a/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx new file mode 100644 index 000000000..9feea8a02 --- /dev/null +++ b/apps/cs/src/pages/privacylog/ui/privacylog-page.tsx @@ -0,0 +1,206 @@ +"use client"; + +import dayjs from "dayjs"; +import { useState } from "react"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; +import { + getCoreRowModel, + type PaginationState, +} from "@tanstack/react-table"; +import { + Button, + DateRangePicker, + Input, + Label, + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@common/components"; +import { PrivacyLogPrivacy } from "@/entities/privacylog"; +import { type PrivacyLogParams} from "@/entities/privacylog/model/privacylog-interface"; +import { useDataTable } from "@/shared/lib"; +import { ENDPOINT } from "@/shared/config"; +import { columns } from "@/pages/privacylog/model/table-columns"; + + + +type DateRange = { + from: Date | undefined; + to?: Date | undefined; +}; + +function PrivacyLogPage({ }) { + + // 1주일 전부터 오늘까지 기본 날짜 설정 + const defaultDateRange: DateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + + const [dateRange, setDateRange] = useState(defaultDateRange); + + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: 10, + }); + + const [privacylogPostQuery, setprivacylogPostQuery] = useState< PrivacyLogParams>({ + siteId: "", + inqInfoKeywordType: "userName", + inqInfoKeyword: "", + rqstrIp: "", + inqDtStart: dayjs().subtract(7, "day").format("YYYY-MM-DD"), + inqDtEnd: dayjs().format("YYYY-MM-DD"), + sort:"inqDt,asc" + }); + + + const query = useQuery({ + queryKey: [ENDPOINT.USER_SERVICE.PRIVACYLOG, pagination], + queryFn: () => + PrivacyLogPrivacy.getPrivacyLogList({ + ...privacylogPostQuery, + page: pagination.pageIndex, + size: pagination.pageSize, + }), + placeholderData: keepPreviousData, + }); + + const { tableComponent, tableInstance: table } = useDataTable({ + query, + tableOptions: { + columns, + state: { + pagination, + }, + manualPagination: true, + enableMultiRowSelection: true, + getCoreRowModel: getCoreRowModel(), + onPaginationChange: setPagination, + }, + dataTableOptions: { + viewPagination: true, + }, + }); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + query.refetch(); + }; + + const handleprivacylogParamsChange = + (key: keyof PrivacyLogParams) => (value: unknown) => { + setprivacylogPostQuery({ ...privacylogPostQuery, [key]: value }); + }; + + const handlePresetDateRange = (value: string) => { + let presetDateRange: DateRange | undefined; + switch (value) { + case "1W": + presetDateRange = { + from: dayjs().subtract(7, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "1M": + presetDateRange = { + from: dayjs().subtract(30, "day").toDate(), + to: dayjs().toDate(), + }; + break; + case "3M": + presetDateRange = { + from: dayjs().subtract(90, "day").toDate(), + to: dayjs().toDate(), + }; + break; + default: + presetDateRange = undefined; + } + handleDateRangeChange(presetDateRange); + }; + + + + const handleDateRangeChange = (value: DateRange | undefined) => { + setDateRange(value || defaultDateRange); + setprivacylogPostQuery({ + ...privacylogPostQuery, + inqDtStart: dayjs(value?.from).format("YYYY-MM-DD") ?? dayjs().subtract(7, "day").format("YYYY-MM-DD"), + inqDtEnd: dayjs(value?.to).format("YYYY-MM-DD") ?? dayjs().format("YYYY-MM-DD"), + }); + }; + + + + + return ( +
+
+
+ + +
+ +
+
+ + + handleprivacylogParamsChange("inqInfoKeyword")(e.target.value) + } + /> + + +
+
+
+
+
+

로그인로그 목록

+
+ +
+
+
+
{tableComponent}
+
+
+ ); +} + +export {PrivacyLogPage }; diff --git a/apps/cs/src/shared/config/api.ts b/apps/cs/src/shared/config/api.ts index b23268e66..ac0f18eca 100644 --- a/apps/cs/src/shared/config/api.ts +++ b/apps/cs/src/shared/config/api.ts @@ -21,6 +21,8 @@ export const ENDPOINT = { ROLES: "/user-service/api/v1/roles", LOGINLOG: "/user-service/api/v1/login-logs", APILOG: "/user-service/api/v1/api-logs", + PRIVACYLOG: "/user-service//api/v1/prvc-inq-logs", + }, CMS_SERVICE: { SITES: "/cms-service/api/v1/sites",