feat: add delete all notifications feature in NotificationController and update NotificationBell component

This commit is contained in:
Yoga Pangestu 2026-08-15 11:09:23 +07:00
parent 22c9a4cf2a
commit ae376342af
3 changed files with 56 additions and 11 deletions

View File

@ -67,4 +67,11 @@ public function markAllAsRead(Request $request): JsonResponse
return response()->json(['message' => 'All notifications marked as read.']);
}
public function deleteAll(Request $request): JsonResponse
{
$request->user()->notifications()->delete();
return response()->json(['message' => 'All notifications deleted.']);
}
}

View File

@ -1,5 +1,5 @@
import { router } from '@inertiajs/react';
import { Bell, Check, Trash2 } from 'lucide-react';
import { Bell, Check, CheckCheck, Trash2 } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
@ -121,6 +121,22 @@ export function NotificationBell() {
}
}, []);
const deleteAll = useCallback(async () => {
try {
await fetch('/api/notifications', {
method: 'DELETE',
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
});
setNotifications([]);
setUnreadCount(0);
} catch {
// Silently fail
}
}, []);
useEffect(() => {
// eslint-disable-next-line react-hooks/set-state-in-effect -- initial data fetch is safe
void fetchUnreadCount();
@ -165,16 +181,34 @@ export function NotificationBell() {
<DropdownMenuContent align="end" className="max-h-[350px] w-80">
<div className="flex items-center justify-between border-b px-4 py-2">
<span className="text-sm font-semibold">Notifikasi</span>
{unreadCount > 0 && (
<button
onClick={() => {
void markAllAsRead();
}}
className="text-xs text-muted-foreground hover:text-foreground"
>
Tandai semua dibaca
</button>
)}
<div className="flex items-center gap-1">
{unreadCount > 0 && (
<Button
variant="ghost"
size="icon"
className="h-6 w-6"
title="Tandai semua sudah dibaca"
onClick={() => {
void markAllAsRead();
}}
>
<CheckCheck className="h-3.5 w-3.5" />
</Button>
)}
{notifications.length > 0 && (
<Button
variant="ghost"
size="icon"
className="h-6 w-6 text-destructive hover:text-destructive"
title="Hapus semua notifikasi"
onClick={() => {
void deleteAll();
}}
>
<Trash2 className="h-3.5 w-3.5" />
</Button>
)}
</div>
</div>
{notifications.length === 0 ? (
<div className="px-4 py-6 text-center text-sm text-muted-foreground">

View File

@ -41,3 +41,7 @@
Route::patch('/notifications/read-all', [NotificationController::class, 'markAllAsRead'])
->middleware(['web', 'auth', 'verified'])
->name('notifications.mark-all-as-read');
Route::delete('/notifications', [NotificationController::class, 'deleteAll'])
->middleware(['web', 'auth', 'verified'])
->name('notifications.delete-all');