Logomark

LARAVEL

Un framework qui rend heureux
Voir cette catégorie
Vers le bas
Voir cette série
Shop : les pays
Vendredi 7 février 2025 18:13

Nous avons déjà bien avancé le paramétrage de notre boutique. Dans le présent article, nous allons nous occuper des pays. Selon la destination d'expédition des commandes, on n'aura pas le même taux de TVA à appliquer. Par exemple, la TVA est à 20% au sein de l'Union européenne, mais à zéro dans un pays comme la Suisse. La gestion des pays sera très simple parce qu'on a peu de données à manipuler.

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

Un formulaire pour les pays

On va avoir un formulaire commun pour la création et la modification d'un pays. On ajoute une vue partielle pour ce formulaire :

Avec un code léger :

<x-form wire:submit="save">
    <x-input 
        label="{{ __('Name') }}" 
        wire:model="name" 
        required 
        placeholder="{{ __('Enter name') }}" 
    />

    <x-input 
        type="text" 
        wire:model="tax" 
        label="{{ __('VAT') }}" 
        required 
        placeholder="{{ __('Enter VAT (e.g., 0.2)') }}" 
    />

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

On ajoute les deux traductions :

"Enter name": "Entrez le nom",
"Enter VAT (e.g., 0.2)": "Entrez la TVA (par exemple, 0.2)",

Le tableau des pays

Un composant pour le tableau

Il nous faut un composant Volt pour afficher le tableau et le formulaire de création d'un pays :

php artisan make:volt admin/parameters/countries/index --class

Avec ce code :

<?php

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

new 
#[Title('Countries')] 
#[Layout('components.layouts.admin')] 
class extends Component
{
    use Toast, WithPagination;
    
    public string $name;
    public string $tax;
    public array $sortBy = ['column' => 'name', 'direction' => 'asc'];

    public function headers(): array
	{
		return [['key' => 'name', 'label' => __('Name')], ['key' => 'tax', 'label' => __('VAT')]];
	}

    public function save(): void
    {
        $data = $this->validate([
            'name' => 'required|string|max:100|unique:countries,name',
            'tax' => 'required|numeric|between:0,0.4',
        ]);

        $country = Country::create($data);

        $ranges = Range::all();
        foreach($ranges as $range) {
            $range->countries()->attach($country, ['price' => 0]);
        }

        $this->success(__('Country created successfully.'));
    }

    public function deleteCountry(Country $country): void
    {
        $country->delete(); 
        $this->success(__('Country deleted successfully.'));
    }

    public function with(): array
	{
		return [
			'countries' => Country::orderBy(...array_values($this->sortBy))->paginate(10),
			'headers' => $this->headers(),
		];
	}
    
}; ?>

<div>
    <x-header title="{{ __('Countries') }}" 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>
        <x-table striped :headers="$headers" :rows="$countries" :sort-by="$sortBy" link="/admin/countries/{id}/edit" with-pagination >
            @scope('actions', $country)
                <x-popover>
                    <x-slot:trigger>
                        <x-button icon="o-trash" wire:click="deleteCountry({{ $country->id }})"
                            wire:confirm="{{ __('Are you sure to delete this country?') }}" 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>
    <x-card title="{!! __('Create a new country') !!}">
        @include('livewire.admin.parameters.countries.form')
    </x-card>
</div>

Pour la validation, on a besoin d'une traduction dans fr.validation :

'tax'  => 'TVA',

On ajoute quelques traductions :

"Create a new country": "Création d'un nouveau pays",
"Country created successfully.": "Pays créé avec succès.",
"Are you sure to delete this country?": "Voulez-vous vraiment supprimer ce pays ?",
"Country deleted successfully.": "Pays supprimé avec succès.",
"Countries": "Pays",

La route

On ajoute une route pour l'atteindre :

Volt::route('/countries', 'admin.parameters.countries.index')->name('admin.parameters.countries.index');

La navigation

On ajoute un lien dans la barre latérale de l'administration :

<x-menu-item title="{{ __('Countries') }}" icon="c-map-pin" link="{{ route('admin.parameters.countries.index') }}" />

Et on a notre tableau avec le formulaire de création intégré :

Vérifiez que la validation fonctionne :

Et que vous pouvez bien créer et supprimer un pays.

La modification d'un pays

On crée le composant pour la modification d'un pays :

php artisan make:volt admin/parameters/countries/edit --class

Avec aussi un code simple :

<?php

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

new #[Title('Dashboard')] #[Layout('components.layouts.admin')] class extends Component
{
    use Toast;
    
    public Country $country;
    public string $name;
    public string $tax;

    public function mount(Country $country): void
    {
        $this->country = $country;
        $this->fill($this->country);
    }

    public function save(): void
    {
        $data = $this->validate([
            'name' => 'required|string|max:100',
            'tax' => 'required|numeric|between:0,0.4',
        ]);

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

        $this->success(__('Country updated successfully.'), redirectTo: '/admin/countries');
    }
   
}; ?>

<div>
    <x-header title="{{ __('Countries') }}" 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 country') !!}">
        @include('livewire.admin.parameters.countries.form')
    </x-card>
</div>

Quelques traductions :

"Edit a country": "Modification d'un pays",
"Country updated successfully.": "Pays mis à jour avec succès.",

On ajoute la route :

Volt::route('/countries/{country}/edit', 'admin.parameters.countries.edit')->name('admin.parameters.countries.edit');

On a le même formulaire que pour la création, mais renseigné avec les données du pays sélectionné :

Conclusion

On en a fini avec la gestion des pays. Dans la prochaine étape, on s'occupera des pages d'information de la boutique.



Par bestmomo

Aucun commentaire

Article précédent : Shop : états de commande
Article suivant : Shop : les pages