mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 03:29:19 +02:00
Add AP filter to admin list; fix reset as unstyled button
This commit is contained in:
1
SPECS.md
1
SPECS.md
@@ -34,4 +34,3 @@ pas disponnible:
|
|||||||
|
|
||||||
- quelle(s) fonte(s) est-ce que vous utilisez sur le site ?
|
- quelle(s) fonte(s) est-ce que vous utilisez sur le site ?
|
||||||
- est-ce que vous pouvez m’envoyez un export de la maquette du site ? (en .jpg c’est ok, c’est juste pour rafraîchir nos mémoires afin qu'on puisse produire les textes en adéquation avec ce qui existe)
|
- est-ce que vous pouvez m’envoyez un export de la maquette du site ? (en .jpg c’est ok, c’est juste pour rafraîchir nos mémoires afin qu'on puisse produire les textes en adéquation avec ce qui existe)
|
||||||
- les questions du dernier mail :)
|
|
||||||
|
|||||||
@@ -217,14 +217,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$db = new Database();
|
$db = new Database();
|
||||||
$searchQuery = isset($_GET['search']) ? trim($_GET['search']) : '';
|
$searchQuery = isset($_GET['search']) ? trim($_GET['search']) : '';
|
||||||
$yearFilter = isset($_GET['year']) ? intval($_GET['year']) : null;
|
$yearFilter = isset($_GET['year']) ? intval($_GET['year']) : null;
|
||||||
$orientationFilter = isset($_GET['orientation']) ? intval($_GET['orientation']) : null;
|
$orientationFilter = isset($_GET['orientation']) ? intval($_GET['orientation']) : null;
|
||||||
|
$apFilter = isset($_GET['ap']) ? intval($_GET['ap']) : null;
|
||||||
|
|
||||||
$filters = [];
|
$filters = [];
|
||||||
if ($searchQuery) $filters['search'] = $searchQuery;
|
if ($searchQuery) $filters['search'] = $searchQuery;
|
||||||
if ($yearFilter) $filters['year'] = $yearFilter;
|
if ($yearFilter) $filters['year'] = $yearFilter;
|
||||||
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
|
if ($orientationFilter) $filters['orientation'] = $orientationFilter;
|
||||||
|
if ($apFilter) $filters['ap'] = $apFilter;
|
||||||
|
|
||||||
$perPage = 25;
|
$perPage = 25;
|
||||||
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
|
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
|
||||||
@@ -237,6 +239,7 @@ try {
|
|||||||
$stats = $db->getThesesStats();
|
$stats = $db->getThesesStats();
|
||||||
$years = $db->getAllYears();
|
$years = $db->getAllYears();
|
||||||
$orientations = $db->getAllOrientations();
|
$orientations = $db->getAllOrientations();
|
||||||
|
$apPrograms = $db->getAllAPPrograms();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
error_log("Error loading theses list: " . $e->getMessage());
|
error_log("Error loading theses list: " . $e->getMessage());
|
||||||
die("Erreur lors du chargement de la liste.");
|
die("Erreur lors du chargement de la liste.");
|
||||||
@@ -277,12 +280,48 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main id="main-content">
|
<main id="main-content">
|
||||||
<div class="admin-list-header">
|
<?php include APP_ROOT . '/templates/partials/flash-messages.php'; ?>
|
||||||
<div class="admin-list-header__top">
|
|
||||||
<h1>Liste des TFE</h1>
|
<!-- Title + filters + stats + import all in one toolbar row -->
|
||||||
|
<div class="admin-list-toolbar">
|
||||||
|
<h1>Liste des TFE</h1>
|
||||||
|
|
||||||
|
<form class="admin-filters" method="get" action="/admin/">
|
||||||
|
<input type="text" name="search" placeholder="Titre, auteur..."
|
||||||
|
value="<?= htmlspecialchars($searchQuery) ?>">
|
||||||
|
<select name="year">
|
||||||
|
<option value="">Année</option>
|
||||||
|
<?php foreach ($years as $y): ?>
|
||||||
|
<option value="<?= $y ?>" <?= $yearFilter == $y ? 'selected' : '' ?>><?= $y ?></option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
<select name="orientation">
|
||||||
|
<option value="">Orientation</option>
|
||||||
|
<?php foreach ($orientations as $o): ?>
|
||||||
|
<option value="<?= $o['id'] ?>" <?= $orientationFilter == $o['id'] ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($o['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
<select name="ap">
|
||||||
|
<option value="">AP</option>
|
||||||
|
<?php foreach ($apPrograms as $ap): ?>
|
||||||
|
<option value="<?= $ap['id'] ?>" <?= $apFilter == $ap['id'] ? 'selected' : '' ?>>
|
||||||
|
<?= htmlspecialchars($ap['name']) ?>
|
||||||
|
</option>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="admin-filters-btn">Filtrer</button>
|
||||||
|
<?php if ($searchQuery || $yearFilter || $orientationFilter || $apFilter): ?>
|
||||||
|
<button type="button" class="admin-filters-reset"
|
||||||
|
onclick="window.location='/admin/'">✕ Réinitialiser</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="admin-list-toolbar__right">
|
||||||
<dl class="admin-stats">
|
<dl class="admin-stats">
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
<dt class="admin-stat__label">TFE total</dt>
|
<dt class="admin-stat__label">Total</dt>
|
||||||
<dd class="admin-stat__number"><?= $stats['total'] ?></dd>
|
<dd class="admin-stat__number"><?= $stats['total'] ?></dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
@@ -290,43 +329,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<dd class="admin-stat__number"><?= $stats['published'] ?></dd>
|
<dd class="admin-stat__number"><?= $stats['published'] ?></dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="admin-stat">
|
<div class="admin-stat">
|
||||||
<dt class="admin-stat__label">En attente</dt>
|
<dt class="admin-stat__label">Attente</dt>
|
||||||
<dd class="admin-stat__number"><?= $stats['pending'] ?></dd>
|
<dd class="admin-stat__number"><?= $stats['pending'] ?></dd>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
|
<button type="button" class="admin-btn admin-btn--sm" id="import-dialog-btn"
|
||||||
|
onclick="document.getElementById('import-dialog').showModal()">
|
||||||
|
Importer un CSV
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="admin-btn" id="import-dialog-btn"
|
|
||||||
onclick="document.getElementById('import-dialog').showModal()">
|
|
||||||
Importer un CSV
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php include APP_ROOT . '/templates/partials/flash-messages.php'; ?>
|
|
||||||
|
|
||||||
<!-- Filters -->
|
|
||||||
<form class="admin-filters" method="get" action="/admin/">
|
|
||||||
<input type="text" name="search" placeholder="Titre, auteur..."
|
|
||||||
value="<?= htmlspecialchars($searchQuery) ?>">
|
|
||||||
<select name="year">
|
|
||||||
<option value="">Toutes les années</option>
|
|
||||||
<?php foreach ($years as $y): ?>
|
|
||||||
<option value="<?= $y ?>" <?= $yearFilter == $y ? 'selected' : '' ?>><?= $y ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<select name="orientation">
|
|
||||||
<option value="">Toutes les orientations</option>
|
|
||||||
<?php foreach ($orientations as $o): ?>
|
|
||||||
<option value="<?= $o['id'] ?>" <?= $orientationFilter == $o['id'] ? 'selected' : '' ?>>
|
|
||||||
<?= htmlspecialchars($o['name']) ?>
|
|
||||||
</option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<button type="submit" class="admin-filters-btn">Filtrer</button>
|
|
||||||
<?php if ($searchQuery || $yearFilter || $orientationFilter): ?>
|
|
||||||
<a href="/admin/" class="admin-filters-reset"><span aria-hidden="true">✕ </span>Réinitialiser</a>
|
|
||||||
<?php endif; ?>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Bulk actions bar -->
|
<!-- Bulk actions bar -->
|
||||||
<div id="bulk-actions" class="admin-bulk-actions" role="toolbar" aria-label="Actions groupées">
|
<div id="bulk-actions" class="admin-bulk-actions" role="toolbar" aria-label="Actions groupées">
|
||||||
<strong><span id="selected-count">0</span> TFE(s) sélectionné(s)</strong>
|
<strong><span id="selected-count">0</span> TFE(s) sélectionné(s)</strong>
|
||||||
@@ -422,6 +435,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
'search' => $searchQuery,
|
'search' => $searchQuery,
|
||||||
'year' => $yearFilter ?: '',
|
'year' => $yearFilter ?: '',
|
||||||
'orientation' => $orientationFilter ?: '',
|
'orientation' => $orientationFilter ?: '',
|
||||||
|
'ap' => $apFilter ?: '',
|
||||||
]);
|
]);
|
||||||
include APP_ROOT . '/templates/partials/pagination.php';
|
include APP_ROOT . '/templates/partials/pagination.php';
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -386,7 +386,7 @@
|
|||||||
gap: var(--space-xs);
|
gap: var(--space-xs);
|
||||||
margin-bottom: var(--space-m);
|
margin-bottom: var(--space-m);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-end;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-filters input[type="text"],
|
.admin-filters input[type="text"],
|
||||||
@@ -425,8 +425,19 @@
|
|||||||
.admin-filters-reset {
|
.admin-filters-reset {
|
||||||
font-size: var(--step--1);
|
font-size: var(--step--1);
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
text-decoration: underline;
|
background: none;
|
||||||
|
border: 1px solid var(--border-primary);
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: inherit;
|
||||||
|
padding: var(--space-3xs) var(--space-xs);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: border-color 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-filters-reset:hover {
|
||||||
|
border-color: var(--text-secondary);
|
||||||
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Bulk actions bar ───────────────────────────────────────────────────── */
|
/* ── Bulk actions bar ───────────────────────────────────────────────────── */
|
||||||
@@ -906,26 +917,32 @@
|
|||||||
margin-top: var(--space-2xs);
|
margin-top: var(--space-2xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── List page header (title + stats row, then button) ──────────────────── */
|
/* ── List page toolbar (title + filters + stats + import, one row) ───────── */
|
||||||
.admin-list-header {
|
.admin-list-toolbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
align-items: flex-end;
|
|
||||||
gap: var(--space-s);
|
|
||||||
margin-bottom: var(--space-l);
|
|
||||||
}
|
|
||||||
|
|
||||||
.admin-list-header__top {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: var(--space-m);
|
gap: var(--space-m);
|
||||||
|
margin-bottom: var(--space-m);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-list-header h1 {
|
.admin-list-toolbar h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-list-toolbar .admin-filters {
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 0;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-list-toolbar__right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--space-s);
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Dialog ───────────────────────────────────────────────────────────── */
|
/* ── Dialog ───────────────────────────────────────────────────────────── */
|
||||||
|
|||||||
@@ -694,6 +694,11 @@ class Database {
|
|||||||
$params[] = intval($filters['orientation']);
|
$params[] = intval($filters['orientation']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($filters['ap'])) {
|
||||||
|
$sql .= " AND t.ap_program_id = ?";
|
||||||
|
$params[] = intval($filters['ap']);
|
||||||
|
}
|
||||||
|
|
||||||
$stmt = $this->pdo->prepare($sql);
|
$stmt = $this->pdo->prepare($sql);
|
||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
return (int) $stmt->fetchColumn();
|
return (int) $stmt->fetchColumn();
|
||||||
@@ -736,6 +741,11 @@ class Database {
|
|||||||
$params[] = intval($filters['orientation']);
|
$params[] = intval($filters['orientation']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($filters['ap'])) {
|
||||||
|
$sql .= " AND t.ap_program_id = ?";
|
||||||
|
$params[] = intval($filters['ap']);
|
||||||
|
}
|
||||||
|
|
||||||
$sql .= " GROUP BY t.id ORDER BY t.year DESC, t.submitted_at DESC";
|
$sql .= " GROUP BY t.id ORDER BY t.year DESC, t.submitted_at DESC";
|
||||||
|
|
||||||
if ($limit > 0) {
|
if ($limit > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user