Files
2026-04-11 14:08:27 +07:00

162 lines
7.6 KiB
Plaintext

<!-- Page Header -->
<div class="page-title-area">
<div>
<h1>Audit Log Details</h1>
<p class="subtitle">Detailed activity record</p>
</div>
<a href="/admin/audit-logs" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left"></i> Back
</a>
</div>
<div class="row g-3">
<!-- Main Info -->
<div class="col-lg-8">
<div class="card border-0 mb-3">
<div class="card-header">
<h5 class="card-header-title"><i class="fas fa-info-circle"></i> Audit Information</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="mb-3">
<div class="form-label">Model</div>
<span class="badge badge-soft-primary" style="font-size:0.8rem"><%= auditLog.model %></span>
</div>
<div class="mb-3">
<div class="form-label">Action</div>
<%
let badgeClass = 'badge-soft-primary';
if (auditLog.action.includes('CREATE')) badgeClass = 'bg-soft-success';
else if (auditLog.action.includes('UPDATE')) badgeClass = 'bg-soft-warning';
else if (auditLog.action.includes('DELETE')) badgeClass = 'bg-soft-danger';
%>
<span class="badge <%= badgeClass %>" style="font-size:0.8rem"><%= auditLog.action %></span>
</div>
<div class="mb-3">
<div class="form-label">Document ID</div>
<code style="font-size:0.8rem;color:var(--primary-color)"><%= auditLog.documentId %></code>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<div class="form-label">Date & Time</div>
<div style="font-size:var(--font-size-sm)">
<%= new Date(auditLog.createdAt).toLocaleDateString('en-GB') %>
<span style="color:var(--text-muted)"><%= new Date(auditLog.createdAt).toLocaleTimeString() %></span>
</div>
</div>
<div class="mb-3">
<div class="form-label">Performed By</div>
<% if (auditLog.performedBy) { %>
<div style="font-weight:500;font-size:var(--font-size-sm)"><%= auditLog.performedBy.username %></div>
<div style="font-size:var(--font-size-xs);color:var(--text-muted)"><%= auditLog.performedBy.email %></div>
<% } else { %>
<span style="color:var(--text-muted);font-size:var(--font-size-sm)">System</span>
<% } %>
</div>
<div class="mb-3">
<div class="form-label">IP Address</div>
<code style="font-size:0.8rem;color:var(--text-muted)"><%= auditLog.ipAddress %></code>
</div>
</div>
<% if (auditLog.userAgent) { %>
<div class="col-12">
<div class="form-label">User Agent</div>
<div style="font-size:0.75rem;color:var(--text-muted);font-family:monospace;word-break:break-all"><%= auditLog.userAgent %></div>
</div>
<% } %>
</div>
</div>
</div>
<!-- Field Changes -->
<% if (auditLog.changes && auditLog.changes.length > 0) { %>
<div class="card border-0">
<div class="card-header">
<h5 class="card-header-title"><i class="fas fa-pen"></i> Field Changes</h5>
<span class="badge badge-soft-accent"><%= auditLog.changes.length %> field<%= auditLog.changes.length > 1 ? 's' : '' %></span>
</div>
<div class="card-body p-0">
<% if (user && (user.role === 'admin' || user.role === 'superadmin')) { %>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th style="width:160px">Field</th>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<% auditLog.changes.forEach(change => { %>
<tr>
<td style="font-weight:500;font-size:var(--font-size-sm)"><%= change.field %></td>
<td>
<div style="background:var(--danger-soft);border-left:3px solid var(--danger-color);padding:0.4rem 0.6rem;border-radius:0 var(--border-radius-sm) var(--border-radius-sm) 0;font-size:0.8rem;word-break:break-all;">
<% if (change.before === null || change.before === undefined) { %>
<em style="color:var(--text-muted)">null</em>
<% } else if (typeof change.before === 'object') { %>
<pre style="margin:0;font-size:0.75rem;max-height:100px;overflow:auto"><%= JSON.stringify(change.before, null, 2) %></pre>
<% } else { %>
<%= change.before %>
<% } %>
</div>
</td>
<td>
<div style="background:var(--success-soft);border-left:3px solid var(--success-color);padding:0.4rem 0.6rem;border-radius:0 var(--border-radius-sm) var(--border-radius-sm) 0;font-size:0.8rem;word-break:break-all;">
<% if (change.after === null || change.after === undefined) { %>
<em style="color:var(--text-muted)">null</em>
<% } else if (typeof change.after === 'object') { %>
<pre style="margin:0;font-size:0.75rem;max-height:100px;overflow:auto"><%= JSON.stringify(change.after, null, 2) %></pre>
<% } else { %>
<%= change.after %>
<% } %>
</div>
</td>
</tr>
<% }); %>
</tbody>
</table>
</div>
<% } else { %>
<div class="p-3">
<div class="alert d-flex gap-2 align-items-center" style="background:var(--info-soft);border:1px solid rgba(14,116,144,0.15);border-radius:var(--border-radius-sm);padding:0.75rem;">
<i class="fas fa-info-circle" style="color:var(--info-color)"></i>
<span style="font-size:var(--font-size-sm)">Detailed field values are restricted to administrators.</span>
</div>
<% auditLog.changes.forEach(change => { %>
<div style="display:flex;align-items:center;gap:0.5rem;padding:0.4rem 0;border-bottom:1px solid var(--border-light);">
<span style="font-weight:500;font-size:var(--font-size-sm)"><%= change.field %></span>
<span class="badge bg-soft-info">Modified</span>
</div>
<% }); %>
</div>
<% } %>
</div>
</div>
<% } %>
</div>
<!-- Sidebar summary -->
<div class="col-lg-4">
<div class="card border-0">
<div class="card-header">
<h5 class="card-header-title"><i class="fas fa-chart-bar"></i> Summary</h5>
</div>
<div class="card-body d-flex flex-column gap-2">
<div class="stat-card primary">
<div class="stat-card-value"><%= auditLog.changes ? auditLog.changes.length : 0 %></div>
<div class="stat-card-label">Fields Changed</div>
</div>
<div class="stat-card accent">
<div class="stat-card-value" style="font-size:1.25rem"><%= new Date(auditLog.createdAt).toLocaleDateString('en-GB') === new Date().toLocaleDateString('en-GB') ? 'Today' : 'Past' %></div>
<div class="stat-card-label">Timing</div>
</div>
</div>
</div>
</div>
</div>