logs.php
11.48 KB
<?php
require_once __DIR__ . '/../bootstrap.php';
requirePermission('logs.view');
global $pdo;
// Get company name
$companyName = 'WorkersPanel';
try {
$stmt = $pdo->query("SELECT value FROM system_info WHERE `key`='company_name'");
$result = $stmt->fetch();
if ($result && !empty($result['value'])) {
$companyName = $result['value'];
}
} catch (Throwable $e) {}
$pageTitle = 'Activity Logs';
$extraHead = '<style>
.card, .table-wrap { max-width: none !important; }
.main-content { max-width: 85%; margin: 0 auto; }
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.table-compact { min-width: 800px; }
@media (max-width: 768px) {
.main-content { max-width: 100% !important; margin: 0 !important; padding: 12px !important; }
.card { margin-bottom: 12px; }
.table-compact { font-size: 0.85rem; min-width: 700px; }
.table-compact th, .table-compact td { padding: 8px 6px; }
}
@media (max-width: 480px) {
.table-compact { font-size: 0.8rem; min-width: 600px; }
.table-compact th, .table-compact td { padding: 6px 4px; }
}
</style>';
// Pagination
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 25;
$offset = ($page - 1) * $perPage;
/**
* Activity Logs with pagination
*/
$logs = [];
$logsCount = 0;
try {
$stmt = $pdo->query("SELECT COUNT(*) FROM activity_logs");
$logsCount = (int)($stmt->fetchColumn() ?? 0);
$sql = "
SELECT al.*, u.username, u.display_name
FROM activity_logs al
LEFT JOIN users u ON al.user_id = u.id
ORDER BY al.created_at DESC
LIMIT {$perPage} OFFSET {$offset}
";
$logs = $pdo->query($sql)->fetchAll();
} catch (Throwable $e) {
$logs = [];
$logsCount = 0;
}
$logPages = ceil($logsCount / $perPage) ?: 1;
/**
* Login Logs with pagination
*/
$loginLogs = [];
$loginsCount = 0;
$loginPage = max(1, (int)($_GET['login_page'] ?? 1));
$loginOffset = ($loginPage - 1) * $perPage;
try {
$stmt = $pdo->query("SELECT COUNT(*) FROM login_logs");
$loginsCount = (int)($stmt->fetchColumn() ?? 0);
$sql = "
SELECT ll.*, u.display_name
FROM login_logs ll
LEFT JOIN users u ON ll.user_id = u.id
ORDER BY ll.created_at DESC
LIMIT {$perPage} OFFSET {$loginOffset}
";
$loginLogs = $pdo->query($sql)->fetchAll();
} catch (Throwable $e) {
$loginLogs = [];
$loginsCount = 0;
}
$loginPages = ceil($loginsCount / $perPage) ?: 1;
/**
* DB Change Logs with pagination
*/
$dbChanges = [];
$dbCount = 0;
$dbPage = max(1, (int)($_GET['db_page'] ?? 1));
$dbOffset = ($dbPage - 1) * $perPage;
try {
$stmt = $pdo->query("SELECT COUNT(*) FROM db_change_logs");
$dbCount = (int)($stmt->fetchColumn() ?? 0);
$sql = "
SELECT dcl.*, u.display_name
FROM db_change_logs dcl
LEFT JOIN users u ON dcl.user_id = u.id
ORDER BY dcl.created_at DESC
LIMIT {$perPage} OFFSET {$dbOffset}
";
$dbChanges = $pdo->query($sql)->fetchAll();
} catch (Throwable $e) {
$dbChanges = [];
$dbCount = 0;
}
$dbPages = ceil($dbCount / $perPage) ?: 1;
include __DIR__ . '/../partials/header.php';
?>
<div class="content-header">
<div>
<h1 class="content-title">📋 Activity Logs</h1>
<p class="content-subtitle">System, login, update and database change history</p>
</div>
</div>
<!-- Activity Logs -->
<div class="card mb-lg">
<div class="card-header">
<h2 class="card-title">Activity Logs (<?= $logsCount ?> total)</h2>
<p class="card-subtitle">Actions performed inside the system</p>
</div>
<div class="card-body">
<?php if (empty($logs)): ?>
<div class="muted">No activity logs found.</div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr>
<th style="width:180px;">Time</th>
<th>User</th>
<th>Action</th>
<th>Entity</th>
<th>Description</th>
<th style="width:140px;">IP</th>
</tr>
</thead>
<tbody>
<?php foreach ($logs as $row): ?>
<tr>
<td><?= htmlspecialchars($row['created_at'] ?? '') ?></td>
<td><?= htmlspecialchars(($row['display_name'] ?? $row['username'] ?? 'System')) ?></td>
<td><span class="badge"><?= htmlspecialchars($row['action'] ?? '') ?></span></td>
<td><?= htmlspecialchars(($row['entity_type'] ?? '') . (($row['entity_id'] ?? null) ? ' #' . $row['entity_id'] : '')) ?></td>
<td><?= htmlspecialchars($row['description'] ?? '') ?></td>
<td><?= htmlspecialchars($row['ip_address'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($logPages > 1): ?>
<div class="pagination" style="margin-top: 20px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
<?php if ($page > 1): ?>
<a href="?page=1" class="btn btn-secondary btn-sm">First</a>
<a href="?page=<?= $page - 1 ?>" class="btn btn-secondary btn-sm">Previous</a>
<?php endif; ?>
<span style="color: var(--text-muted);">Page <?= $page ?> of <?= $logPages ?></span>
<?php if ($page < $logPages): ?>
<a href="?page=<?= $page + 1 ?>" class="btn btn-secondary btn-sm">Next</a>
<a href="?page=<?= $logPages ?>" class="btn btn-secondary btn-sm">Last</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<!-- Login Logs -->
<div class="card mb-lg">
<div class="card-header">
<h2 class="card-title">Login Logs (<?= $loginsCount ?> total)</h2>
<p class="card-subtitle">Sign-in history</p>
</div>
<div class="card-body">
<?php if (empty($loginLogs)): ?>
<div class="muted">No login logs found.</div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr>
<th style="width:180px;">Time</th>
<th>User</th>
<th>Status</th>
<th style="width:140px;">IP</th>
<th>User Agent</th>
</tr>
</thead>
<tbody>
<?php foreach ($loginLogs as $row): ?>
<tr>
<td><?= htmlspecialchars($row['created_at'] ?? '') ?></td>
<td><?= htmlspecialchars($row['display_name'] ?? 'Unknown') ?></td>
<td>
<?php if ($row['success']): ?>
<span class="badge badge-success">Success</span>
<?php else: ?>
<span class="badge badge-error">Failed</span>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($row['ip_address'] ?? '') ?></td>
<td class="muted"><?= htmlspecialchars($row['user_agent'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($loginPages > 1): ?>
<div class="pagination" style="margin-top: 20px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
<?php if ($loginPage > 1): ?>
<a href="?login_page=1" class="btn btn-secondary btn-sm">First</a>
<a href="?login_page=<?= $loginPage - 1 ?>" class="btn btn-secondary btn-sm">Previous</a>
<?php endif; ?>
<span style="color: var(--text-muted);">Page <?= $loginPage ?> of <?= $loginPages ?></span>
<?php if ($loginPage < $loginPages): ?>
<a href="?login_page=<?= $loginPage + 1 ?>" class="btn btn-secondary btn-sm">Next</a>
<a href="?login_page=<?= $loginPages ?>" class="btn btn-secondary btn-sm">Last</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<!-- DB Change Logs -->
<div class="card mb-lg">
<div class="card-header">
<h2 class="card-title">Database Change Logs (<?= $dbCount ?> total)</h2>
<p class="card-subtitle">Auto-captured inserts/updates/deletes (requires migration)</p>
</div>
<div class="card-body">
<?php if (empty($dbChanges)): ?>
<div class="muted">No DB change logs found.</div>
<?php else: ?>
<div class="table-wrap">
<table class="table">
<thead>
<tr>
<th style="width:180px;">Time</th>
<th>User</th>
<th>Table</th>
<th>Action</th>
<th>Row</th>
<th>IP</th>
</tr>
</thead>
<tbody>
<?php foreach ($dbChanges as $row): ?>
<tr>
<td><?= htmlspecialchars($row['created_at'] ?? '') ?></td>
<td><?= htmlspecialchars($row['display_name'] ?? 'System') ?></td>
<td><?= htmlspecialchars($row['table_name'] ?? '') ?></td>
<td><span class="badge"><?= htmlspecialchars($row['action'] ?? '') ?></span></td>
<td><?= htmlspecialchars(($row['row_id'] ?? '') ? '#'.$row['row_id'] : '') ?></td>
<td><?= htmlspecialchars($row['ip_address'] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php if ($dbPages > 1): ?>
<div class="pagination" style="margin-top: 20px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
<?php if ($dbPage > 1): ?>
<a href="?db_page=1" class="btn btn-secondary btn-sm">First</a>
<a href="?db_page=<?= $dbPage - 1 ?>" class="btn btn-secondary btn-sm">Previous</a>
<?php endif; ?>
<span style="color: var(--text-muted);">Page <?= $dbPage ?> of <?= $dbPages ?></span>
<?php if ($dbPage < $dbPages): ?>
<a href="?db_page=<?= $dbPage + 1 ?>" class="btn btn-secondary btn-sm">Next</a>
<a href="?db_page=<?= $dbPages ?>" class="btn btn-secondary btn-sm">Last</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<?php include __DIR__ . '/../partials/footer.php'; ?>