/** * /admin/time-tracking/audit * * Phase 2 — read-only audit trail viewer for admins. Shows every * mutating action on a timesheet, its entries, or the related * entities, ordered most-recent-first. */ import { redirect } from "next/navigation"; import { getAdminUser } from "@/lib/admin-permissions"; import { withBrand } from "@/db/client"; import { timeTrackingAuditLog } from "@/db/schema/time-tracking"; import { PageHeader } from "@/components/admin/design-system"; import { desc, eq, sql } from "drizzle-orm"; const TUXEDO_BRAND_ID = "64294306-5f42-463d-a5e8-2ad6c81a96de"; export const dynamic = "force-dynamic"; export default async function AuditPage({ searchParams, }: { searchParams: Promise<{ action?: string; entity?: string }>; }) { const adminUser = await getAdminUser(); if (!adminUser) redirect("/login"); if (adminUser.role !== "platform_admin" && adminUser.role !== "brand_admin") { redirect("/admin/time-tracking"); } const brandId = adminUser.brand_id ?? TUXEDO_BRAND_ID; const sp = await searchParams; const rows = await withBrand(brandId, async (db) => { const conds = [eq(timeTrackingAuditLog.brandId, brandId)]; if (sp.action) conds.push(eq(timeTrackingAuditLog.action, sp.action)); if (sp.entity) conds.push(eq(timeTrackingAuditLog.entityType, sp.entity)); return db .select({ id: timeTrackingAuditLog.id, actor_label: timeTrackingAuditLog.actorLabel, actor_kind: timeTrackingAuditLog.actorKind, action: timeTrackingAuditLog.action, entity_type: timeTrackingAuditLog.entityType, entity_id: timeTrackingAuditLog.entityId, details: timeTrackingAuditLog.details, created_at: timeTrackingAuditLog.createdAt, }) .from(timeTrackingAuditLog) .where(sql`1=1`) .orderBy(desc(timeTrackingAuditLog.createdAt)) .limit(500); }); return (
{rows.map((r) => ( ))}
When Action Actor Entity Details
{new Date(r.created_at).toLocaleString("en-US", { month: "short", day: "numeric", hour: "numeric", minute: "2-digit", })} {r.action} {r.actor_label} ({r.actor_kind}) {r.entity_type} {r.entity_id && ( {r.entity_id.slice(0, 8)} )}
                      {JSON.stringify(r.details, null, 0)}
                    
); }