SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
2.2 KB · 36 lines tsx
Raw Blame History
1import Link from 'next/link';2import { requireAdmin } from '@/lib/admin/auth';3import { auditLog } from '@/lib/admin/queries';4import { AdminShell, fmtTs } from '@/components/admin/shell';5import { Table, th, td } from '@/components/ui/primitives';67const TYPES = ['', 'sale', 'listing', 'asset', 'connector', 'normalized_record', 'taxonomy_proposal'];89export default async function AuditPage({ searchParams }: { searchParams: Promise<{ type?: string }> }) {10  await requireAdmin();11  const sp = await searchParams;12  const rows = await auditLog({ entityType: sp.type || undefined });13  return (14    <AdminShell current="/admin/audit" title="Audit log" subtitle="Every flag, exclusion, restore, merge, edit and admin decision — the platform never silently deletes data" actions={<div className="flex flex-wrap gap-1 text-xs">{TYPES.map((t) => <Link key={t} href={`/admin/audit${t ? `?type=${t}` : ''}`} className={`rounded-md border px-2 py-1 ${(sp.type ?? '') === t ? 'border-accent bg-accent text-accent-fg' : 'border-border hover:bg-inset'}`}>{t || 'all'}</Link>)}</div>}>15      <div className="card">16        <Table>17          <thead><tr><th className={th}>When</th><th className={th}>Entity</th><th className={th}>Action</th><th className={th}>Actor</th><th className={th}>Reason</th><th className={th}>Details</th></tr></thead>18          <tbody>19            {rows.length === 0 ? <tr><td className={td} colSpan={6}><span className="text-subtle">No audit entries.</span></td></tr> : null}20            {rows.map((r) => (21              <tr key={String(r.id)} className="align-top">22                <td className={td}>{fmtTs(r.created_at)}</td>23                <td className={`${td} font-mono text-[11px]`}>{String(r.entity_type)}<br />{String(r.entity_id)}</td>24                <td className={td}>{String(r.action)}</td>25                <td className={td}>{String(r.actor)}</td>26                <td className={`${td} max-w-[320px] whitespace-normal`}>{String(r.reason)}</td>27                <td className={`${td} max-w-[320px] whitespace-normal font-mono text-[10px] text-muted`}>{JSON.stringify(r.details)}</td>28              </tr>29            ))}30          </tbody>31        </Table>32      </div>33    </AdminShell>34  );35}36