Laravel

Un framework qui rend heureux

Voir cette catégorie
Vers le bas
Voir cette série
Mon CMS - Le profil
Mardi 3 septembre 2024 15:04

Notre CMS est maintenant bien équipé, offrant une présentation élégante de nos articles et commentaires, la possibilité de naviguer entre les catégories et de mener des recherches. L'authentification est également en place, mais cela ne suffit pas pour une expérience utilisateur complète. Pour répondre aux besoins de ces derniers, il est important de leur fournir un accès à leurs données personnelles et de leur permettre de les modifier à tout moment. Nous allons donc créer une page de profil dédiée à cette tâche.

Cette page de profil permettra aux utilisateurs d'effectuer diverses actions importantes :

  • Visualiser leur nom (non modifiable)
  • Modifier leur mot de passe (avec proposition d'un mot de passe sécurisé)
  • Supprimer leur compte

En créant cette page de profil, nous améliorerons considérablement l'expérience utilisateur de notre CMS, en leur donnant un contrôle sur leur présence sur le site.

Le composant pour le profil

On crée un composant pour la gestion du profil utilisateur :

php artisan make:volt auth/profile --class

Le PHP

Voici la partie PHP du code du composant :

<?php

use App\Models\User;
use Illuminate\Support\Facades\{Auth, Hash};
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;
use Mary\Traits\Toast;

new #[Title('Profile')] #[Layout('components.layouts.auth')] class extends Component {
    use Toast;

    public User $user;
    public string $email = '';
    public string $password = '';
    public string $password_confirmation = '';

    public function mount(): void
    {
        $this->user = Auth::user();
        $this->email = $this->user->email;
    }

    public function save(): void
    {
        $data = $this->validate([
            'email' => ['required', 'email', Rule::unique('users')->ignore($this->user->id)],
            'password' => 'confirmed',
        ]);

        if (!empty($data['password'])) {
            $data['password'] = Hash::make($data['password']);
        }

        $this->user->update($data);
        $this->success(__('Profile updated with success.'), redirectTo: '/profile');
    }

    public function deleteAccount(): void
    {
        $this->user->delete();
        $this->success(__('Account deleted with success.'), redirectTo: '/');
    }

    public function generatePassword($length = 16): void
    {
        $this->password = Str::random($length);
        $this->password_confirmation = $this->password;
    }
}; ?>

Ce code ne présente pas de difficulté particulière. Au montage du composant, on récupère seulement l'email. Pour la validation seul cet email est requis, le changement du mot de passe est optionnel. S'il est présent, alors on vérifie que la confirmation est correcte.

On a aussi une fonction pour générer un mot de passe aléatoire.

Le HTML

Le formulaire est généré par la partie HTML du composant :

<div>
    <x-card class="flex items-center justify-center h-screen" title="">

        <a href="/" title="{{ __('Go on site') }}">
            <x-card class="items-center py-0" title="{{ __('Update profile') }}" shadow separator
                progress-indicator></x-card>
        </a>

        <x-form wire:submit="save">

            <x-avatar :image="Gravatar::get($user->email)" class="!w-24">
                <x-slot:title class="pl-2 text-xl">
                    {{ $user->name }}
                </x-slot:title>
                <x-slot:subtitle class="flex flex-col gap-1 pl-2 mt-2 text-gray-500">
                    <x-icon name="c-user" label="{{ __('You can change your profile picture on Gravatar') }}" />
                    <a href="https://fr.gravatar.com/">
                        <x-icon name="c-user" label="{{ __('You can change your profile picture on Gravatar') }}" />
                    </a>
                </x-slot:subtitle>
            </x-avatar>

            <x-input label="{{ __('E-mail') }}" wire:model="email" icon="o-envelope" inline /><hr>
            <x-input label="{{ __('Password') }}" wire:model="password" icon="o-key" inline />
            <x-input label="{{ __('Confirm Password') }}" wire:model="password_confirmation" icon="o-key" inline />
            <x-button label="{{ __('Generate a secure password') }}" wire:click="generatePassword()" icon="m-wrench"
                class="btn-outline btn-sm" />

            <x-slot:actions>
                <x-button label="{{ __('Cancel') }}" link="/" class="btn-ghost" />
                <x-button label="{{ __('Delete account') }}" icon="c-hand-thumb-down"
                    wire:confirm="{{ __('Are you sure to delete your account?') }}" wire:click="deleteAccount"
                    class="btn-warning" />
                <x-button label="{{ __('Save') }}" icon="o-paper-airplane" spinner="save" type="submit"
                    class="btn-primary" />
            </x-slot:actions>

        </x-form>
    </x-card>
</div>

On retrouve l'utilisation du Gravatar comme on l'a déjà fait pour les commentaires, mais là, on va proposer à l'utilisateur, au moyen d'un lien, d'aller modifier son compte sur le site de Gravatar.

Ensuite, on a un formulaire classique avec des boutons de commande.

Les traductions

Comme d'habitude, on a besoin de nouvelles traductions :

"Update profile": "Modifier le profil",
"Your name can't be changed": "Votre nom ne peut pas être modifié",
"You can change your profile picture on Gravatar": "Vous pouvez changer votre image de profil sur Gravatar",
"Generate a secure password": "Créer un mot de passe sécurisé",
"Profile updated with success.": "Profil mis à jour avec succès.",
"Delete account": "Supprimer le compte",
"Are you sure to delete your account?": "Etes-vous sûr de vouloir supprimer votre compte ?",
"Profile": "Profil",

La route

Pour accéder au composant, on a besoin d'une route. On crée un groupe pour les utilisateurs authentifiés protégé par le middleware auth :

Route::middleware('auth')->group(function () {
	Volt::route('/profile', 'auth.profile')->name('profile');
});

Les menus

On doit pouvoir accéder à la page de profil à partir de la barre de navigation, mais aussi de la barre latérale.

Pour la barre de navigation (navigation.navbar) :

@if ($user = auth()->user())
    <x-dropdown>
        <x-slot:trigger>
            <x-button label="{{ $user->name }}" class="btn-ghost" />
        </x-slot:trigger>
        <x-menu-item title="{{ __('Profile') }}" link="{{ route('profile') }}" />

Et pour la barre latérale (navigation.sidebar) :

@if($user = auth()->user())
    <x-menu-separator />
        <x-list-item :item="$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-item title="{{ __('Profile') }}" icon="o-user" link="{{ route('profile') }}" />

Le formulaire

Voici l'aspect du formulaire :

On rappelle que le nom ne peut pas être modifié.

On a un lien pour diriger vers le site de Gravatar.

On a des zones de saisie pour l'email (au chargement, il apparaît l'email actuel de l'utilisateur) et le mot de passe.

Un bouton permet de générer un mot de passe sécurisé :

Pour la suppression du compte, une alerte est affichée pour éviter une manœuvre accidentelle :

Conclusion

Encore une fois, vous constatez avec quelle facilité Volt permet d'ajouter une fonctionnalité à notre CMS. Un composant, une route, quelques traductions, et ça fonctionne.

Pour vous simplifier la vie, vous pouvez charger le projet dans son état à l’issue de ce chapitre.



Par bestmomo

Aucun commentaire

Article précédent : Mon CMS - Les commentaires (2/2)
Article suivant : Mon CMS - Les favoris