From 4d87c341aa8853d9100f3fda0d45ffcee4e2c5f8 Mon Sep 17 00:00:00 2001 From: Imugiii Date: Thu, 18 Jun 2026 10:16:03 +0000 Subject: [PATCH] feat(admin): dashboard branche aux donnees reelles (compteurs catalogue + stock critique) KPI du tableau de bord cables sur StatsRepository (seam testable comme StatsController) : produits actifs, categories, menus, ingredients en stock critique (RG-T21). Vue A+C (tuiles + alerte rouge conditionnelle). Le feed d'activite reste a faire (choix produit sur le contenu/gating des evenements audit). Tests verts (PHPUnit 301, PHPStan L6). --- src/app/Controllers/DashboardController.php | 20 ++++++- src/app/Views/admin/dashboard.php | 59 +++++++++++++++++--- tests/Unit/Admin/DashboardControllerTest.php | 32 +++++++++++ 3 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/app/Controllers/DashboardController.php b/src/app/Controllers/DashboardController.php index e85511c..9ce7f91 100644 --- a/src/app/Controllers/DashboardController.php +++ b/src/app/Controllers/DashboardController.php @@ -4,12 +4,14 @@ declare(strict_types=1); namespace App\Controllers; +use App\Catalogue\StatsRepository; use App\Core\Response; /** * Tableau de bord back-office. GET /admin/dashboard (landing par defaut du role - * admin, cf. seed role.default_route). Accessible a tout utilisateur authentifie ; - * les KPI reels (stats.read) seront ajoutes au chunk statistiques. + * admin, cf. seed role.default_route). Accessible a tout utilisateur authentifie. + * Affiche des indicateurs synthetiques (catalogue + sante stock) ; le detail vit + * sous /admin/stats (permission stats.read). * * Non `final` : les tests sous-classent pour injecter des doubles via les hooks. */ @@ -25,10 +27,22 @@ class DashboardController extends AdminController return $guard; } + $stats = $this->statsRepository(); + return $this->adminView( 'admin/dashboard', - ['title' => 'Tableau de bord - Wakdo Admin', 'activeNav' => 'dashboard'], + [ + 'title' => 'Tableau de bord - Wakdo Admin', + 'activeNav' => 'dashboard', + 'counts' => $stats->counts(), + 'stock' => $stats->stockHealth(), + ], $guard, ); } + + protected function statsRepository(): StatsRepository + { + return new StatsRepository($this->db()); + } } diff --git a/src/app/Views/admin/dashboard.php b/src/app/Views/admin/dashboard.php index 50f9e89..a7c7ef8 100644 --- a/src/app/Views/admin/dashboard.php +++ b/src/app/Views/admin/dashboard.php @@ -3,24 +3,65 @@ declare(strict_types=1); /** - * Fragment du tableau de bord, injecte dans admin/layout.php. Volontairement - * minimal en chunk shell : les KPI reels (ventes, commandes) viendront avec le - * chunk statistiques (permission stats.read). + * Tableau de bord, injecte dans admin/layout.php (direction UI A+C). + * Indicateurs synthetiques catalogue + sante stock (StatsRepository). * - * @var string $currentUserName + * @var string $currentUserName + * @var array> $counts + * @var array{bands:array} $stock */ $name = htmlspecialchars($currentUserName ?? 'Utilisateur', ENT_QUOTES, 'UTF-8'); + +$kpi = isset($counts) && is_array($counts) ? $counts : []; +$stk = isset($stock) && is_array($stock) ? $stock : []; + +$nProducts = (int) ($kpi['products']['available'] ?? 0); +$nCategories = (int) ($kpi['categories']['total'] ?? 0); +$nMenus = (int) ($kpi['menus']['total'] ?? 0); +$nCritical = (int) ($stk['bands']['critical'] ?? 0); ?> -
-

Le back-office est en ligne. Utilisez la navigation pour gerer le catalogue, - les commandes et les utilisateurs selon vos permissions.

-

Les indicateurs (ventes, commandes du jour) seront ajoutes prochainement.

+
+
+
+ + En vente +
+
+
Produits actifs
+
+ +
+
+ + Classees +
+
+
Categories
+
+ +
+
+ + Proposes +
+
+
Menus
+
+ +
+
+ + 0 ? 'A recommander' : 'OK' ?> +
+
+
Stock critique
+
diff --git a/tests/Unit/Admin/DashboardControllerTest.php b/tests/Unit/Admin/DashboardControllerTest.php index 7e7ca0d..b1c79b7 100644 --- a/tests/Unit/Admin/DashboardControllerTest.php +++ b/tests/Unit/Admin/DashboardControllerTest.php @@ -10,6 +10,7 @@ use App\Auth\GuardResult; use App\Auth\SessionGuard; use App\Auth\SessionManager; use App\Auth\UserDirectory; +use App\Catalogue\StatsRepository; use App\Controllers\DashboardController; use App\Core\Config; use App\Core\Database; @@ -17,6 +18,32 @@ use App\Core\Request; use App\Core\Response; use App\Tests\Support\FakeDatabase; +/** + * Stub de StatsRepository : KPIs canned, sans base (les agregats reels sont + * couverts par StatsRepositoryDbTest). + */ +final class DashStubStatsRepository extends StatsRepository +{ + public function counts(): array + { + return [ + 'products' => ['total' => 53, 'available' => 50], + 'categories' => ['total' => 9, 'active' => 9], + 'menus' => ['total' => 13, 'available' => 12], + 'ingredients' => ['total' => 7, 'active' => 6], + ]; + } + + public function stockHealth(): array + { + return [ + 'active_total' => 6, + 'bands' => ['normal' => 4, 'low' => 1, 'critical' => 1], + 'alerts' => [], + ]; + } +} + /** * Sous-classe de test : injecte session test + FakeDatabase dans la garde, * l'autorisation et l'annuaire, sans base reelle. @@ -53,6 +80,11 @@ final class TestDashboardController extends DashboardController return new UserDirectory($this->fakeDb); } + protected function statsRepository(): StatsRepository + { + return new DashStubStatsRepository($this->fakeDb); + } + /** * Expose le chemin garde par permission d'AdminController::guard() (RG-T03), * que le dashboard (auth seule) n'exerce pas. -- 2.45.3