fix(admin): stats bar always shows whole-DB counts, not filtered counts

admin/index.php showed "TFE total / Publiés / En attente" by running
array_filter() over the already-filtered $theses array returned by
getThesesList(). When any search or year filter was active the three
numbers reflected only the matching subset, making the stats misleading
(e.g. searching for a single student would show "1 total, 0 publiés").

Add Database::getThesesStats(): array — a single SQL aggregation query:
  SELECT COUNT(*), SUM(is_published), SUM(NOT is_published) FROM theses

This runs against the raw theses table with no filters, so the counters
always display the true whole-database figures regardless of what filter
the admin has active. admin/index.php now calls getThesesStats() and
reads $stats['total'], $stats['published'], $stats['pending'] instead
of the array_filter expressions.
This commit is contained in:
Pontoporeia
2026-03-28 11:42:44 +01:00
parent 2e277b104e
commit 69e161ada3
5 changed files with 31 additions and 6 deletions

View File

@@ -22,6 +22,7 @@ try {
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
$theses = $db->getThesesList($filters);
$stats = $db->getThesesStats();
$years = $db->getAllYears();
$orientations = $db->getAllOrientations();
} catch (Exception $e) {
@@ -95,18 +96,18 @@ document.addEventListener('DOMContentLoaded', () => {
<?php endif; ?>
</div>
<!-- Stats -->
<!-- Stats (always reflects full DB, independent of active filters) -->
<div class="admin-stats">
<div class="admin-stat">
<div class="admin-stat__number"><?= count($theses) ?></div>
<div class="admin-stat__number"><?= $stats['total'] ?></div>
<div class="admin-stat__label">TFE total</div>
</div>
<div class="admin-stat">
<div class="admin-stat__number"><?= count(array_filter($theses, fn($t) => $t['is_published'])) ?></div>
<div class="admin-stat__number"><?= $stats['published'] ?></div>
<div class="admin-stat__label">Publiés</div>
</div>
<div class="admin-stat">
<div class="admin-stat__number"><?= count(array_filter($theses, fn($t) => !$t['is_published'])) ?></div>
<div class="admin-stat__number"><?= $stats['pending'] ?></div>
<div class="admin-stat__label">En attente</div>
</div>
</div>