import { useState, useEffect } from "react"; import { LogIn, LogOut, Key, Fingerprint, Smartphone, AlertTriangle, Loader2, RefreshCw, Users } from "lucide-react"; import { Card, CardContent } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { api, AuditLogEntry } from "@/lib/api"; import { useAuth } from "@/contexts/AuthContext"; // Map audit log action strings to display info const getEventDisplay = (action: string) => { const a = action.toLowerCase(); if (a.includes("login") && a.includes("fail")) { return { icon: , title: "Failed login attempt", failed: true }; } if (a.includes("login") || a.includes("authenticate")) { return { icon: , title: "Signed in", failed: false }; } if (a.includes("logout") || a.includes("sign_out")) { return { icon: , title: "Signed out", failed: false }; } if (a.includes("passkey") || a.includes("webauthn")) { return { icon: , title: "Passkey event", failed: false }; } if (a.includes("mfa") || a.includes("totp") || a.includes("2fa")) { return { icon: , title: "MFA event", failed: false }; } if (a.includes("ssh")) { return { icon: , title: "SSH key event", failed: false }; } return { icon: , title: action.replace(/_/g, " "), failed: !action.includes("success") && a.includes("fail") }; }; export default function ActivityPage() { const { isOrgAdmin } = useAuth(); const [filter, setFilter] = useState("all"); const [view, setView] = useState<"mine" | "org">("mine"); const [events, setEvents] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(""); const loadEvents = () => { setIsLoading(true); setError(""); const req = view === "org" && isOrgAdmin ? api.admin.getAuditLogs({ per_page: "100" }).then((d) => d.audit_logs ?? []) : api.users.auditLogs({ per_page: "50" }).then((d) => d.audit_logs ?? []); req .then((logs) => setEvents(logs)) .catch(() => setError("Failed to load activity. Please try again.")) .finally(() => setIsLoading(false)); }; useEffect(() => { loadEvents(); }, [view]); // eslint-disable-line react-hooks/exhaustive-deps const formatDate = (dateString: string) => { const date = new Date(dateString); return new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", }).format(date); }; const filteredEvents = events.filter((e) => { if (filter === "all") return true; const a = e.action.toLowerCase(); if (filter === "logins") return a.includes("session_create") || a.includes("session_revoke") || a.includes("external_auth") || a.includes("login") || a.includes("logout"); if (filter === "security") return a.includes("mfa") || a.includes("passkey") || a.includes("ssh") || a.includes("totp") || a.includes("password") || a.includes("webauthn"); return true; }); return (

Activity

{view === "org" ? "Organization-wide audit log" : "Your recent account activity and security events"}

{isOrgAdmin && ( setView(v as "mine" | "org")}> My Activity Org Logs )}
{isLoading ? (
) : error ? (

{error}

) : filteredEvents.length === 0 ? (

No activity events found.

) : (
{filteredEvents.map((event) => { const display = getEventDisplay(event.action); return (
{display.icon}

{display.title}

{(!event.success || display.failed) && ( Failed )}
{view === "org" && event.user_id && (

User: {event.user_id}

)} {event.description &&

{event.description}

}
{event.ip_address && ( {event.ip_address} )} {event.user_agent && ( {event.user_agent} )}

{formatDate(event.created_at)}

); })}
)}
); }