
Nous avons bien avancé avec les paramètres de notre boutique dans les articles précédents. Nous avons besoin de donner des informations à nos clients : conditions générales de vente, mentions légales, politique de confidentialité... Il nous faut donc pouvoir créer et modifier des pages contenant ces informations.
Vous pouvez trouver le code dans ce dépôt Github.
Conception du tableau de gestion des pages
Le tableau
Pour faciliter la gestion des pages, nous allons créer un tableau. Ce tableau rassemblera les informations clés de chaque page en un coup d'œil, permettant aux administrateurs de gérer efficacement le contenu. Voici les éléments que nous inclurons dans notre tableau :
- Titre
- Slug
En plus de ces informations de base, nous allons envisager d'ajouter une fonctionnalité supplémentaire pour améliorer l'expérience utilisateur :
- Suppression d'une page
Un composant pour le tableau
Il nous faut maintenant un composant Volt pour afficher le tableau :
php artisan make:volt admin/parameters/pages/index --class
Avec ce code :
<?php
use Livewire\Volt\Component;
use Livewire\Attributes\{Layout, Title};
use App\Models\Page;
use Mary\Traits\Toast;
new
#[Title('Pages')]
#[Layout('components.layouts.admin')]
class extends Component
{
use Toast;
public array $sortBy = [
'column' => 'title',
'direction' => 'asc',
];
public function headers(): array
{
return [
['key' => 'title', 'label' => __('Title')],
['key' => 'slug', 'label' => __('Slug')],
];
}
public function deletePage(Page $page): void
{
$page->delete();
$this->success(__('Page deleted successfully.'));
}
public function with(): array
{
return [
'pages' => Page::orderBy(...array_values($this->sortBy))->get(),
'headers' => $this->headers(),
];
}
}; ?>
<div>
<x-header title="{{ __('Pages') }}" separator progress-indicator>
<x-slot:actions>
<x-button
icon="s-building-office-2"
label="{{ __('Dashboard') }}"
class="btn-outline lg:hidden"
link="{{ route('admin') }}"
/>
<x-button
icon="o-plus"
label="{!! __('Create a new page') !!}"
link="/admin/pages/create"
spinner
class="btn-primary"
/>
</x-slot:actions>
</x-header>
<x-card>
<x-table
striped
:headers="$headers"
:rows="$pages"
:sort-by="$sortBy"
link="/admin/pages/{id}/edit"
>
@scope('actions', $page)
<x-popover>
<x-slot:trigger>
<x-button
icon="o-trash"
wire:click="deletePage({{ $page->id }})"
wire:confirm="{{ __('Are you sure you want to delete this page?') }}"
spinner
class="text-red-500 btn-ghost btn-sm"
/>
</x-slot:trigger>
<x-slot:content class="pop-small">
@lang('Delete')
</x-slot:content>
</x-popover>
@endscope
</x-table>
</x-card>
</div>
On ajoute ces traductions :
"Create a new page": "Création d'une nouvelle page",
"Page created successfully.": "Page crée avec succès.",
"Are you sure you want to delete this page?": "Voulez-vous vraiment supprimer cette page ?",
"Page deleted successfully.": "Page supprimée avec succès.",
La route
On ajoute une route pour l'atteindre :
Volt::route('/pages', 'admin.parameters.pages.index')->name('admin.parameters.pages.index');
La navigation
On ajoute un lien dans la barre latérale de l'administration :
<x-menu-item title="{{ __('Pages') }}" icon="o-document-duplicate" link="{{ route('admin.parameters.pages.index') }}" />
Et on a notre tableau :
Un formulaire pour les pages
On va avoir un formulaire commun pour la création et la modification d'une page. On ajoute une vue partielle pour ce formulaire :
Avec ce simple code :
<x-form wire:submit="save">
<x-input
label="{{ __('Title') }}"
wire:model.live.lazy="title"
required
placeholder="{!! __('Enter page title') !!}"
/>
<x-input
label="{{ __('Slug') }}"
wire:model="slug"
required
placeholder="{{ __('Enter unique slug') }}"
/>
<x-editor
wire:model="text"
label="{{ __('Text') }}"
:config="config('tinymce.config_page')"
folder="photos"
/>
<x-slot:actions>
<x-button
label="{{ __('Save') }}"
icon="o-paper-airplane"
spinner="save"
type="submit"
class="btn-primary"
/>
</x-slot:actions>
</x-form>
On a une configuration spécifique pour TinyMCE (config.tinymce) :
return [
...
'config_page' => [
'language' => env('APP_TINYMCE_LOCALE', 'en_US'),
'plugins' => 'codesample fullscreen',
'toolbar' => 'undo redo style | fontfamily fontsize | alignleft aligncenter alignright alignjustify | bullist numlist | copy cut paste pastetext | hr | codesample | link image quicktable | fullscreen',
'toolbar_sticky' => true,
'min_height' => 1000,
'license_key' => 'gpl',
'valid_elements' => '*[*]',
],
];
Et on ajoute une traduction :
"Enter page title": "Entrez le titre de la page",
Un trait pour les éléments communs
De la même manière, on va avoir des éléments PHP communs pour la création et la modification d'une page, on crée un trait :
On va y placer les propriétés, une petite fonction et les règles de validation :
<?php
namespace App\Traits;
use Illuminate\Support\Str;
trait ManagePage
{
public string $title = '';
public string $slug = '';
public string $text = '';
public function updatedTitle(): void
{
$this->slug = Str::slug($this->title);
}
protected function validatePageData(array $additionalData = []): array
{
$pageId = property_exists($this, 'page') && isset($this->page->id)
? ',' . $this->page->id
: '';
$rules = [
'title' => "required|string|max:100|unique:pages,title{$pageId}",
'slug' => "required|string|max:50|unique:pages,slug{$pageId}|regex:/^[a-z0-9-]+$/",
'text' => 'required|string|max:65535',
];
return $this->validate(array_merge($rules, $additionalData));
}
}
La création d'une page
On crée le composant pour la création d'une page :
php artisan make:volt admin/parameters/pages/create --class
Avec la création précédemment de la vue pour le formulaire et le trait, le code devient bien plus léger dans ce composant :
<?php
use Livewire\Volt\Component;
use Livewire\Attributes\{Layout, Title};
use App\Models\Page;
use Mary\Traits\Toast;
use App\Traits\ManagePage;
new
#[Title('Page creation')]
#[Layout('components.layouts.admin')]
class extends Component
{
use Toast, ManagePage;
public function save(): void
{
$data = $this->validatePageData();
Page::create($data);
$this->success(__('Page created successfully.'), redirectTo: '/admin/pages');
}
}; ?>
<div>
<x-header title="{!! __('Pages') !!}" separator progress-indicator >
<x-slot:actions>
<x-button
icon="s-building-office-2"
label="{{ __('Dashboard') }}"
class="btn-outline lg:hidden"
link="{{ route('admin') }}"
/>
</x-slot:actions>
</x-header>
<x-card title="{!! __('Create a new page') !!}">
@include('livewire.admin.parameters.pages.form')
</x-card>
</div>
On ajoute la route :
Volt::route('/states/create', 'admin.parameters.states.create')->name('admin.parameters.states.create');
Une traduction :
"Text": "Texte",
On obtient ce simple formulaire :
J'en suis là !
Vérifiez que tout fonctionne correctement, en particulier la validation.
La modification d'une page
On crée le composant pour la modification d'une page :
php artisan make:volt admin/parameters/pages/edit --class
Avec aussi un code simple :
<?php
use Livewire\Volt\Component;
use Livewire\Attributes\{Layout, Title};
use App\Models\Page;
use Mary\Traits\Toast;
use App\Traits\ManagePage;
new
#[Title('Page edition')]
#[Layout('components.layouts.admin')]
class extends Component
{
use Toast, ManagePage;
public Page $page;
public function mount(Page $page): void
{
$this->page = $page;
$this->fill($this->page);
}
public function save(): void
{
$data = $this->validatePageData();
$this->page->update($data);
$this->success(__('Page updated successfully.'), redirectTo: '/admin/pages');
}
}; ?>
<div>
<x-header title="{!! __('Pages') !!}" separator progress-indicator>
<x-slot:actions>
<x-button
icon="s-building-office-2"
label="{{ __('Dashboard') }}"
class="btn-outline lg:hidden"
link="{{ route('admin') }}"
/>
</x-slot:actions>
</x-header>
<x-card title="{!! __('Edit a page') !!}">
@include('livewire.admin.parameters.pages.form')
</x-card>
</div>
On ajoute la route :
Volt::route('/pages/{page}/edit', 'admin.parameters.pages.edit')->name('admin.parameters.pages.edit');
Des traductions :
"Edit a page": "Modification d'une page",
"Page updated successfully.": "Page mise à jour avec succès.",
On a le même formulaire que pour la création, mais renseigné avec les données de la page sélectionnée :
Conclusion
On en a fini avec la gestion des pages. Dans la prochaine étape, on s'occupera des frais de port.
Par bestmomo
Nombre de commentaires : 2