import { useState, useMemo } from 'react' import { AdminLayout } from '../Admin' import { Badge } from '../../../design-system/primitives/Badge/Badge' import { DateRangePicker } from '../../../design-system/primitives/DateRangePicker/DateRangePicker' import { Input } from '../../../design-system/primitives/Input/Input' import { Select } from '../../../design-system/primitives/Select/Select' import { MonoText } from '../../../design-system/primitives/MonoText/MonoText' import { CodeBlock } from '../../../design-system/primitives/CodeBlock/CodeBlock' import { DataTable } from '../../../design-system/composites/DataTable/DataTable' import type { Column } from '../../../design-system/composites/DataTable/types' import type { DateRange } from '../../../design-system/utils/timePresets' import { AUDIT_EVENTS, type AuditEvent } from './auditMocks' import styles from './AuditLog.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' }, ] 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, }) } 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) => ( ), }, ] const now = Date.now() const INITIAL_RANGE: DateRange = { from: new Date(now - 7 * 24 * 3600_000).toISOString().slice(0, 16), to: new Date(now).toISOString().slice(0, 16), } export function AuditLog() { const [dateRange, setDateRange] = useState(INITIAL_RANGE) const [userFilter, setUserFilter] = useState('') const [categoryFilter, setCategoryFilter] = useState('') const [searchFilter, setSearchFilter] = useState('') const filtered = useMemo(() => { const from = new Date(dateRange.from).getTime() const to = new Date(dateRange.to).getTime() return AUDIT_EVENTS.filter((e) => { const ts = new Date(e.timestamp).getTime() if (ts < from || ts > to) return false if (userFilter && !e.username.toLowerCase().includes(userFilter.toLowerCase())) return false if (categoryFilter && e.category !== categoryFilter) return false if (searchFilter) { const q = searchFilter.toLowerCase() if (!e.action.toLowerCase().includes(q) && !e.target.toLowerCase().includes(q)) return false } return true }) }, [dateRange, userFilter, categoryFilter, searchFilter]) return (
setUserFilter(e.target.value)} onClear={() => setUserFilter('')} className={styles.filterInput} /> setSearchFilter(e.target.value)} onClear={() => setSearchFilter('')} className={styles.filterInput} />
Audit Log
{filtered.length} events
row.result === 'FAILURE' ? 'error' : undefined} expandedContent={(row) => (
IP Address {row.ipAddress}
User Agent {row.userAgent}
Detail
)} />
) }