Commit 30b8d87d9dd317af4aa4c2f04bfd3cd1c422eedc
1 parent
72556b0d
Exists in
main
Auditoria: paginação com escolha de registros por página
Adiciona seletor de 10/25/50/100 registros por página e navegação por Anterior/Próxima + select de página, em vez de listar todos os números de página de uma vez (inviável com muitos registros). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Showing
1 changed file
with
47 additions
and
16 deletions
Show diff stats
public_html/auditoria.php
| @@ -5,12 +5,18 @@ declare(strict_types=1); | @@ -5,12 +5,18 @@ declare(strict_types=1); | ||
| 5 | require __DIR__ . '/../src/bootstrap.php'; | 5 | require __DIR__ . '/../src/bootstrap.php'; |
| 6 | Auth::requireAdmin(); | 6 | Auth::requireAdmin(); |
| 7 | 7 | ||
| 8 | -$perPage = 50; | 8 | +$perPageOptions = [10, 25, 50, 100]; |
| 9 | +$perPage = (int) ($_GET['per'] ?? 50); | ||
| 10 | +if (!in_array($perPage, $perPageOptions, true)) { | ||
| 11 | + $perPage = 50; | ||
| 12 | +} | ||
| 13 | +$total = (int) Database::pdo()->query('SELECT COUNT(*) FROM audit_log')->fetchColumn(); | ||
| 14 | +$totalPages = max(1, (int) ceil($total / $perPage)); | ||
| 15 | + | ||
| 9 | $page = max(1, (int) ($_GET['p'] ?? 1)); | 16 | $page = max(1, (int) ($_GET['p'] ?? 1)); |
| 17 | +$page = min($page, $totalPages); | ||
| 10 | $offset = ($page - 1) * $perPage; | 18 | $offset = ($page - 1) * $perPage; |
| 11 | 19 | ||
| 12 | -$total = (int) Database::pdo()->query('SELECT COUNT(*) FROM audit_log')->fetchColumn(); | ||
| 13 | - | ||
| 14 | $stmt = Database::pdo()->prepare( | 20 | $stmt = Database::pdo()->prepare( |
| 15 | 'SELECT * FROM audit_log ORDER BY criado_em DESC, id DESC LIMIT :limit OFFSET :offset' | 21 | 'SELECT * FROM audit_log ORDER BY criado_em DESC, id DESC LIMIT :limit OFFSET :offset' |
| 16 | ); | 22 | ); |
| @@ -19,8 +25,6 @@ $stmt->bindValue('offset', $offset, PDO::PARAM_INT); | @@ -19,8 +25,6 @@ $stmt->bindValue('offset', $offset, PDO::PARAM_INT); | ||
| 19 | $stmt->execute(); | 25 | $stmt->execute(); |
| 20 | $logs = $stmt->fetchAll(); | 26 | $logs = $stmt->fetchAll(); |
| 21 | 27 | ||
| 22 | -$totalPages = max(1, (int) ceil($total / $perPage)); | ||
| 23 | - | ||
| 24 | $acaoLabels = [ | 28 | $acaoLabels = [ |
| 25 | 'login' => 'Login', | 29 | 'login' => 'Login', |
| 26 | 'login_negado' => 'Login negado (sem permissão)', | 30 | 'login_negado' => 'Login negado (sem permissão)', |
| @@ -42,9 +46,23 @@ View::header('Auditoria'); | @@ -42,9 +46,23 @@ View::header('Auditoria'); | ||
| 42 | <h1>Auditoria</h1> | 46 | <h1>Auditoria</h1> |
| 43 | <p class="hint"> | 47 | <p class="hint"> |
| 44 | Histórico de logins (inclusive tentativas com senha incorreta), alterações em | 48 | Histórico de logins (inclusive tentativas com senha incorreta), alterações em |
| 45 | - alunos, administradores e configurações. Mostrando <?= count($logs) ?> de <?= $total ?> registros. | 49 | + alunos, administradores e configurações. |
| 46 | </p> | 50 | </p> |
| 47 | 51 | ||
| 52 | + <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px;margin-bottom:4px"> | ||
| 53 | + <span class="hint"> | ||
| 54 | + Mostrando <?= count($logs) ?> de <?= $total ?> registros — página <?= $page ?> de <?= $totalPages ?> | ||
| 55 | + </span> | ||
| 56 | + <form method="get" action="auditoria" style="display:flex;align-items:center;gap:8px;margin:0"> | ||
| 57 | + <label for="per" style="margin:0;white-space:nowrap">Por página</label> | ||
| 58 | + <select id="per" name="per" onchange="this.form.submit()" style="margin:0;width:auto"> | ||
| 59 | + <?php foreach ($perPageOptions as $opt): ?> | ||
| 60 | + <option value="<?= $opt ?>" <?= $opt === $perPage ? 'selected' : '' ?>><?= $opt ?></option> | ||
| 61 | + <?php endforeach; ?> | ||
| 62 | + </select> | ||
| 63 | + </form> | ||
| 64 | + </div> | ||
| 65 | + | ||
| 48 | <table> | 66 | <table> |
| 49 | <tr> | 67 | <tr> |
| 50 | <th>Data/hora</th> | 68 | <th>Data/hora</th> |
| @@ -70,16 +88,29 @@ View::header('Auditoria'); | @@ -70,16 +88,29 @@ View::header('Auditoria'); | ||
| 70 | </table> | 88 | </table> |
| 71 | 89 | ||
| 72 | <?php if ($totalPages > 1): ?> | 90 | <?php if ($totalPages > 1): ?> |
| 73 | - <p style="margin-top:12px"> | ||
| 74 | - <?php for ($p = 1; $p <= $totalPages; $p++): ?> | ||
| 75 | - <?php if ($p === $page): ?> | ||
| 76 | - <strong><?= $p ?></strong> | ||
| 77 | - <?php else: ?> | ||
| 78 | - <a href="auditoria?p=<?= $p ?>"><?= $p ?></a> | ||
| 79 | - <?php endif; ?> | ||
| 80 | - <?php if ($p < $totalPages): ?> | <?php endif; ?> | ||
| 81 | - <?php endfor; ?> | ||
| 82 | - </p> | 91 | + <div style="display:flex;align-items:center;gap:10px;margin-top:16px;flex-wrap:wrap"> |
| 92 | + <?php if ($page > 1): ?> | ||
| 93 | + <a class="btn secondary" href="auditoria?per=<?= $perPage ?>&p=<?= $page - 1 ?>">← Anterior</a> | ||
| 94 | + <?php else: ?> | ||
| 95 | + <span class="btn secondary" style="opacity:.4;pointer-events:none">← Anterior</span> | ||
| 96 | + <?php endif; ?> | ||
| 97 | + | ||
| 98 | + <form method="get" action="auditoria" style="display:flex;align-items:center;gap:8px;margin:0"> | ||
| 99 | + <input type="hidden" name="per" value="<?= $perPage ?>"> | ||
| 100 | + <label for="p" style="margin:0;white-space:nowrap">Página</label> | ||
| 101 | + <select id="p" name="p" onchange="this.form.submit()" style="margin:0;width:auto"> | ||
| 102 | + <?php for ($p = 1; $p <= $totalPages; $p++): ?> | ||
| 103 | + <option value="<?= $p ?>" <?= $p === $page ? 'selected' : '' ?>><?= $p ?> de <?= $totalPages ?></option> | ||
| 104 | + <?php endfor; ?> | ||
| 105 | + </select> | ||
| 106 | + </form> | ||
| 107 | + | ||
| 108 | + <?php if ($page < $totalPages): ?> | ||
| 109 | + <a class="btn secondary" href="auditoria?per=<?= $perPage ?>&p=<?= $page + 1 ?>">Próxima →</a> | ||
| 110 | + <?php else: ?> | ||
| 111 | + <span class="btn secondary" style="opacity:.4;pointer-events:none">Próxima →</span> | ||
| 112 | + <?php endif; ?> | ||
| 113 | + </div> | ||
| 83 | <?php endif; ?> | 114 | <?php endif; ?> |
| 84 | </div> | 115 | </div> |
| 85 | <?php | 116 | <?php |