DEV Community

Cover image for Notifications and Conclusion πŸŽ‰
Northon Iserhardt
Northon Iserhardt

Posted on

Notifications and Conclusion πŸŽ‰

Now, back to notifications

Now let's add a space in the navigation bar to display our notifications.

In resources/views/layouts/app.blade.php add the code below so we can use the material icons:
Image description

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
Enter fullscreen mode Exit fullscreen mode

Let's create the "notifications" component:
php artisan make:livewire components.notification

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

@livewire('components.notification')
Enter fullscreen mode Exit fullscreen mode

Mobile:
Image description

@livewire('components.notification')
Enter fullscreen mode Exit fullscreen mode

Let's incorporate Laravel Echo to monitor notification events. This way, as soon as a notification is received, we can dynamically reload the notifications and post listing components.

Image description

<script>
    document.addEventListener('DOMContentLoaded', () => {
        Echo.private('App.Models.User.{{auth()->user()->id}}')
            .notification(() => {
                Livewire.dispatch('refreshNotification');
                Livewire.dispatch('refreshPostList');
            });
    });
</script>
Enter fullscreen mode Exit fullscreen mode

In resources/views/livewire/components/notification.blade.php:
Image description

<div>
    <x-dropdown align="right" width="48">
        <x-slot name="trigger">
            <button
                class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
                <span class="rounded-full p-1 bg-red-500 text-white">17</span>
                <span class="material-symbols-outlined">
                    notifications
                </span>
            </button>
        </x-slot>
        <x-slot name="content">
            <div class="p-3 text-center">
                <p>some notifications</p>
            </div>
        </x-slot>
    </x-dropdown>
</div>
Enter fullscreen mode Exit fullscreen mode

Notification Class

As we are going to send our notifications via the database channel, we need to create the notifications table:
php artisan notifications:table
php artisan migrate

Now let's create a notification class:
php artisan make:notification PostCreated

A new directory containing our class will be created:
Image description

In app/Notifications/PostCreated.php we will add the broadcast settings:
The constructor:
Image description

    public $userId;
    public $dataNotify;

    /**
     * Create a new notification instance.
     */
    public function __construct($userId, $dataNotify)
    {
        $this->userId = $userId;
        $this->dataNotify = $dataNotify;
    }
Enter fullscreen mode Exit fullscreen mode

Channel and type:
Image description

    /**
     * Get the notification's delivery channels.
     *
     * @return array<int, string>
     */
    public function via(object $notifiable): array
    {
        return ['broadcast', 'database'];
    }

    public function broadcastType()
    {
        return 'broadcast.message';
    }
Enter fullscreen mode Exit fullscreen mode

Channel name and connection:
Image description

    public function toBroadcast(object $notifiable): BroadcastMessage
    {
        return (new BroadcastMessage($this->dataNotify))->onConnection('database');
    }

    public function broadcastOn(): Channel
    {
        return new PrivateChannel("App.Models.User.{$this->userId}");
    }
Enter fullscreen mode Exit fullscreen mode

To send notifications, we will choose to use the Notifiable trait, which is already incorporated into our User model by default. This gives us an efficient, out-of-the-box approach. For more information about how to use this trait: https://laravel.com/docs/10.x/notifications#using-the-notifiable-trait

In app/Livewire/Posts/PostCreate.php we will add the action of notifying users anytime they have been tagged:
Image description

if ($this->state['tagged_user_id']) {
    $taggedUser = User::query()->find($this->state['tagged_user_id']);
    $taggedUser?->notify(new PostCreated($taggedUser['id'], $this->state));
}
Enter fullscreen mode Exit fullscreen mode

The documentation explains the correct way to retrieve user notifications https://laravel.com/docs/10.x/notifications#accessing-the-notifications.

Let's add notification retrieval logic to app/Livewire/Components/Notification.php:
Image description

    protected $listeners = [
        'refreshNotification' => '$refresh'
    ];

    public $notifications;
    public $notificationsCounter;

    public function getNotifications()
    {
        $this->notifications = auth()->user()->unreadNotifications;
        $this->notificationsCounter = $this->notifications->count();

    }

    public function render()
    {
        $this->getNotifications();

        return view('livewire.components.notification');
    }
Enter fullscreen mode Exit fullscreen mode

And let's modify the blade to display the notification counter:
Image description

<div>
    <x-dropdown align="right" width="48">
        <x-slot name="trigger">
            <button
                class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
                @if($notificationsCounter)
                    <span class="rounded-full p-1 bg-red-500 text-white">{{$notificationsCounter}}</span>
                @endif
                <span class="material-symbols-outlined">
                    notifications
                </span>
            </button>
        </x-slot>
        <x-slot name="content">
            @foreach($notifications as $notification)
                <div class="p-3 text-center">
                    <p>You have been tagged in a new post!</p>
                </div>
            @endforeach
        </x-slot>
    </x-dropdown>
</div>
Enter fullscreen mode Exit fullscreen mode

Let's start our worker:
php artisan queue:work

At this moment, our notifications are already being processed in queues and being directed in real time to marked users, as follows:

Conclusion

We were able to build, step by step, the real-time notification functionality using Laravel and Livewire, following only the official documentation. Despite the success, there are still several possible features to improve the project, such as:

  • Creation of the validation layer.
  • Creation of the repository layer.
  • Pass data to the notification, such as the name of the person who tagged the user.
  • Mark notifications as read.

I'm leaving the repository link for anyone interested: https://github.com/northoniserhardt/still-loving-docs

Beyond this, you are the one who decides! Thank you very much for following the tutorial.

Top comments (0)