Files
template-app/apps/web/src/routes/$org._settings.audit.tsx
T
2026-11-14 09:56:45 +00:00

59 lines
2.2 KiB
TypeScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// The audit viewer (spec §9.4), a tab of Settings, for whoever holds `tenancy.audit.read`: the loader asks before
// anything renders, so a member without it gets a real 403 and a stranger a real 404 (src/server/org-pages.ts).
import { PageSection, PageState } from "@conusai-kit/ui/patterns"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@conusai-kit/ui/primitives"
import { createFileRoute } from "@tanstack/react-router"
import { createServerFn } from "@tanstack/react-start"
import type { ReactElement } from "react"
import type { AuditData, OrgParams } from "../server/org-pages"
import { RoutePending } from "../ui/route-pending"
const ROUTE = "/$org/audit"
const read = createServerFn({ method: "GET" })
.validator((params: OrgParams) => params)
.handler(async ({ data }): Promise<AuditData> => {
const [{ reported }, { auditData }] = await Promise.all([import("../server/page"), import("../server/org-pages")])
return reported(ROUTE, () => auditData(data))
})
export const Route = createFileRoute("/$org/_settings/audit")({
loader: ({ params }) => read({ data: { org: params.org } }),
pendingComponent: RoutePending,
component: Page,
})
function Page(): ReactElement {
const data = Route.useLoaderData()
return (
<PageSection title={data.title}>
{data.rows.length === 0 ? (
<PageState title={data.empty} />
) : (
<Table>
<TableHeader>
<TableRow>
<TableHead scope="col">{data.when}</TableHead>
<TableHead scope="col">{data.action}</TableHead>
<TableHead scope="col">{data.outcome}</TableHead>
<TableHead scope="col">{data.resource}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.rows.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.when}</TableCell>
<TableCell>{row.action}</TableCell>
<TableCell>{row.outcome}</TableCell>
<TableCell>{row.resource}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}
</PageSection>
)
}