diff --git a/TODO.md b/TODO.md
index 432b505..14371b8 100644
--- a/TODO.md
+++ b/TODO.md
@@ -44,7 +44,7 @@ PHP has no component system, but `include`/`require` with variable scoping works
### Shared UI partials — `templates/partials/`
- [x] **`pagination.php`** — pagination nav is duplicated between `index.php` and `search.php` with minor variations; unify into one partial accepting `$page`, `$totalPages`, `$baseParams[]`
-- [ ] **`status-badge.php`** — the published/pending badge + access badge pattern is repeated in `index.php` admin table rows; extract into a partial
+- [x] **`status-badge.php`** — the published/pending badge + access badge pattern is repeated in `index.php` admin table rows; extract into a partial
- [ ] **`admin-alert.php`** — rename/merge `flash-messages.php` to also handle the 3 different legacy flash key patterns (`$_SESSION['error']`, `$_SESSION['admin_error']`, `$_SESSION['edit_error']`, etc.) that pages still consume manually instead of via `App::consumeFlash()`
## System Page Caching — Database-Backed Status Cache
diff --git a/public/admin/account.php b/public/admin/account.php
index 1f4e758..783a225 100644
--- a/public/admin/account.php
+++ b/public/admin/account.php
@@ -33,20 +33,12 @@ if (empty($_SESSION['csrf_token'])) {
Authentification PHP
-
- Active
-
- Non configurée
-
+
Fichier de configuration
config/admin_credentials.php
-
- Présent
-
- Absent
-
+
diff --git a/public/admin/index.php b/public/admin/index.php
index a12523d..d3c1f1e 100644
--- a/public/admin/index.php
+++ b/public/admin/index.php
@@ -187,20 +187,9 @@ document.addEventListener('DOMContentLoaded', () => {
= htmlspecialchars($thesis['orientation'] ?? 'N/A') ?> |
= htmlspecialchars($thesis['ap_program'] ?? 'N/A') ?> |
-
- ● Publié
-
- ◌ En attente
-
+
- '○', 'interne' => '◑', 'interdit' => '●'];
- $accessSymbol = $accessSymbols[$accessSlug] ?? '●';
- ?>
-
- = $accessSymbol ?> = htmlspecialchars($thesis['access_type']) ?>
-
+
|
diff --git a/templates/partials/status-badge.php b/templates/partials/status-badge.php
new file mode 100644
index 0000000..5c1b96a
--- /dev/null
+++ b/templates/partials/status-badge.php
@@ -0,0 +1,67 @@
+ with a decorative symbol,
+ * an aria-label, and the visible label text.
+ *
+ * Variables (set before include):
+ *
+ * $badgeType (string) One of:
+ * 'publish' — publish/pending state (uses $badgeValue as bool)
+ * 'access' — access-type label (uses $badgeValue as string name)
+ * 'ok' — generic green/yellow ok-or-warn (uses $badgeValue as bool)
+ *
+ * $badgeValue (mixed) Meaning depends on $badgeType (see above).
+ *
+ * $badgeOkLabel (string, optional) Label when ok/published/true. Default: 'Oui'
+ * $badgeWarnLabel (string, optional) Label when warn/pending/false. Default: 'Non'
+ * $badgeContext (string, optional) Prefix for aria-label, e.g. 'Statut'.
+ * When empty the visible label is used directly.
+ *
+ * Example — publish badge:
+ *
+ *
+ * Example — access badge:
+ *
+ *
+ * Example — generic ok badge:
+ *
+ */
+
+$badgeType = $badgeType ?? 'ok';
+$badgeValue = $badgeValue ?? false;
+$badgeOkLabel = $badgeOkLabel ?? 'Oui';
+$badgeWarnLabel = $badgeWarnLabel ?? 'Non';
+$badgeContext = $badgeContext ?? null; // null = use visible label as aria-label
+
+if ($badgeType === 'publish') {
+ $isOk = (bool) $badgeValue;
+ $symbol = $isOk ? '●' : '◌';
+ $cssClass = $isOk ? 'status-published' : 'status-pending';
+ $visibleLabel = $isOk ? 'Publié' : 'En attente';
+ $ariaLabel = 'Statut : ' . $visibleLabel;
+} elseif ($badgeType === 'access') {
+ $accessName = (string) $badgeValue;
+ $accessSlug = strtolower(preg_replace('/[^a-z]/i', '', $accessName));
+ $symbols = ['libre' => '○', 'interne' => '◑', 'interdit' => '●'];
+ $symbol = $symbols[$accessSlug] ?? '●';
+ $cssClass = 'status-access status-access--' . $accessSlug;
+ $visibleLabel = $accessName;
+ $ariaLabel = 'Accès : ' . $visibleLabel;
+} else {
+ // 'ok' — generic boolean badge
+ $isOk = (bool) $badgeValue;
+ $symbol = $isOk ? '●' : '◌';
+ $cssClass = $isOk ? 'status-published' : 'status-pending';
+ $visibleLabel = $isOk ? $badgeOkLabel : $badgeWarnLabel;
+ $ariaLabel = $badgeContext !== null
+ ? ($badgeContext !== '' ? $badgeContext . ' : ' . $visibleLabel : $visibleLabel)
+ : $visibleLabel;
+}
+?>
+= $symbol ?> = htmlspecialchars($visibleLabel) ?>
+ |