"use client";
import { useState } from "react";
import { RefreshCw } from "lucide-react";
import { api, type AuditRow } from "@/lib/api";
import { useAsync, useDebounced } from "@/lib/hooks";
import { useAuth } from "@/lib/auth";
import { fmtInt, fmtTs } from "@/lib/format";
import { Banner, Card, ErrorState, Field, PageHeader, StatusBadge } from "@/components/ui";
import { DataTable } from "@/components/DataTable";
import { JsonView } from "@/components/JsonView";
const ACTIONS = ["", "auth.", "auth.login", "auth.mfa", "admin.", "admin.enqueue", "admin.key_create", "admin.key_revoke", "export.", "query.sql"];
const HIDDEN = new Set(["id", "at", "action", "actor", "principal", "target", "outcome", "ip", "request_id", "detail", "user_agent"]);
export default function AuditPage() {
const { isOwner } = useAuth();
const [action, setAction] = useState("");
const [limit, setLimit] = useState(200);
const da = useDebounced(action.trim(), 300);
const { data, error, loading, reload } = useAsync((s) => api.get<{ data: AuditRow[] }>("/admin/audit", { action: da || undefined, limit }, s), [da, limit], { enabled: isOwner });
if (!isOwner) return The audit log is restricted to the owner.;
return (
<>
setAction(e.target.value)} placeholder="admin." />
>
}
/>
{error && }
String(r.id ?? `${r.at}-${i}`)}
mobile="cards"
maxHeight="75dvh"
columns={[
{ key: "at", header: "At (UTC)", render: (r) => {fmtTs(r.at)} },
{ key: "action", header: "Action", mono: true },
{ key: "actor", header: "Actor", render: (r) => {String(r.actor ?? r.principal ?? "—")} },
{ key: "target", header: "Target", render: (r) => {r.target ?? "—"} },
{ key: "outcome", header: "Outcome", render: (r) => (r.outcome ? : —) },
{ key: "ip", header: "IP", hideSm: true, mono: true },
{
key: "detail",
header: "Detail",
render: (r) => {
const d = r.detail ?? Object.fromEntries(Object.entries(r).filter(([k]) => !HIDDEN.has(k)));
return Object.keys(d).length ? : —;
},
},
{ key: "request_id", header: "Request", hideSm: true, render: (r) => {r.request_id ?? "—"} },
]}
empty="No audit entries match."
footer={{fmtInt(data?.data.length ?? 0)} entries}
/>
>
);
}