From 5b376b83d1c2cd0088bb3d0e871c0fe1bd3ba548 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Wed, 3 Sep 2025 12:05:52 +0330 Subject: [PATCH] access logs detail --- src/pages/accessLogs/AccessLogsList.tsx | 61 ++- .../accessLogs/components/AccessLogsTable.tsx | 5 +- .../accessLogs/components/LogDetailsModal.tsx | 410 ++++++++++-------- .../accessLogs/service/AccessLogService.ts | 8 + 4 files changed, 289 insertions(+), 195 deletions(-) diff --git a/src/pages/accessLogs/AccessLogsList.tsx b/src/pages/accessLogs/AccessLogsList.tsx index a09c968..76bb28d 100644 --- a/src/pages/accessLogs/AccessLogsList.tsx +++ b/src/pages/accessLogs/AccessLogsList.tsx @@ -1,9 +1,9 @@ import React, { useState } from "react"; import { DocumentText, - Refresh, Activity, - InfoCircle + InfoCircle, + Refresh } from "iconsax-react"; import Button from "../../components/Button"; import Pagination from "../../components/Pagination"; @@ -14,7 +14,7 @@ import FilterPanel from "./components/FilterPanel"; import AccessLogsTable from "./components/AccessLogsTable"; import LogDetailsModal from "./components/LogDetailsModal"; import { useAccessLogs, useAccessLogDetail } from "./hooks/useAccessLogs"; -import { AccessLog } from "./types/AccessLogTypes"; +import { AccessLog, OperationType, UserType } from "./types/AccessLogTypes"; const AccessLogsList: React.FC = () => { const { @@ -28,17 +28,32 @@ const AccessLogsList: React.FC = () => { refetch, } = useAccessLogs(); - const { log: selectedLog, fetchLog, clearLog } = useAccessLogDetail(); + const { log: selectedLog, loading: detailLoading, error: detailError, fetchLog, clearLog } = useAccessLogDetail(); const [isDetailsModalOpen, setIsDetailsModalOpen] = useState(false); + const [directLog, setDirectLog] = useState(null); const handleViewDetails = async (log: AccessLog) => { - await fetchLog(log.id); - setIsDetailsModalOpen(true); + try { + setIsDetailsModalOpen(true); + // اگر لاگ کامل است (مثل داده‌های نمونه)، مستقیماً نمایش بده + if (log.user !== undefined || log.oldValues !== undefined || log.newValues !== undefined) { + setDirectLog(log); + clearLog(); // پاک کردن selectedLog + } else { + // اگر لاگ از API آمده، جزئیات کامل را دریافت کن + setDirectLog(null); + await fetchLog(log.id); + } + } catch (error) { + console.error('خطا در دریافت جزئیات لاگ:', error); + // مودال باز می‌ماند تا خطا نمایش داده شود + } }; const handleCloseDetailsModal = () => { setIsDetailsModalOpen(false); clearLog(); + setDirectLog(null); }; const handleSort = (field: string, order: "ASC" | "DESC") => { @@ -80,6 +95,36 @@ const AccessLogsList: React.FC = () => {
+ diff --git a/src/pages/accessLogs/components/LogDetailsModal.tsx b/src/pages/accessLogs/components/LogDetailsModal.tsx index 60deb6d..b65eb15 100644 --- a/src/pages/accessLogs/components/LogDetailsModal.tsx +++ b/src/pages/accessLogs/components/LogDetailsModal.tsx @@ -26,14 +26,18 @@ interface LogDetailsModalProps { log: AccessLog | null; isOpen: boolean; onClose: () => void; + loading?: boolean; + error?: string | null; } const LogDetailsModal: React.FC = ({ log, isOpen, onClose, + loading = false, + error = null, }) => { - if (!log) return null; + if (!isOpen) return null; const getOperationTypeColor = (type: OperationType): string => { const colors = { @@ -154,209 +158,245 @@ const LogDetailsModal: React.FC = ({
- {/* Basic Information */} -
- } - label="نوع عملیات" - value={ - - } - /> + {/* Loading State */} + {loading && ( +
+
+
+

در حال بارگذاری جزئیات...

+
+
+ )} - } - label="نوع کاربر" - value={ - - {UserTypeLabels[log.userType]} - - } - /> - - } - label="موجودیت" - value={ + {/* Error State */} + {error && ( +
+
+
-
{log.entityName}
- {log.entityId && ( -
{log.entityId}
- )} +

خطا در بارگذاری

+

{error}

- } - /> +
+
+ )} - } - label="تاریخ و زمان" - value={formatDate(log.createdAt)} - /> + {/* Content - Only show if not loading and no error */} + {!loading && !error && log && ( + <> + {/* Basic Information */} +
+ } + label="نوع عملیات" + value={ + + } + /> - {log.actionDescription && ( - } - label="توضیحات عملیات" - value={log.actionDescription} - fullWidth - /> - )} -
- - {/* User Information */} - {log.user && ( -
-

- - اطلاعات کاربر -

-
} - label="نام و نام خانوادگی" - value={`${log.user.firstName} ${log.user.lastName}`} + label="نوع کاربر" + value={ + + {UserTypeLabels[log.userType]} + + } /> - } - label="ایمیل" - value={log.user.email} - /> - {log.user.phone && ( - } - label="شماره تماس" - value={log.user.phone} - /> - )} - } - label="شناسه کاربر" - value={log.user.id} - /> -
-
- )} - {/* Technical Details */} -
-

- - جزئیات فنی -

-
- {log.ipAddress && ( } - label="آدرس IP" - value={log.ipAddress} + icon={} + label="موجودیت" + value={ +
+
{log.entityName}
+ {log.entityId && ( +
{log.entityId}
+ )} +
+ } /> - )} - {log.endpoint && ( - } - label="Endpoint" - value={log.endpoint} - /> - )} - - {log.httpMethod && ( - } - label="متد HTTP" - value={HttpMethodLabels[log.httpMethod]} - /> - )} - - } - label="کد وضعیت" - value={ - - {log.statusCode || "N/A"} - - } - /> - - {log.executionTime && ( } - label="زمان اجرا" - value={formatExecutionTime(log.executionTime)} + label="تاریخ و زمان" + value={formatDate(log.createdAt)} /> - )} - {log.sessionId && ( - } - label="شناسه جلسه" - value={log.sessionId} - /> - )} - - {log.requestId && ( - } - label="شناسه درخواست" - value={log.requestId} - /> - )} -
-
- - {/* Error Information */} - {log.errorMessage && ( -
-

- - اطلاعات خطا -

-
-

{log.errorMessage}

+ {log.actionDescription && ( + } + label="توضیحات عملیات" + value={log.actionDescription} + fullWidth + /> + )}
+ + {/* User Information */} + {log.user && ( +
+

+ + اطلاعات کاربر +

+
+ } + label="نام و نام خانوادگی" + value={`${log.user.firstName} ${log.user.lastName}`} + /> + } + label="ایمیل" + value={log.user.email} + /> + {log.user.phone && ( + } + label="شماره تماس" + value={log.user.phone} + /> + )} + } + label="شناسه کاربر" + value={log.user.id} + /> +
+
+ )} + + {/* Technical Details */} +
+

+ + جزئیات فنی +

+
+ {log.ipAddress && ( + } + label="آدرس IP" + value={log.ipAddress} + /> + )} + + {log.endpoint && ( + } + label="Endpoint" + value={log.endpoint} + /> + )} + + {log.httpMethod && ( + } + label="متد HTTP" + value={HttpMethodLabels[log.httpMethod]} + /> + )} + + } + label="کد وضعیت" + value={ + + {log.statusCode || "N/A"} + + } + /> + + {log.executionTime && ( + } + label="زمان اجرا" + value={formatExecutionTime(log.executionTime)} + /> + )} + + {log.sessionId && ( + } + label="شناسه جلسه" + value={log.sessionId} + /> + )} + + {log.requestId && ( + } + label="شناسه درخواست" + value={log.requestId} + /> + )} +
+
+ + {/* Error Information */} + {log.errorMessage && ( +
+

+ + اطلاعات خطا +

+
+

{log.errorMessage}

+
+
+ )} + + {/* User Agent */} + {log.userAgent && ( + } + label="User Agent" + value={ +
+ {log.userAgent} +
+ } + fullWidth + /> + )} + + {/* Data Changes */} +
+ + +
+ + {/* Metadata */} + {log.metadata && Object.keys(log.metadata).length > 0 && ( + + )} + + {/* Footer */} +
+ +
+ + )} + + {/* No Data State */} + {!loading && !error && !log && ( +
+ +

هیچ داده‌ای برای نمایش وجود ندارد

)} - - {/* User Agent */} - {log.userAgent && ( - } - label="User Agent" - value={ -
- {log.userAgent} -
- } - fullWidth - /> - )} - - {/* Data Changes */} -
- - -
- - {/* Metadata */} - {log.metadata && Object.keys(log.metadata).length > 0 && ( - - )} - - {/* Footer */} -
- -
); diff --git a/src/pages/accessLogs/service/AccessLogService.ts b/src/pages/accessLogs/service/AccessLogService.ts index 68a2563..60e0336 100644 --- a/src/pages/accessLogs/service/AccessLogService.ts +++ b/src/pages/accessLogs/service/AccessLogService.ts @@ -79,6 +79,14 @@ class AccessLogsService { // Get specific log by ID async getLogById(id: string): Promise<{ accessLog: AccessLog }> { const response = await axios.get(`${this.baseUrl}/${id}`); + + // Handle the nested data structure + if (response.data.data && response.data.data.accessLog) { + return { + accessLog: response.data.data.accessLog, + }; + } + return response.data; }