QuickAdminPanel: Livewire+Tailwind Version

In April 2021, we released a separate QuickAdminPanel version that generates the code with Livewire and Tailwind, using the modern TALL stack.

Notice: this version is available only for the Yearly Plan customers.

Here are a few screenshots of a simple adminpanel, fully generated without writing a single line of code:

For the design, we're using a theme Notus JS by Creative Tim.

Structure of Generated Code

We believe that Laravel Livewire is really powerful for dynamic elements on the pages, so every inner page in our adminpanel is a Livewire component that you can customize however you want.

So, the main project structure is good old Laravel with Routes and Blade, and inside of each resources/views/admin/xxxxx.blade.php you will find a line similar to this:

<div class="card-body">
    @livewire('transaction.create')
</div>

It means that there are three separate Livewire components for each CRUD:

  • Create Page;

  • Edit Page;

  • Index Page.

Typical code of Livewire component:

app/Http/Livewire/Transaction/Index.php

<?php

namespace App\Http\Livewire\Transaction;

use App\Http\Livewire\WithConfirmation;
use App\Http\Livewire\WithSorting;
use App\Models\Transaction;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Gate;
use Livewire\Component;
use Livewire\WithPagination;

class Index extends Component
{
    use WithPagination;
    use WithSorting;
    use WithConfirmation;

    public int $perPage;

    public array $orderable;

    public string $search = '';

    public array $selected = [];

    public array $paginationOptions;

    protected $queryString = [
        'search' => [
            'except' => '',
        ],
        'sortBy' => [
            'except' => 'id',
        ],
        'sortDirection' => [
            'except' => 'desc',
        ],
    ];

    public function getSelectedCountProperty()
    {
        return count($this->selected);
    }

    public function updatingSearch()
    {
        $this->resetPage();
    }

    public function updatingPerPage()
    {
        $this->resetPage();
    }

    public function resetSelected()
    {
        $this->selected = [];
    }

    public function mount()
    {
        $this->sortBy            = 'id';
        $this->sortDirection     = 'desc';
        $this->perPage           = 100;
        $this->paginationOptions = config('project.pagination.options');
        $this->orderable         = (new Transaction())->orderable;
    }

    public function render()
    {
        $query = Transaction::advancedFilter([
            's'               => $this->search ?: null,
            'order_column'    => $this->sortBy,
            'order_direction' => $this->sortDirection,
        ]);

        $transactions = $query->paginate($this->perPage);

        return view('livewire.transaction.index', compact('query', 'transactions', 'transactions'));
    }

    public function deleteSelected()
    {
        abort_if(Gate::denies('transaction_delete'), Response::HTTP_FORBIDDEN, '403 Forbidden');

        Transaction::whereIn('id', $this->selected)->delete();

        $this->resetSelected();
    }

    public function delete(Transaction $transaction)
    {
        abort_if(Gate::denies('transaction_delete'), Response::HTTP_FORBIDDEN, '403 Forbidden');

        $transaction->delete();
    }
}

For Datatables, we don't use any external packages, as we believe it's not needed in this case - all the pagination/filtering/sorting could happen directly in the component, using the power of some reusable Traits.

For Roles/Permissions, we use the core Laravel Gate functionality, without any external packages. You can read more about it here.

You can look at the full code of this example adminpanel in this public repository.

Last updated