Skip to content

Commit f4f7e8d

Browse files
committed
✨ mis en place des notifications
1 parent 54f415a commit f4f7e8d

File tree

17 files changed

+395
-2
lines changed

17 files changed

+395
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Models\Reply;
6+
7+
class ReplyAbleController extends Controller
8+
{
9+
public function redirect($id, $type)
10+
{
11+
$reply = Reply::where('replyable_id', $id)->where('replyable_type', $type)->firstOrFail();
12+
13+
return redirect(route_to_reply_able($reply->replyAble));
14+
}
15+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace App\Http\Livewire;
4+
5+
use Illuminate\Support\Facades\Auth;
6+
use Livewire\Component;
7+
8+
class NotificationCount extends Component
9+
{
10+
public int $count = 0;
11+
12+
protected $listeners = [
13+
'NotificationMarkedAsRead' => 'updateCount',
14+
];
15+
16+
public function updateCount(int $count): int
17+
{
18+
return $count;
19+
}
20+
21+
public function render()
22+
{
23+
$this->count = Auth::user()->unreadNotifications()->count();
24+
25+
return view('livewire.notification-count', [
26+
'count' => $this->count,
27+
]);
28+
}
29+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace App\Http\Livewire;
4+
5+
use Illuminate\Support\Facades\Auth;
6+
use Livewire\Component;
7+
8+
class NotificationIndicator extends Component
9+
{
10+
public bool $hasNotification = false;
11+
12+
protected $listeners = [
13+
'NotificationMarkedAsRead' => 'setHasNotification',
14+
];
15+
16+
public function setHasNotification(int $count): bool
17+
{
18+
return $count > 0;
19+
}
20+
21+
public function render()
22+
{
23+
$this->hasNotification = $this->setHasNotification(
24+
Auth::user()->unreadNotifications()->count(),
25+
);
26+
27+
return view('livewire.notification-indicator', [
28+
'hasNotification' => $this->hasNotification
29+
]);
30+
}
31+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace App\Http\Livewire;
4+
5+
use App\Policies\NotificationPolicy;
6+
use Carbon\Carbon;
7+
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
8+
use Illuminate\Notifications\DatabaseNotification;
9+
use Illuminate\Support\Facades\Auth;
10+
use Livewire\Component;
11+
use WireUi\Traits\Actions;
12+
13+
class Notifications extends Component
14+
{
15+
use Actions, AuthorizesRequests;
16+
17+
public $notificationId;
18+
19+
public function mount(): void
20+
{
21+
abort_if(Auth::guest(), 403);
22+
}
23+
24+
public function getNotificationProperty(): DatabaseNotification
25+
{
26+
return DatabaseNotification::findOrFail($this->notificationId);
27+
}
28+
29+
public function markAsRead(string $notificationId): void
30+
{
31+
$this->notificationId = $notificationId;
32+
33+
$this->authorize(NotificationPolicy::MARK_AS_READ, $this->notification);
34+
35+
$this->notification->markAsRead();
36+
37+
$this->notification()->success('Notification', 'Cette notification a été marquée comme lue.');
38+
39+
$this->emit('NotificationMarkedAsRead', Auth::user()->unreadNotifications()->count());
40+
}
41+
42+
public function render()
43+
{
44+
return view('livewire.notifications', [
45+
'notifications' => Auth::user()
46+
->unreadNotifications()
47+
->take(10)
48+
->get()
49+
->groupBy(
50+
fn ($notification) => Carbon::parse($notification->created_at)->format('M, Y')
51+
),
52+
]);
53+
}
54+
}

app/Notifications/YouWereMentioned.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public function toArray($notifiable): array
3939
'author_name' => $this->reply->author->name,
4040
'author_username' => $this->reply->author->username,
4141
'author_photo' => $this->reply->author->profile_photo_url,
42+
'replyable_id' => $this->reply->replyable_id,
4243
'replyable_type' => $this->reply->replyable_type,
4344
'replyable_subject' => $this->reply->replyAble->replyAbleSubject(),
4445
];
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Policies;
4+
5+
use App\Models\User;
6+
use Illuminate\Notifications\DatabaseNotification;
7+
8+
class NotificationPolicy
9+
{
10+
const MARK_AS_READ = 'markAsRead';
11+
12+
/**
13+
* Determine if the given notification can be marked as read by the user.
14+
*/
15+
public function markAsRead(User $user, DatabaseNotification $notification): bool
16+
{
17+
return $notification->notifiable->is($user);
18+
}
19+
}

app/Providers/AuthServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
use App\Models\Thread;
99
use App\Policies\ArticlePolicy;
1010
use App\Policies\DiscussionPolicy;
11+
use App\Policies\NotificationPolicy;
1112
use App\Policies\ReplyPolicy;
1213
use App\Policies\ThreadPolicy;
1314
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
15+
use Illuminate\Notifications\DatabaseNotification as Notification;
1416
use Illuminate\Support\Facades\Gate;
1517

1618
class AuthServiceProvider extends ServiceProvider
@@ -25,6 +27,7 @@ class AuthServiceProvider extends ServiceProvider
2527
Thread::class => ThreadPolicy::class,
2628
Reply::class => ReplyPolicy::class,
2729
Discussion::class => DiscussionPolicy::class,
30+
Notification::class => NotificationPolicy::class,
2831
];
2932

3033
/**

app/helpers.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,19 @@ function getFilter(string $key, array $filters = [], string $default = 'recent')
7979
return in_array($filter, $filters) ? $filter : $default;
8080
}
8181
}
82+
83+
if (! function_exists('route_to_reply_able')) {
84+
/**
85+
* Returns the route for the replyAble.
86+
*/
87+
function route_to_reply_able(mixed $replyAble)
88+
{
89+
if ($replyAble instanceof App\Models\Thread) {
90+
return route('forum.show', $replyAble->slug());
91+
}
92+
93+
if ($replyAble instanceof App\Models\Discussion) {
94+
return route('discussions.show', $replyAble->slug());
95+
}
96+
}
97+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
@php($data = $notification->data)
2+
3+
<li>
4+
<div class="relative pb-8">
5+
<span class="absolute top-5 left-5 -ml-px h-full w-0.5 bg-skin-footer" aria-hidden="true"></span>
6+
<div class="relative flex items-start space-x-8">
7+
<div class="whitespace-nowrap text-sm leading-5 text-skin-base">
8+
<div class="flex items-center space-x-3">
9+
<span class="p-2 flex items-center justify-center rounded-full bg-skin-card-gray">
10+
<x-heroicon-s-chat-alt class="w-5 h-5 text-skin-base"/>
11+
</span>
12+
<div>
13+
<p class="font-normal text-base leading-6">Un commentaire a été ajoutée dans la conversation <a href="{{ route('replyable', [$data['replyable_id'], $data['replyable_type']]) }}" class="text-skin-primary hover:text-skin-primary-hover">"{{ $data['replyable_subject'] }}"</a>.</p>
14+
<p class="mt-1 text-sm leading-5 text-skin-muted font-sans">
15+
<time-ago time="{{ $notification->created_at->getTimestamp() }}" />
16+
</p>
17+
</div>
18+
</div>
19+
</div>
20+
21+
<div class="whitespace-nowrap text-sm leading-5 text-skin-base text-right">
22+
<div class="flex justify-end -mt-3">
23+
<button wire:click="markAsRead('{{ $notification->id }}')" type="button" title="Marquer comme lue" class="inline-flex items-center justify-center p-2 bg-green-500 bg-opacity-10 text-green-600 text-sm leading-5 rounded-full focus:outline-none transform hover:scale-125 transition-all">
24+
<x-heroicon-s-check class="w-5 h-5" />
25+
</button>
26+
</div>
27+
</div>
28+
</div>
29+
</div>
30+
</li>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
@php($data = $notification->data)
2+
3+
<li>
4+
<div class="relative pb-8">
5+
<span class="absolute top-5 left-5 -ml-px h-full w-0.5 bg-skin-footer" aria-hidden="true"></span>
6+
<div class="relative flex items-start space-x-8">
7+
<div class="whitespace-nowrap text-sm leading-5 text-skin-base">
8+
<div class="flex items-center space-x-3">
9+
<span class="p-2 flex items-center justify-center rounded-full bg-skin-card-gray">
10+
<x-heroicon-s-at-symbol class="w-5 h-5 text-skin-base"/>
11+
</span>
12+
<div>
13+
<p class="font-normal text-base leading-6">
14+
<a href="{{ route('profile', $data['author_username']) }}" class="font-medium text-skin-primary">{{ $data['author_name'] }}</a>
15+
vous a mentionné dans <a href="{{ route('replyable', [$data['replyable_id'], $data['replyable_type']]) }}" class="text-skin-primary hover:text-skin-primary-hover">"{{ $data['replyable_subject'] }}"</a>.
16+
</p>
17+
<p class="mt-1 text-sm leading-5 text-skin-muted font-sans">
18+
<time-ago time="{{ $notification->created_at->getTimestamp() }}" />
19+
</p>
20+
</div>
21+
</div>
22+
</div>
23+
24+
<div class="whitespace-nowrap text-sm leading-5 text-skin-base text-right">
25+
<div class="flex justify-end -mt-3">
26+
<button wire:click="markAsRead('{{ $notification->id }}')" type="button" title="Marquer comme lue" class="inline-flex items-center justify-center p-2 bg-green-500 bg-opacity-10 text-green-600 text-sm leading-5 rounded-full focus:outline-none transform hover:scale-125 transition-all">
27+
<x-heroicon-s-check class="w-5 h-5" />
28+
</button>
29+
</div>
30+
</div>
31+
</div>
32+
</div>
33+
</li>

0 commit comments

Comments
 (0)