Este é uma aplicação Laravel
utilizando a "extensão" Livewire
. Uma extensão reativa, que agiliza o desenvolvimento
com componentes reativo
"sem" o uso de javascript (Existe o javascript, mas não precisamos se preocupar com desenvolvimento).
Com livewire temos componentes responsivos e juntamente com o blade, temos uma ferramenta poderosa. Componentes que podemos atualizar sem precisar atualizar toda página de forma fácil e rápida.
- listagem de todas atividades Criação de compoenente
todo
e busca de atividades porquery
ewhen
para filtro e messagem de listagem vazia caso não tenha. - Filtro das atividades por
pendentes
econcluídas
Criação de propriedadefilter
com statusall, pending, done
para querywhen
. - Ordenação da listagem Utilização de
orderBy
porchecked
de atividades. Check
com input da atividade concluída Criação de input do typocheckbox
para concluir atividade com novo componenteitem
com metodo updatedTodo da propriedade PropriedadeTodo $todo
.- Reoordenação da listagem ao check da atividade Utilização de
event
livewire no compoenteItem
que vai aosalvar
fazer orefresh
na listagem do componentTodo
pelo eventoemitTo e listeners
. - Creação de atividade A criação da atividade irá receber via
click
o titulo da atividade e refresh na listatodo
. - Exclusão da atividade Uma deleção básica e refresh na lista
todo
. - No frontend: Layout responsivo e mode dark usando
Tailwindcss
.
Na versão 2.0 do app, além do layout novo
, foi adicionado propriedades computadas
do livewire, autorizações
de usuários
para suas atividades, autenticação
básica de login/logout para demonstração do que um usuário pode visualizar e interagir no app e por
fim notificações
para cada ação.
- Autenticação de usuário Criação demonstrativa de usuário direto pelo id.
- Politicas de Autenticação de usuário Usuários só podem criar, editar e deletar se estiverem logados.
- Autorização de ações Usuário não pode visualizar a deleção da atividade se a atividade não foi criada por ele.
- Negação de ações Usuário não pode editar atividade que não foi criada por ele.
- Notificações Criar notificações na tela para ações.
- Parametros da url Criar parametros nos filtro da URL para um histórico na navegação.
- Php
8.2
- Laravel
9.52.5
[Projeto laravel] composer create-project laravel/laravel name-project - Livewire
2.12
[Livewire] composer require livewire/livewire - laravel debugbar
3.8
[Debugbar] composer require barryvdh/laravel-debugbar --dev - Remixicon
2.5.0
Docs - Tailwindcss
3.3.3
[Tailwindcss] npm install -D tailwindcss postcss autoprefixer- Configuração do framework esta neste link Install Tailwind CSS with Laravel
- Alpine jS
2.8.2
Docs
php artisan serve --port=8000
[inicializando servidor]php artisan livewire:make todo
[Criando componente todo]php artisan make:model Todo -m
[Criado a tabela modelo para add propriedades]- checked boolean nullable false
- title string
php artisan make:factory TodoFactory --model=Todo
[Criado a migration para tabela no banco]- checked => $this->faker->boolean
- title => $this->faker->sentence
php artisan migrate --seed
[Criado a migration de todas tabelas no banco e seed populando dados fakes]- Criação do componentes de interação: A ideia é trabalhar com cada
componente livewire
de modo separado e não no proprio componentetodo
, para assim não ter um componente com muitas responsabilidades e desta forma cada componente tera a sua.php artisan livewire:make todo.item
[Criando componente todo item] | Componente que terá a responsabilidade de realizar o checked da atividade.php artisan livewire:make todo.create
[Criando componente todo create] | Componente que terá a responsabilidade de criar componente com seu titulo.php artisan livewire:make todo.delete
[Criando componente todo delete] | Componente que terá a responsabilidade de deletar a tividade.
View blade *todo*
- listagem
{{-- LIST TASKS --}}
@if(count($todos) > 0)
@foreach($todos as $todo)
<livewire:todo.item :todo="$todo" :key="$todo->id" />
@endforeach
@else
<div class="flex justify-center rounded-lg font-medium tracking-wide text-red-500 text-xs mt-6 mb-6">
<div>
Não existem tarefas registradas!
</div>
</div>
@endif
Diretiva | Explicação |
---|---|
@foreach($todos as $todo) |
Recebendo a listagem com todas atividades ou por filtro no componente todo com um foreach para mostrar cada um. |
<livewire:todo.item :todo="$todo" :key="$todo->id" /> |
Passando cada atividade para componente view item e para que cada tenha sua identificação para livewire, passamos o key do ID . |
View blade *create*
- Como passar dados de input para metodo com click Enter
.
<input wire:model.defer="title" wire:keydown.enter="save"
Controller *create*
public string $title ='';
public function save()
{
$this->validate(['title' => ['required', 'min:3']],
[
'title.required' => 'Descrição é obrigatória!',
'title.min'=> 'Mínimo de 3 letras, por favor!'
]);
Todo::create(['title' => $this->title]);
$this->reset('title');
$this->emitTo(\App\Http\Livewire\Todo::class, 'todo::created');
}
Controller *Todo*
protected $listeners = [
'todo::updated' => '$refresh',
'todo::created' => '$refresh',
'todo::deleted' => '$refresh'
];
Classe | Explicação importantes |
---|---|
validate(['title' => ['required', 'min:3']] |
* Validação de criação e mensagens personalizadas de cada tipo* |
$this->emitTo |
EmitTo é uma função que avisa um componente de alguma atividade realizada e apartir disso podemos por exemplo, realizar refresh |
- Estruturação de
migrate
emodel
da Todo.- Adição da foreignId
$table->foreignIdFor(\App\Models\User::class)->nullable();
- Adição da fillable user id
protected $fillable = ['title', 'checked', 'user_id']
- Metodo belongsTo da Todo pegar o usuário dono.
- Adição da foreignId
public function user(){
return $this->belongsTo(User::class);
}
- Criação de
factories e seeders
para popular banco.- Exemplo
User::updateOrCreate([
'name'=> 'Rafael Blum',
'email'=> 'Rafaelblum_digital@hotmail.com',
'email_verified_at' => now(),
'password'=> Hash::make('123'),
'remember_token' => Str::random(10),
]);
User::updateOrCreate([
'name' => fake()->name(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
]);
Todo::updateOrCreate([
'checked' => fake()->boolean,
'user_id' => User::where('email', 'Rafaelblum_digital@hotmail.com')->first()->id,
'title' => fake()->sentence
]);
-
Criação de politica todo.
php artisan make:policy TodoPolicy --model=Todo
[Criando politica] | Cria a policy e com o--model=Todo
cria todos metodos.
-
A criação de
notificações
seram acessados direto pelo componente que iráiniciar um evento
e assendo as props de componente do blade.
$this->emit('notifications', [
'type' => 'error',
'message' => 'Você precisa se logar para criar atividade'
]);
- Metodo da classe Notifications
protected $listeners = ['notifications'=>'notify'];
public function notify($props)
{
$this->message = $props['message'];
$this->type = $props['type'];
}
- view livewire e componente x-blade
<x-notification :type="$type">
{!! $message !!}
</x-notification>
@props([
'type'
])
<div {{$attributes->class([
'w-80 text-center text-sm mb-2 font-semibold tracking-wide cursor-pointer',
'text-yellow-500' => $type == 'warning',
'text-red-500' => $type == 'error',
'text-green-500' => $type == 'success',
'text-indigo-500' => $type == 'info',
])}} >
{{$slot}}
</div>
- Autorizações de ações.
- Atraves da Politica criada da todo, cada metodo ira retornar e verificar se o user id do user logado é igual ao id do user_id da tabela Todo.
return $user->is($todo->user);
- Na classe Delete, por exemplo.
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use AuthorizesRequests;
$this->authorize('delete', $this->todo);
- Outra forma de autorização é utilizando o
can()
if(!auth()->check() || !auth()->user()->can('update', $this->todo)){
$this->emit('notifications', [
'type' => "error",
'message' => "Você não pode finalizar a atividade <br> {$this->todo->title}"
]);
return;
}
- Nas views podemos também usar o @can()
- Aqui se não é sua atividade, você não terá acesso a visualização do componente.
@can('update', $todo)
...
@endcan