import { useState } from 'react' import { Badge, DataTable, EmptyState, ErrorState, PageHeader, Skeleton, Toolbar } from '@sims/ui' import { getAudit, getEmployees, type AuditPage, type Employee } from '../api' import { useData } from './Clients' const PAGE_SIZE = 50 /** Compact before→after diff of the changed keys in an audit row. */ function diff(before: string | null, after: string | null): string { const b = before !== null ? JSON.parse(before) as Record : {} const a = after !== null ? JSON.parse(after) as Record : {} const keys = [...new Set([...Object.keys(b), ...Object.keys(a)])] const changed = keys.filter((k) => JSON.stringify(b[k]) !== JSON.stringify(a[k])) if (changed.length === 0) return before === null && after !== null ? 'created' : after === null ? '' : '—' return changed.slice(0, 6).map((k) => `${k}: ${JSON.stringify(a[k] ?? b[k])}`).join(', ') } /** Audit log viewer (D27, owner-only): who did what, filterable + paginated. */ export function Audit() { const [entity, setEntity] = useState('') const [action, setAction] = useState('') const [page, setPage] = useState(1) const list = useData( () => getAudit({ entity, action, page, pageSize: PAGE_SIZE }), [entity, action, page]) const emps = useData<{ employees: Employee[]; total: number } | undefined>(() => getEmployees(), []) const nameOf = (id: string) => id === 'system' ? 'system' : (emps.data?.employees.find((e) => e.id === id)?.displayName ?? id.slice(0, 8)) const data = list.data const totalPages = data !== undefined ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1 return (
{data !== undefined && {data.total} entries} {list.error !== undefined ? : data === undefined ? : data.rows.length === 0 ? No audit entries match. : ( <> ({ when: r.at_wall.replace('T', ' ').slice(0, 19), who: nameOf(r.user_id), action: {r.action}, entity: {r.entity}, change: {diff(r.before_json, r.after_json)}, }))} /> Page {data.page} / {totalPages} )}
) }