import { useState, useMemo } from 'react'; import { Badge, DateRangePicker, Input, Select, MonoText, CodeBlock, DataTable, } from '@cameleer/design-system'; import type { Column } from '@cameleer/design-system'; import { useAuditLog, type AuditEvent } from '../../api/queries/admin/audit'; import styles from './AuditLogPage.module.css'; const CATEGORIES = [ { value: '', label: 'All categories' }, { value: 'INFRA', label: 'INFRA' }, { value: 'AUTH', label: 'AUTH' }, { value: 'USER_MGMT', label: 'USER_MGMT' }, { value: 'CONFIG', label: 'CONFIG' }, { value: 'RBAC', label: 'RBAC' }, ]; function formatTimestamp(iso: string): string { return new Date(iso).toLocaleString('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }); } type AuditRow = Omit & { id: string }; const COLUMNS: Column[] = [ { key: 'timestamp', header: 'Timestamp', width: '170px', sortable: true, render: (_, row) => {formatTimestamp(row.timestamp)}, }, { key: 'username', header: 'User', sortable: true, render: (_, row) => {row.username}, }, { key: 'category', header: 'Category', width: '110px', sortable: true, render: (_, row) => , }, { key: 'action', header: 'Action' }, { key: 'target', header: 'Target', render: (_, row) => {row.target}, }, { key: 'result', header: 'Result', width: '90px', sortable: true, render: (_, row) => ( ), }, ]; export default function AuditLogPage() { const [dateRange, setDateRange] = useState({ start: new Date(Date.now() - 7 * 24 * 3600_000), end: new Date(), }); const [userFilter, setUserFilter] = useState(''); const [categoryFilter, setCategoryFilter] = useState(''); const [searchFilter, setSearchFilter] = useState(''); const [page, setPage] = useState(0); const { data } = useAuditLog({ username: userFilter || undefined, category: categoryFilter || undefined, search: searchFilter || undefined, from: dateRange.start.toISOString(), to: dateRange.end.toISOString(), page, size: 25, }); const rows: AuditRow[] = useMemo( () => (data?.items || []).map((item) => ({ ...item, id: String(item.id) })), [data], ); const totalCount = data?.totalCount ?? 0; return (
{ setDateRange(range); setPage(0); }} /> { setUserFilter(e.target.value); setPage(0); }} onClear={() => { setUserFilter(''); setPage(0); }} className={styles.filterInput} /> { setSearchFilter(e.target.value); setPage(0); }} onClear={() => { setSearchFilter(''); setPage(0); }} className={styles.filterInput} />
Audit Log
{totalCount} events
row.result === 'FAILURE' ? 'error' : undefined} expandedContent={(row) => (
IP Address {row.ipAddress}
User Agent {row.userAgent}
Detail
)} />
); }