import { useState, useEffect, useCallback } from "react"; import { useTranslation } from "react-i18next"; import i18n from "i18next"; import { Card, CardContent, CardHeader, CardTitle, } from "@/shared/common/ui/card"; import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell, } from "@/shared/common/ui/table"; import { Input } from "@/shared/common/ui/input"; import { Button } from "@/shared/common/ui/button"; import { Search, RefreshCw, ChevronLeft, ChevronRight } from "lucide-react"; import { listAuditLogExtensions } from "@/shared/services/audit/audit.api"; interface ActivityLog { id: string; createdAt: string; entityName: string; queryMethod: "INSERT" | "UPDATE" | "DELETE" | string; user: { id: string; name: { am: string; en: string; }; email: string; username?: string; }; } const ITEMS_PER_PAGE = 10; export default function ActivityLogPage() { const { t } = useTranslation(); const [searchQuery, setSearchQuery] = useState(""); const [allLogs, setAllLogs] = useState([]); const [filteredLogs, setFilteredLogs] = useState([]); const [loading, setLoading] = useState(false); const [currentPage, setCurrentPage] = useState(1); const fetchAuditLogs = useCallback(async () => { setLoading(true); try { // Fetch all 1000 records from super admin endpoint const data = await listAuditLogExtensions( "/audit-log-extensions/audit/superAdmin", { skip: 0, take: 1000, orderBy: "createdAt:DESC", } ); const logs = (data.items || []) as ActivityLog[]; setAllLogs(logs); setCurrentPage(1); } catch (error: any) { console.error("Error fetching audit logs:", error); setAllLogs([]); } finally { setLoading(false); } }, []); useEffect(() => { fetchAuditLogs(); // Refresh every 30 seconds const interval = setInterval(fetchAuditLogs, 30000); return () => clearInterval(interval); }, [fetchAuditLogs]); // Paginate the logs whenever currentPage changes useEffect(() => { const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; const endIndex = startIndex + ITEMS_PER_PAGE; let filtered = allLogs.slice(startIndex, endIndex); // Apply search filter if (searchQuery) { filtered = filtered.filter( (log) => log.entityName.toLowerCase().includes(searchQuery.toLowerCase()) || log.user.name.am.toLowerCase().includes(searchQuery.toLowerCase()) || log.user.name.en.toLowerCase().includes(searchQuery.toLowerCase()) || log.user.email.toLowerCase().includes(searchQuery.toLowerCase()), ); } setFilteredLogs(filtered); }, [allLogs, currentPage, searchQuery]); const totalPages = Math.ceil(allLogs.length / ITEMS_PER_PAGE); const hasNextPage = currentPage < totalPages; const hasPrevPage = currentPage > 1; return (
{t("activityLogPage.title")}
setSearchQuery(e.target.value)} className="pl-10" />
{t("activityLogPage.table.time")} {t("activityLogPage.table.description")} {t("activityLogPage.table.performedBy")} {loading ? (
{t("common.loading", "Loading...")}
) : filteredLogs.length > 0 ? ( filteredLogs.map((log) => { const userName = i18n.language === "am" ? log.user.name.am : log.user.name.en; const entityLabel = log.entityName.replace(/_/g, " "); const actionVerb = log.queryMethod.toLowerCase() === "insert" ? "created" : log.queryMethod.toLowerCase() === "update" ? "updated" : log.queryMethod.toLowerCase() === "delete" ? "deleted" : log.queryMethod.toLowerCase(); const timestamp = new Date(log.createdAt).toLocaleString( i18n.language, { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", } ); return ( {timestamp}

{userName} {" "} {actionVerb} {" "} {entityLabel} {" "} at {timestamp}

{userName}

{log.user.email}

); }) ) : ( {t("activityLogPage.table.noLogs")} )}
{/* Pagination Footer */} {allLogs.length > 0 && (
{t("common.showing", "Showing")} {(currentPage - 1) * ITEMS_PER_PAGE + 1}- {Math.min(currentPage * ITEMS_PER_PAGE, allLogs.length)}{" "} {t("common.of", "of")} {allLogs.length}
{currentPage} / {totalPages || 1}
)}
); }