fix(admin): fix audit log rows overflowing off-screen
flex-wrap with long IDs/IPs pushed content past the viewport edge instead of wrapping. Switched to a fixed-column grid with truncation + title tooltips, wrapped in a horizontal-scroll container so the whole table scrolls as a unit on narrow screens instead of individual cells clipping.
This commit is contained in:
1 parent
e099763211
commit
3ea668a137
1 file changed
+58
-33
@@ -117,41 +117,66 @@ export default function AdminAuditLogPage() {
|
||||
<p className="text-sm text-zinc-500 text-center py-12">No entries match these filters</p>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
{entries.map((entry) => (
|
||||
<div
|
||||
key={entry.id}
|
||||
className="flex flex-wrap items-center gap-x-4 gap-y-1 rounded-xl border border-zinc-800 bg-zinc-900 px-4 py-3"
|
||||
>
|
||||
<Badge variant="secondary" className="text-[10px] shrink-0">
|
||||
{entry.action}
|
||||
</Badge>
|
||||
<p className="text-xs text-zinc-500 shrink-0">
|
||||
{entry.targetType} · <span className="font-mono">{entry.targetId.slice(0, 16)}…</span>
|
||||
</p>
|
||||
<div className="flex-1 min-w-[10rem]">
|
||||
<p className="text-sm text-zinc-200 truncate">
|
||||
{entry.moderatorName ?? <span className="text-zinc-500">unnamed</span>}
|
||||
{entry.moderatorRole && (
|
||||
<Badge
|
||||
className={`ml-2 text-[10px] ${
|
||||
ROLE_BADGE_CLASS[entry.moderatorRole] ?? "bg-zinc-700 text-zinc-200"
|
||||
}`}
|
||||
>
|
||||
{entry.moderatorRole}
|
||||
</Badge>
|
||||
)}
|
||||
</p>
|
||||
<p className="text-xs text-zinc-600 font-mono truncate">{entry.moderatorId}</p>
|
||||
{/* Fixed-width grid columns instead of flex-wrap — long IDs/IPs used
|
||||
to force rows to overflow the viewport instead of wrapping. The
|
||||
outer scroll wrapper lets the whole table scroll as one unit on
|
||||
narrow screens rather than clipping individual cells. */}
|
||||
<div className="overflow-x-auto rounded-xl border border-zinc-800">
|
||||
<div className="min-w-[1000px]">
|
||||
<div className="grid grid-cols-[150px_190px_1fr_130px_170px] gap-3 border-b border-zinc-800 bg-zinc-900/80 px-4 py-2 text-[11px] font-semibold uppercase tracking-wide text-zinc-500">
|
||||
<span>Action</span>
|
||||
<span>Target</span>
|
||||
<span>Moderator</span>
|
||||
<span>IP</span>
|
||||
<span>Time</span>
|
||||
</div>
|
||||
<p className="text-xs text-zinc-500 font-mono shrink-0">{entry.ipAddress ?? "—"}</p>
|
||||
<p className="text-xs text-zinc-600 shrink-0">
|
||||
{new Date(entry.createdAt).toLocaleString()}
|
||||
</p>
|
||||
{entry.reason && (
|
||||
<p className="w-full text-xs text-zinc-400 truncate">Reason: {entry.reason}</p>
|
||||
)}
|
||||
{entries.map((entry) => (
|
||||
<div key={entry.id} className="border-b border-zinc-800 bg-zinc-900 last:border-b-0">
|
||||
<div className="grid grid-cols-[150px_190px_1fr_130px_170px] items-center gap-3 px-4 py-3">
|
||||
<Badge variant="secondary" className="w-fit text-[10px]">
|
||||
{entry.action}
|
||||
</Badge>
|
||||
<p className="min-w-0 truncate text-xs text-zinc-500" title={entry.targetId}>
|
||||
{entry.targetType} · <span className="font-mono">{entry.targetId}</span>
|
||||
</p>
|
||||
<div className="min-w-0">
|
||||
<p className="flex items-center gap-2 truncate text-sm text-zinc-200">
|
||||
<span className="truncate">
|
||||
{entry.moderatorName ?? <span className="text-zinc-500">unnamed</span>}
|
||||
</span>
|
||||
{entry.moderatorRole && (
|
||||
<Badge
|
||||
className={`shrink-0 text-[10px] ${
|
||||
ROLE_BADGE_CLASS[entry.moderatorRole] ?? "bg-zinc-700 text-zinc-200"
|
||||
}`}
|
||||
>
|
||||
{entry.moderatorRole}
|
||||
</Badge>
|
||||
)}
|
||||
</p>
|
||||
<p
|
||||
className="truncate font-mono text-xs text-zinc-600"
|
||||
title={entry.moderatorId}
|
||||
>
|
||||
{entry.moderatorId}
|
||||
</p>
|
||||
</div>
|
||||
<p className="truncate font-mono text-xs text-zinc-500">
|
||||
{entry.ipAddress ?? "—"}
|
||||
</p>
|
||||
<p className="truncate text-xs text-zinc-600">
|
||||
{new Date(entry.createdAt).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
{entry.reason && (
|
||||
<p className="truncate px-4 pb-3 text-xs text-zinc-400">
|
||||
Reason: {entry.reason}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{hasNextPage && (
|
||||
<div className="flex justify-center pt-2">
|
||||
|
||||
Reference in new issue
Block a user