
Maintenant que nous avons créé la partie visuelle de la boutique, autrement dénommée frontend, nous allons à présent nous consacrer à la partie cachée, l'administration, aussi dénommée backend. Nous allons conserver la même architecture avec MaryUi et Volt pour rester cohérent. On pourrait utiliser n'importe quel autre environnement et même passer par des solutions toutes prêtes comme Filament que j'aime bien. Cependant, il est bien plus pertinent d'un point de vue didactique de développer complètement cette partie.
Vous pouvez trouver le code dans ce dépôt Github.
Un middleware
Pour les besoins de l'administration, on aura souvent besoin de savoir si l'utilisateur connecté est administrateur pour filtrer les accès correspondants.
Un middleware dans Laravel est une couche intermédiaire qui traite les requêtes HTTP avant qu'elles n'atteignent les contrôleurs ou après qu'elles aient été traitées par les contrôleurs. Il permet d'exécuter des tâches spécifiques, comme l'authentification, la validation, la journalisation, ou la modification des requêtes et des réponses. Les middlewares sont utilisés pour centraliser et organiser le code qui doit être exécuté à chaque requête, ce qui facilite la maintenance et la réutilisation du code.
On commence par ajouter une méthode dans le modèle User :
public function isAdmin(): bool
{
return 'admin' === $this->role;
}
On crée un middleware pour sélectionner les administrateurs :
php artisan make:middleware IsAdmin
public function handle(Request $request, Closure $next): Response
{
if (!auth()->user()->isAdmin()) {
abort(403);
}
return $next($request);
}
Le layout
Au niveau du layout, nous n'allons pas avoir les mêmes besoins que pour l'authentification et l'affichage de la boutique. On va donc créer un layout spécifique pour cette partie. En particulier, on va se contenter d'une barre latérale de navigation.
La barre de navigation
On crée le composant pour la barre de navigation :
php artisan make:volt admin/sidebar --class
Avec ce code :
<?php
use Illuminate\Support\Facades\{Auth, Session};
use Livewire\Volt\Component;
new class() extends Component
{
public function logout(): void
{
Auth::guard('web')->logout();
Session::invalidate();
Session::regenerateToken();
$this->redirect('/');
}
}; ?>
<div>
<x-menu activate-by-route>
<x-menu-separator />
<x-list-item :item="Auth::user()" value="name" sub-value="email" no-separator no-hover class="-mx-2 !-my-2 rounded">
<x-slot:actions>
<x-button icon="o-power" wire:click="logout" class="btn-circle btn-ghost btn-xs"
tooltip-left="{{ __('Logout') }}" no-wire-navigate />
</x-slot:actions>
</x-list-item>
<x-menu-separator />
<x-menu-item title="{{ __('Dashboard') }}" icon="s-building-office-2" link="{{ route('admin') }}" />
<x-menu-item icon="m-arrow-right-end-on-rectangle" title="{{ __('Go on store') }}" link="/" />
<x-menu-item>
<x-theme-toggle />
</x-menu-item>
</x-menu>
</div>
Vous avez sans doute remarqué qu'on a une route que nous n'avons pas encore créée, mais ça ne va pas tarder.
Le layout
Maintenant, nous pouvons ajouter notre layout :
Avec ce code :
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ isset($title) ? $title . ' | ' . config('app.name') : config('app.name') }}</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen font-sans antialiased bg-base-200/50 dark:bg-base-200">
{{-- MAIN --}}
<x-main full-width>
{{-- SIDEBAR --}}
<x-slot:sidebar drawer="main-drawer" collapsible class="bg-base-100">
<livewire:admin.sidebar />
</x-slot:sidebar>
<x-slot:content>
<!-- Drawer toggle for "main-drawer" -->
<label for="main-drawer" class="mr-3 lg:hidden">
<x-icon name="o-bars-3" class="cursor-pointer" />
</label>
{{ $slot }}
</x-slot:content>
</x-main>
{{-- TOAST area --}}
<x-toast />
</body>
</html>
Un composant pour le tableau de bord
Il ne nous manque plus que le composant pour notre tableau de bord :
php artisan make:volt admin/index --class
Ajoutez ce code :
<?php
use App\Models\{ Order, Product, User };
use Livewire\Attributes\{Layout, Title};
use Livewire\Volt\Component;
new
#[Title('Dashboard')]
#[Layout('components.layouts.admin')]
class extends Component
{
public bool $openGlance = true;
public function with(): array
{
return [
'productsCount' => Product::count(),
'ordersCount' => Order::whereRelation('state', 'indice', '>', 3)
->whereRelation('state', 'indice', '<', 6)
->count(),
'usersCount' => User::count(),
];
}
}; ?>
<div>
<x-collapse wire:model="openGlance" class="shadow-md">
<x-slot:heading>
@lang('In a glance')
</x-slot:heading>
<x-slot:content class="flex flex-wrap gap-4">
<a href="/" class="flex-grow">
<x-stat
title="{{ __('Active products') }}"
description=""
value="{{ $productsCount }}"
icon="s-shopping-bag"
class="shadow-hover" />
</a>
<a href="/" class="flex-grow">
<x-stat
title="{{ __('Successful orders') }}"
description=""
value="{{ $ordersCount }}"
icon="s-shopping-cart"
class="shadow-hover" />
</a>
<a href="/" class="flex-grow">
<x-stat
title="{{ __('Customers') }}"
description=""
value="{{ $usersCount }}"
icon="s-user"
class="shadow-hover" />
</a>
</x-slot:content>
</x-collapse>
</div>
On ajoute la route :
use App\Http\Middleware\IsAdmin;
...
Route::middleware('auth')->group(function () {
...
Route::middleware(IsAdmin::class)->prefix('admin')->group(function ()
{
Volt::route('/dashboard', 'admin.index')->name('admin');
});
On a besoin de quelques traductions :
"In a glance": "En un coup d'oeil",
"Dashboard": "Tableau de bord",
"Active products": "Produits actifs",
"Validated orders": "Commandes validées",
"Customers": "Clients",
"Go on store": "Aller sur la boutique",
"Successful orders": "Commandes validées",
Avec l'URL /admin/dashboard, on arrive maintenant sur le tableau de bord :
On affiche sur ce tableau de bord quelques statistiques concernant les produits, les commandes validées et les clients. Pour le moment, les liens ne mènent nulle part, nous complèterons cela lorsque nous coderons les gestions correspondantes.
On pourra ajouter plus tard d'autres informations dans le tableau de bord.
La navigation
Il faut prévoir un accès au tableau de bord à partir de la barre de navigation de la boutique (navigation.navbar) :
@if ($user = auth()->user())
<x-dropdown>
<x-slot:trigger>
<x-button label="{{ $user->name }} {{ $user->firstname }}" class="btn-ghost" />
</x-slot:trigger>
<span class="text-black">
@if ($user->isAdmin())
<x-menu-item title="{{ __('Administration') }}" link="{{ route('admin') }}" />
@endif
Et il ne faut pas oublier la barre latérale (navigation.sidebar) :
<x-menu-separator />
@if ($user->isAdmin())
<x-menu-item title="{{ __('Administration') }}" icon="s-building-office-2" link="{{ route('admin') }}" />
@endif
<x-menu-separator />
Conclusion
La base de notre administration est désormais en place. Dans le prochain article, on complètera avec la gestion des commandes. Pour le tableau de bord, on verra plus tard avec quoi on le complète, si vous avez des idées...
Par bestmomo
Aucun commentaire