"use client"; import { useState, useEffect } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { Loader2, Filter, Calendar } from "lucide-react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; interface AuditLog { id: string; timestamp: string; user_id: string | null; user_email: string | null; user_name: string | null; action: string; resource: string; resource_id: string | null; details: Record | null; ip_address: string | null; } interface Pagination { page: number; limit: number; total: number; totalPages: number; } interface Filters { actions: string[]; resources: string[]; } const actionColors: Record = { create: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200", update: "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200", delete: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200", sign_in: "bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200", sign_out: "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200", sign_in_failed: "bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200", ban: "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200", unban: "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200", role_change: "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200", }; export function AuditLogTable() { const router = useRouter(); const searchParams = useSearchParams(); const [logs, setLogs] = useState([]); const [pagination, setPagination] = useState(null); const [filters, setFilters] = useState({ actions: [], resources: [] }); const [isLoading, setIsLoading] = useState(true); const [actionFilter, setActionFilter] = useState(searchParams.get("action") || "all"); const [resourceFilter, setResourceFilter] = useState(searchParams.get("resource") || "all"); async function fetchLogs() { setIsLoading(true); try { const params = new URLSearchParams(); if (actionFilter && actionFilter !== "all") params.set("action", actionFilter); if (resourceFilter && resourceFilter !== "all") params.set("resource", resourceFilter); params.set("page", searchParams.get("page") || "1"); const response = await fetch(`/api/admin/audit-log?${params.toString()}`); if (!response.ok) throw new Error("Failed to fetch audit logs"); const data = await response.json(); setLogs(data.logs); setPagination(data.pagination); setFilters(data.filters); } catch (error) { console.error("Error fetching audit logs:", error); } finally { setIsLoading(false); } } useEffect(() => { fetchLogs(); }, [searchParams]); function handleFilterChange(type: "action" | "resource", value: string) { const params = new URLSearchParams(searchParams.toString()); if (value && value !== "all") { params.set(type, value); } else { params.delete(type); } params.set("page", "1"); if (type === "action") setActionFilter(value); if (type === "resource") setResourceFilter(value); router.push(`/admin/audit-log?${params.toString()}`); } function formatAction(action: string): string { return action.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); } return (
{/* Filters */}
{/* Table */}
Timestamp User Action Resource Details IP Address {isLoading ? ( ) : logs.length === 0 ? ( No audit logs found ) : ( logs.map((log) => ( {new Date(log.timestamp).toLocaleString()} {log.user_name || log.user_email || "System"} {formatAction(log.action)} {log.resource} {log.details ? (
                            {JSON.stringify(log.details, null, 2)}
                          
) : ( "-" )}
{log.ip_address || "-"}
)) )}
{/* Pagination */} {pagination && pagination.totalPages > 1 && (

Showing {(pagination.page - 1) * pagination.limit + 1} to{" "} {Math.min(pagination.page * pagination.limit, pagination.total)} of{" "} {pagination.total} entries

)}
); }