"use client";
import { useCallback } from "react";
import {
AuditLogTable,
type AuditRecord,
} from "@/components/ui/audit-log-table";
const settings = {
dangerousOnly: false,
failExport: false,
pageSize: 8,
};
/** Fixed times (no clock): the same rows on the server and in the browser. */
const BASE = Date.parse("2026-10-17T09:30:00Z");
const MINUTE = 60_000;
const at = (minutesAgo: number) =>
new Date(BASE - minutesAgo * MINUTE).toISOString();
const RECORDS: AuditRecord[] = [
{
action: "user.role_changed",
actor: "Amelia Brooks",
dangerous: true,
detail: "Role changed from Viewer to Admin.",
ip: "203.0.113.24",
target: "lucas.meyer@acme.dev",
},
{
action: "session.signed_in",
actor: "Lucas Meyer",
detail: "Signed in with a passkey.",
ip: "198.51.100.7",
target: "lucas.meyer@acme.dev",
},
{
action: "api_key.rotated",
actor: "Noah Bennett",
dangerous: true,
detail: "Production key rotated; the old one stops working in 24 hours.",
ip: "203.0.113.51",
target: "key_live_payments",
},
{
action: "alert_rule.updated",
actor: "Mia Turner",
detail: "Threshold raised from 80% to 90% disk.",
ip: "198.51.100.33",
target: "rule/disk-space",
},
{
action: "export.downloaded",
actor: "Grace Kim",
detail: "Monthly invoices, 1,284 rows.",
ip: "192.0.2.14",
target: "invoices-2026-09.csv",
},
{
action: "user.invited",
actor: "Amelia Brooks",
detail: "Invited as Support agent.",
ip: "203.0.113.24",
target: "sophia.lee@acme.dev",
},
{
action: "project.deleted",
actor: "Ethan Cole",
dangerous: true,
detail: "Project and its 3 environments deleted.",
ip: "198.51.100.90",
target: "project/legacy-billing",
},
{
action: "session.signed_in",
actor: "Grace Kim",
detail: "Signed in with email code.",
ip: "192.0.2.14",
target: "grace.kim@acme.dev",
},
{
action: "webhook.created",
actor: "deploy-bot",
detail: "Sends deploy events to the release channel.",
target: "https://hooks.acme.dev/releases",
},
{
action: "settings.updated",
actor: "Mia Turner",
detail: "Session timeout set to 12 hours.",
ip: "198.51.100.33",
target: "workspace/security",
},
{
action: "two_factor.disabled",
actor: "Lucas Meyer",
dangerous: true,
detail: "Turned off by an admin after a lost phone.",
ip: "198.51.100.7",
target: "lucas.meyer@acme.dev",
},
{
action: "alert_rule.paused",
actor: "Noah Bennett",
detail: "Paused for the database migration window.",
ip: "203.0.113.51",
target: "rule/replica-lag",
},
{
action: "user.removed",
actor: "Amelia Brooks",
dangerous: true,
detail: "Access removed at the end of the contract.",
ip: "203.0.113.24",
target: "contractor.ops@acme.dev",
},
{
action: "export.downloaded",
actor: "Sophia Lee",
detail: "Support tickets, last 30 days.",
ip: "192.0.2.77",
target: "tickets-30d.csv",
},
{
action: "session.signed_in",
actor: "Ethan Cole",
detail: "Signed in with a passkey.",
ip: "198.51.100.90",
target: "ethan.cole@acme.dev",
},
{
action: "settings.updated",
actor: "Grace Kim",
detail:
'=HYPERLINK("https://example.com") pasted into a note: exported as text.',
ip: "192.0.2.14",
target: "workspace/notes",
},
{
action: "api_key.created",
actor: "deploy-bot",
detail: "Read-only key for the status page.",
target: "key_live_status",
},
{
action: "user.role_changed",
actor: "Mia Turner",
detail: "Role changed from Admin to Editor.",
ip: "198.51.100.33",
target: "noah.bennett@acme.dev",
},
{
action: "session.signed_in",
actor: "Amelia Brooks",
detail: "Signed in with a passkey.",
ip: "203.0.113.24",
target: "amelia.brooks@acme.dev",
},
{
action: "backup.restored",
actor: "Noah Bennett",
dangerous: true,
detail: "Staging database restored from the 02:00 snapshot.",
ip: "203.0.113.51",
target: "db/staging",
},
{
action: "webhook.deleted",
actor: "Ethan Cole",
detail: "Old CI hook removed.",
ip: "198.51.100.90",
target: "https://ci.acme.dev/hook",
},
{
action: "export.downloaded",
actor: "Mia Turner",
detail: "Audit log, last 7 days.",
ip: "198.51.100.33",
target: "audit-log-7d.csv",
},
{
action: "session.signed_in",
actor: "Sophia Lee",
detail: "Signed in with email code.",
ip: "192.0.2.77",
target: "sophia.lee@acme.dev",
},
].map((record, i) => ({ ...record, at: at(i * 37 + 3), id: `evt-${i + 1}` }));
/** An audit log of a small team: search, filter, page through and export it. */
export default function Demo(props: Partial<typeof settings>) {
const s = { ...settings, ...props };
const failingExport = useCallback(async () => {
await new Promise((resolve) => setTimeout(resolve, 600));
throw new Error(
"The export service did not answer. Try again in a minute."
);
}, []);
return (
<div className="flex min-h-[640px] w-full items-start justify-center bg-background p-4 sm:p-8">
<AuditLogTable
className="max-w-5xl"
defaultDangerousOnly={s.dangerousOnly}
fileName="audit-log-demo.csv"
key={`${s.dangerousOnly}`}
onExport={s.failExport ? failingExport : undefined}
pageSize={s.pageSize}
records={RECORDS}
/>
</div>
);
}