Logomark

LARAVEL

Un framework qui rend heureux
Voir cette catégorie
Vers le bas
Voir cette série
Shop : la boutique
Vendredi 7 février 2025 12:49

Nous avons dans le précédent article mis en place la gestion de notre catalogue. Nous allons à présent coder le paramétrage de la boutique pour préciser nom, adresse, téléphone, compte bancaire, modes de paiement... Tout un tas de renseignements indispensables qui peuvent évoluer au fil du temps : changement d'adresse, de banque, de paiements autorisés, d'informations livrées en page d'accueil...

Vous pouvez trouver le code dans ce dépôt Github.

TinyMCE

Pour renseigner le contenu des informations variables de la boutique (et plus tard le contenu des pages), on va avoir besoin d'un éditeur performant. On va s'en sortir élégamment parce que MaryUI intègre TinyMCE dans un composant. Il existe deux façons de l'utiliser :

La première option est plus simple à mettre en place, mais le plan gratuit est limité à 1000 chargements mensuels de l'éditeur. La seconde option est plus longue à mettre en place, mais vous n'avez aucune limitation de chargement. On va donc choisir la seconde possibilité. Évidemment, les mises à jour dans ce cas ne seront pas automatiques, contrairement à la première option.

Télécharger et copiez tous les fichiers ici :

Il faut ensuite configurer l'éditeur en fonction de nos besoins. En particulier les commandes à prévoir dans la barre d'outils et les plugins utiles. Il y a plusieurs façons pour le faire, le plus logique me semble d'utiliser un fichier de configuration :

Avec ce code :

<?php

return [
	'config' => [
		'language'       => env('APP_TINYMCE_LOCALE', 'en_US'),
		'plugins'        => 'fullscreen',
		'toolbar'        => 'undo redo style | fontfamily fontsize | alignleft aligncenter alignright alignjustify | bullist numlist | copy cut paste pastetext | hr | link image quicktable | fullscreen',
		'toolbar_sticky' => true,
		'min_height'     => 50,
		'license_key'    => 'gpl',
		'valid_elements' => '*[*]',
	],
];

On voit que la locale pour le langage est récupéré dans le fichier .env, on l'ajoute dans ce fichier :

APP_TINYMCE_LOCALE=fr_FR

Mais pour que ça fonctionne, il faut aussi charger les traductions, vous trouvez les gratuites sur cette page. Chargez le français et mettez le fichier ici :

On prévoit le plugin "full screen" pour avoir l'éditeur en plein écran au besoin.

Dans notre layout admin, on doit charger la librairie :

<head>
    ...

    <script src="{{ asset('storage/scripts/tinymce.min.js') }}" referrerpolicy="origin"></script>
</head>

Un composant pour la boutique

On crée le composant pour la gestion des paramètres de la boutique :

php artisan make:volt admin/parameters/store --class

Avec un code un peu chargé :

<?php

use Livewire\Volt\Component;
use Livewire\Attributes\{Layout, Title};
use App\Models\Shop;
use Mary\Traits\Toast;

new 
#[Title('Store')] 
#[Layout('components.layouts.admin')] 
class extends Component
{
    use Toast;
    
    public Shop $shop;
    public string $name;
    public string $address;
    public string $email;
    public string $phone;
    public string $facebook;
    public string $holder;
    public string $bank;
    public string $bank_address;
    public string $bic;
    public string $iban;
    public string $home;
    public string $home_infos;
    public string $home_shipping;
    public bool $invoice;
    public bool $billing;
    public bool $card;
    public bool $transfer;
    public bool $check;
    public bool $mandat;

    public function mount(): void
    {
        $this->shop = Shop::firstOrFail();

        $this->fill($this->shop);
    }

    public function save(): void
    {
        $data = $this->validate([
            'name' => 'required|string|max:255',
            'address' => 'required|string|max:255',
            'holder' => 'required|string|max:255',
            'email' => 'required|string|email|max:255',
            'bic' => 'required|regex:/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i',
            'iban' => 'required|regex:/^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4,}$/',
            'bank' => 'required|string|max:255',
            'bank_address' => 'required|string|max:255',
            'phone' => 'required|regex:/^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/|max:25',
            'facebook' => 'required|url|regex:/^(https?:\/\/)?(www\.)?facebook\.com\/.+/i|max:255',
            'home' => 'required|string|max:16777215',
            'home_infos' => 'required|string|max:16777215',
            'home_shipping'=> 'required|string|max:16777215',
            'invoice' => 'required|boolean',
            'card' => 'required|boolean',
            'transfer' => 'required|boolean',
            'check' => 'required|boolean',
            'mandat' => 'required|boolean',
        ]);

        $this->shop->update($data);

        $this->success(__('Store updated with success.'));
    }
    
}; ?>

<div>
    <x-header title="{{ __('Store') }}" 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 shadow separator progress-indicator >
        <x-form wire:submit="save">
            <x-card title="{{ __('Identity') }}" shadow separator >
                <div class="space-y-2">
                    <x-input label="{{ __('Name') }}" wire:model="name" required />
                    <x-input label="{{ __('Address') }}" wire:model="address" required />
                    <x-input label="{{ __('Email') }}" wire:model="email" required />
                    <x-input label="{{ __('Phone') }}" wire:model="phone" required />
                    <x-input label="{{ __('Facebook') }}" wire:model="facebook" required />
                </div>
            </x-card>
            <x-card title="{{ __('Bank') }}" shadow separator >
                <div class="space-y-2">
                    <x-input label="{{ __('Holder') }}" wire:model="holder" required />
                    <x-input label="{{ __('Name') }}" wire:model="bank" required />
                    <x-input label="{{ __('Address') }}" wire:model="bank_address" required />
                    <x-input label="{{ __('BIC') }}" wire:model="bic" required />
                    <x-input label="{{ __('IBAN') }}" wire:model="iban" required />
                </div>
            </x-card>
            <x-card title="{{ __('Home') }}" shadow separator >
                <div class="space-y-2">
                    <x-editor wire:model="home" label="{{ __('Title') }}" :config="config('tinymce.config')" folder="photos" />
                    <x-editor wire:model="home_infos" label="{{ __('General informations') }}" :config="config('tinymce.config')" folder="photos" />
                    <x-editor wire:model="home_shipping" label="{{ __('Shipping costs') }}" :config="config('tinymce.config')" folder="photos" />
                </div>
            </x-card>
            <x-card title="{{ __('Billing') }}" shadow separator >
                <x-checkbox label="{{ __('Activation of billing') }}" wire:model="invoice" />
            </x-card>
            <x-card title="{{ __('Accepted payment methods') }}" shadow separator >
                <div class="space-y-4">
                    <x-checkbox label="{{ __('Credit card') }}" wire:model="card" />
                    <x-checkbox label="{{ __('Bank transfer') }}" wire:model="transfer" />
                    <x-checkbox label="{{ __('Check') }}" wire:model="check" />
                    <x-checkbox label="{{ __('Administrative mandate') }}" wire:model="mandat" />
                </div>
            </x-card>

            <x-slot:actions>
                <x-button 
                    label="{{ __('Save') }}" 
                    icon="o-paper-airplane" 
                    spinner="save" 
                    type="submit"
                    class="btn-primary" />
            </x-slot:actions>
        </x-form>
    </x-card>
</div>

On a encore besoin de traductions :

"Edit a product": "Modification d'un produit",
"Store": "Boutique",
"Phone": "Téléphone",
"Bank": "Banque",
"Holder": "Titulaire",
"Accepted payment methods": "Moyens de paiement acceptés",
"Store updated with success.": "Boutique mise à jour avec succès.",
"Shipping costs": "Frais de livraison",
"Title": "Titre",
"Activation of billing": "Activation de la facturation",

Dans la validation également :

'holder'             => 'titulaire',
'bank_address'       => 'adresse de la banque',

Une route pour atteindre le composant :

Route::middleware(IsAdmin::class)->prefix('admin')->group(function ()
{
	...
	Volt::route('/store', 'admin.parameters.store')->name('admin.parameters.store');

Et on complète la barre de navigation latérale :

<x-menu-sub title="{{ __('Settings') }}" icon="s-cog-8-tooth">
    <x-menu-item title="{{ __('Store') }}" icon="c-building-storefront" link="{{ route('admin.parameters.store') }}" />
</x-menu-sub>

Une petite traduction :

"Store": "Boutique",

Dans la partie supérieure, on a l'identité de la boutique :

Puis les informations bancaires : 

Suivent les informations livrées sur la page d'accueil (boostées par TinyMCE) :

Et enfin l'activation de la facturation et des différents modes de paiement :

Conclusion

On peut désormais modifier tous les paramètres de la boutique à partir de l'administration. Dans le prochain article, on continuera le paramétrage.



Par bestmomo

Aucun commentaire

Article précédent : Shop : le catalogue
Article suivant : Shop : états de commande