mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
admin/index.php: add server-side pagination (25/page)
- Add Database::getThesesListCount(array $filters) — runs the same WHERE clauses as getThesesList() but with COUNT(DISTINCT t.id); used to compute total pages without loading all rows. - Extend Database::getThesesList() with $limit/$offset parameters; when $limit > 0 appends LIMIT/OFFSET and re-binds positional params individually to avoid the PDO mixed-style restriction. - Fix getThesesList() SELECT: add LEFT JOIN access_types + at.name as access_type — the column was referenced in the template but never fetched. - Wire admin/index.php: read ?page=, compute $totalPages/$offset, pass $perPage=25 + $offset to getThesesList(); include pagination.php partial below the table with filter-preserving $baseParams. - Add result-count line (<p class="admin-list-meta">) showing "X–Y sur Z TFE" when multiple pages exist. - Add .admin-body .pagination-wrap / .pagination-btn / .pagination-info styles to admin.css (scoped to .admin-body to avoid colliding with public pages).
This commit is contained in:
@@ -21,7 +21,14 @@ try {
|
||||
if ($yearFilter) $filters['year'] = $yearFilter;
|
||||
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
|
||||
|
||||
$theses = $db->getThesesList($filters);
|
||||
$perPage = 25;
|
||||
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
|
||||
$totalCount = $db->getThesesListCount($filters);
|
||||
$totalPages = $totalCount > 0 ? (int) ceil($totalCount / $perPage) : 1;
|
||||
$page = min($page, $totalPages);
|
||||
$offset = ($page - 1) * $perPage;
|
||||
|
||||
$theses = $db->getThesesList($filters, $perPage, $offset);
|
||||
$stats = $db->getThesesStats();
|
||||
$years = $db->getAllYears();
|
||||
$orientations = $db->getAllOrientations();
|
||||
@@ -74,14 +81,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<aside role="status" class="admin-maintenance-bar <?= $maintenanceOn ? 'admin-maintenance-bar--active' : '' ?>" aria-label="Statut du site">
|
||||
<?php if ($maintenanceOn): ?>
|
||||
<span>⚠ Mode maintenance <strong>activé</strong> — le site public est inaccessible.</span>
|
||||
<form method="post" action="actions/maintenance.php" style="display:inline;">
|
||||
<form method="post" action="actions/maintenance.php">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="action" value="disable_maintenance">
|
||||
<button type="submit" class="admin-btn admin-btn--sm">Désactiver la maintenance</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<span>Site public : <strong>en ligne</strong></span>
|
||||
<form method="post" action="actions/maintenance.php" style="display:inline;">
|
||||
<form method="post" action="actions/maintenance.php">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="action" value="enable_maintenance">
|
||||
<button type="submit" class="admin-btn admin-btn--sm admin-btn--warning"
|
||||
@@ -150,8 +157,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
<!-- Table -->
|
||||
<?php if (empty($theses)): ?>
|
||||
<p style="color:var(--text-secondary);padding:1rem 0;">Aucun TFE trouvé.</p>
|
||||
<p class="admin-empty">Aucun TFE trouvé.</p>
|
||||
<?php else: ?>
|
||||
<p class="admin-list-meta">
|
||||
<?php
|
||||
$from = $offset + 1;
|
||||
$to = min($offset + $perPage, $totalCount);
|
||||
if ($totalPages > 1) {
|
||||
echo "$from–$to sur $totalCount TFE";
|
||||
} else {
|
||||
echo "$totalCount TFE";
|
||||
}
|
||||
?>
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -170,7 +188,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<?php foreach ($theses as $thesis): ?>
|
||||
<tr>
|
||||
<td><input type="checkbox" name="selected_theses[]" value="<?= $thesis['id'] ?>"></td>
|
||||
<td style="color:var(--text-secondary);font-size:.8rem;"><?= htmlspecialchars($thesis['identifier'] ?? $thesis['id']) ?></td>
|
||||
<td class="admin-table-id"><?= htmlspecialchars($thesis['identifier'] ?? $thesis['id']) ?></td>
|
||||
<td>
|
||||
<div class="thesis-title"><?= htmlspecialchars($thesis['title']) ?></div>
|
||||
<?php if ($thesis['subtitle']): ?>
|
||||
@@ -210,6 +228,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
$baseParams = array_filter([
|
||||
'search' => $searchQuery,
|
||||
'year' => $yearFilter ?: '',
|
||||
'orientation' => $orientationFilter ?: '',
|
||||
]);
|
||||
include APP_ROOT . '/templates/partials/pagination.php';
|
||||
?>
|
||||
</main>
|
||||
|
||||
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|
||||
|
||||
@@ -343,6 +343,29 @@
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.admin-maintenance-bar form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* Result-count line above the thesis table */
|
||||
.admin-list-meta {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.85rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Empty-state message below the thesis table */
|
||||
.admin-empty {
|
||||
color: var(--text-secondary);
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
/* Identifier column in the thesis table */
|
||||
.admin-table-id {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
/* ── Filters bar ────────────────────────────────────────────────────────── */
|
||||
.admin-filters {
|
||||
display: flex;
|
||||
@@ -808,3 +831,52 @@
|
||||
color: var(--text-secondary);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ── Pagination (admin list) ─────────────────────────────────────────────── */
|
||||
.admin-body .pagination-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 1.5rem 0 0.5rem;
|
||||
}
|
||||
|
||||
.admin-body .pagination-wrap ul {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.admin-body .pagination-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 2.75rem;
|
||||
min-height: 2.75rem;
|
||||
padding: 0 0.6rem;
|
||||
border: 1px solid var(--border-secondary);
|
||||
border-radius: 3px;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.9rem;
|
||||
text-decoration: none;
|
||||
transition: border-color 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.admin-body .pagination-btn:hover:not(.disabled) {
|
||||
border-color: var(--admin-purple);
|
||||
color: var(--admin-purple);
|
||||
}
|
||||
|
||||
.admin-body .pagination-btn.disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.admin-body .pagination-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user