import { useState, useEffect, useMemo } from "react"; import { Loader2, User, ArrowRight } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { auditLogService } from "@/services/audit-log-service"; import type { AuditLog } from "@/types/audit-log"; import { useAppSelector } from "@/hooks/redux-hooks"; import { useAppTheme } from "@/hooks/useAppTheme"; import { cn } from "@/lib/utils"; import { StatusBadge, DataTable, type Column } from "@/components/shared"; import { Button } from "@/components/ui/button"; // Helper functions const formatRelativeTime = (dateString: string): string => { const date = new Date(dateString); const now = new Date(); const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); if (diffInSeconds < 60) return "Just now"; const diffInMinutes = Math.floor(diffInSeconds / 60); if (diffInMinutes < 60) return `${diffInMinutes} min ago`; const diffInHours = Math.floor(diffInMinutes / 60); if (diffInHours < 24) return `${diffInHours} hours ago`; const diffInDays = Math.floor(diffInHours / 24); if (diffInDays === 1) return "Yesterday"; return date.toLocaleDateString(); }; const getStatusColor = (status: number | null): string => { if (!status) return "text-[#6b7280]"; if (status >= 200 && status < 300) return "text-[#10b981]"; if (status >= 400) return "text-[#ef4444]"; return "text-[#f59e0b]"; }; const getMethodVariant = ( method: string | null, ): "success" | "failure" | "info" | "process" => { if (!method) return "info"; const upperMethod = method.toUpperCase(); if (upperMethod === "GET") return "success"; if (upperMethod === "POST") return "info"; if (upperMethod === "PUT" || upperMethod === "PATCH") return "process"; if (upperMethod === "DELETE") return "failure"; return "info"; }; export interface RecentActivityProps { variant?: "list" | "table"; } export const RecentActivity = ({ variant }: RecentActivityProps) => { const { primaryColor } = useAppTheme(); const [auditLogs, setAuditLogs] = useState([]); const [isLoading, setIsLoading] = useState(true); const { tenantId, roles } = useAppSelector((state) => state.auth); const navigate = useNavigate(); const auditLogPath = roles?.includes("super_admin") ? "/audit-logs" : "/tenant/audit-logs"; // Default to table variant for a more professional look const activeVariant = variant || "table"; useEffect(() => { const fetchRecentActivity = async (): Promise => { try { setIsLoading(true); const response = await auditLogService.getMyLogs(1, 5); if (response.success) { setAuditLogs(response.data); } } catch (err: any) { console.error("Failed to fetch recent activity:", err); } finally { setIsLoading(false); } }; fetchRecentActivity(); }, [tenantId, activeVariant]); const columns = useMemo[]>(() => [ { key: "created_at", label: "Timestamp", render: (log) => ( {formatRelativeTime(log.created_at)} ), }, { key: "resource_type", label: "Resource Type", render: (log) => ( {log.resource_type} ), }, { key: "request_method", label: "Method", render: (log) => ( {log.request_method || "N/A"} ), }, { key: "response_status", label: "Status", render: (log) => ( {log.response_status || "---"} ), }, { key: "ip_address", label: "IP Address", render: (log) => ( {log.ip_address || "---"} ), }, ], [primaryColor]); if (activeVariant === "list") { return (

Recent Activity

{isLoading ? (
) : auditLogs.length === 0 ? (
No recent activity
) : (
{auditLogs.map((log, index) => (
{formatRelativeTime(log.created_at)}
{log.action} {log.resource_type}
))}
)}
); } // TABLE VARIANT return (

Recent Activity

log.id} isLoading={isLoading} emptyMessage="No recent activity recorded" />
); };