DEV Community

Cover image for Criação, Listagem e Reatividade 📜
Northon Iserhardt
Northon Iserhardt

Posted on

Criação, Listagem e Reatividade 📜

Posts

Para prosseguirmos com as notificações, precisamos de eventos que as acionem. Como mencionado anteriormente, notificaremos um usuário sempre que ele for marcado em um post. Portanto, avançaremos para a criação dos posts.

Novos posts

Vamos adicionar a nossa navbar uma opção para o cadastro dos posts:
Image description

Em resources/views/livewire/layout/navigation.blade.php:
Image description

<x-nav-link :href="route('posts.index')" :active="request()->routeIs('posts.index')" wire:navigate>
    {{ __('Posts') }}
</x-nav-link>
Enter fullscreen mode Exit fullscreen mode

Image description

<x-responsive-nav-link :href="route('posts.index')" :active="request()->routeIs('posts.index')" wire:navigate>
    {{ __('Posts') }}
</x-responsive-nav-link>
Enter fullscreen mode Exit fullscreen mode

Através dos comandos do Laravel podemos criar vários recursos ao mesmo tempo, para mais detalhes https://laravel.com/docs/10.x/eloquent#generating-model-classes, no nosso caso vamos criar a Model, migration and controller with resources:
php artisan make:model -mrc Post

Em database/migrations/{date}_create_posts_table.php:
Image description

    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->foreignId('tagged_user_id')->nullable()->constrained('users')->cascadeOnDelete();
            $table->string('message', 280);
            $table->timestamps();
        });
    }
Enter fullscreen mode Exit fullscreen mode

tagged_user_id pode ser nula, visto que, um post pode ser criado sem ter que marcar alguém.

Vamos rodar as migrations:
php artisan migrate

Em routes/web.php:
Image description

Route::view('posts','posts.index')->middleware('auth')->name('posts.index');
Enter fullscreen mode Exit fullscreen mode

Em app/Models/Post.php:
Image description

    protected $fillable = [
      'user_id',
      'tagged_user_id',
      'message',
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function taggedUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'tagged_user_id');
    }
Enter fullscreen mode Exit fullscreen mode

Em app/Models/User.php:
Image description

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    public function taggedPosts(): HasMany
    {
        return $this->hasMany(Post::class, 'tagged_user_id');
    }
Enter fullscreen mode Exit fullscreen mode

Vamos criar os componentes de cadastro e listagem dos posts:
php artisan make:livewire posts.post-create
php artisan make:livewire posts.post-list

Vamos criar em resources/views/posts o arquivo index.blade.php, e importaremos o layout default com nossos componentes:
Image description

<x-app-layout>
    @livewire('posts.post-create')
    @livewire('posts.post-list')
</x-app-layout>
Enter fullscreen mode Exit fullscreen mode

Um ponto de atenção: Para tornar o projeto mais simples não trabalharemos com camadas de validação e repositório.

Em resources/views/livewire/posts/post-create.blade.php:
Image description

<div>
    <form class="grid grid-cols-2 max-w-xl mx-auto m-6" wire:submit.prevent="save">
        <textarea
            wire:model="state.message"
            placeholder="{{ __('Post Message') }}"
            class="col-span-2 w-full shadow rounded-lg border-gray-200"
        ></textarea>
        @error('state.message') <span class="error">{{ $message }}</span> @enderror

        <select wire:model="state.tagged_user_id" class="mt-4 border-gray-200 rounded-lg">
            <option value=""></option>
            @foreach($users as $user)
                <option value="{{$user->id}}">{{$user->name}}</option>
            @endforeach
        </select>
        @error('state.tagged_user_id') <span class="error">{{ $message }}</span> @enderror

        <div class="flex justify-end">
            <button class="w-16 rounded-lg mt-4 bg-blue-500 shadow text-white">{{ __('Save') }}</button>
        </div>
    </form>
</div>

Enter fullscreen mode Exit fullscreen mode

Vamos adicionar em app/Livewire/Posts/PostCreate.php:
Image description

    public $state = [
        'tagged_user_id' => null,
        'message' => ''
    ];

    public $users = null;

    public function mount()
    {
        $this->users = User::query()->get();
    }

    public function save(Request $request)
    {
        $this->validate([
            'state.message' => 'required|max:280',
            'state.tagged_user_id' => 'sometimes'
        ]);

        $request->user()->posts()->create($this->state);
        $this->reset('state');
    }
Enter fullscreen mode Exit fullscreen mode

Listagem dos posts

Agora, procederemos com a listagem dos posts, onde incluiremos tanto os posts que criamos quanto aqueles nos quais fomos marcados.

Em resources/views/livewire/post/post-list.blade.php:

Image description

<div>
    <div class="max-w-xl mx-auto mt-16">
        @foreach($posts as $post)
            <div class="bg-white p-6 rounded-md shadow-md text-center break-words mt-4">
                <p class="text-gray-700">
                    "{{$post->message}}"
                </p>
                <p class="text-blue-500 text-sm">{{ optional($post->taggedUser)->name ? '@'.$post->taggedUser->name : '' }}</p>
                <p class="text-end text-sm text-gray-500 mt-2">{{$post->user->name}}</p>
            </div>
        @endforeach
    </div>
</div>

Enter fullscreen mode Exit fullscreen mode

Em app/Livewire/Posts/PostList.php:

Image description

<?php

namespace App\Livewire\Posts;

use Livewire\Component;

class PostList extends Component
{
    public $posts;

    public function render()
    {
        $this->posts = auth()->user()->posts()
            ->orWhere('tagged_user_id', auth()->user()->id)
            ->orderBy('id', 'desc')
            ->get();

        return view('livewire.posts.post-list');
    }
}
Enter fullscreen mode Exit fullscreen mode

Reatividade

Quando um post é criado, é necessário recarregar a tela para visualizá-lo. No entanto, com Livewire, conseguimos tornar a listagem reativa. Isso significa que ao criarmos um post, a lista será atualizada automaticamente.

Mas como?
Vamos realizar um dispatch do componente de criação para o componente de listagem, indicando que é necessário atualizar a lista.

Em app/Livewire/Posts/PostCreate.php vamos adicionar o dispatch:

Image description

        $this->dispatch('refreshPostList');
Enter fullscreen mode Exit fullscreen mode

Em app/Livewire/Posts/PostList.php vamos adicionar nosso listener com o evento de refresh:
Image description

    protected $listeners = [
        'refreshPostList' => '$refresh'
    ];
Enter fullscreen mode Exit fullscreen mode

Pronto! Nossas funcionalidades já estão reativas.

Top comments (0)