refactor: streamline NotificationBell component markup for improved readability and maintainability

This commit is contained in:
Yoga Pangestu 2026-06-30 17:23:43 +07:00
parent 9a0e7f552b
commit 67ae00384f

View File

@ -79,6 +79,7 @@ function openNotification(notification: NotificationItem): void {
if (!notification.is_read) {
void markAsRead(notification);
}
if (notification.url) {
isOpen.value = false;
router.visit(notification.url);
@ -180,11 +181,8 @@ onUnmounted(() => {
<PopoverTrigger as-child>
<Button variant="ghost" size="icon" class="relative size-8">
<Bell class="size-4" />
<Badge
v-if="unreadCount > 0"
variant="destructive"
class="absolute -top-1 -right-1 flex size-4 items-center justify-center rounded-full p-0 text-[10px]"
>
<Badge v-if="unreadCount > 0" variant="destructive"
class="absolute -top-1 -right-1 flex size-4 items-center justify-center rounded-full p-0 text-[10px]">
{{ unreadCount > 99 ? '99+' : unreadCount }}
</Badge>
</Button>
@ -199,8 +197,7 @@ onUnmounted(() => {
<TooltipTrigger as-child>
<button
class="flex items-center rounded p-1 text-muted-foreground hover:text-foreground"
@click="markAllAsRead"
>
@click="markAllAsRead">
<CheckCheck class="size-3.5" />
</button>
</TooltipTrigger>
@ -210,8 +207,7 @@ onUnmounted(() => {
<TooltipTrigger as-child>
<button
class="flex items-center rounded p-1 text-muted-foreground hover:text-destructive"
@click="deleteAll"
>
@click="deleteAll">
<Trash2 class="size-3.5" />
</button>
</TooltipTrigger>
@ -222,36 +218,23 @@ onUnmounted(() => {
<!-- List -->
<div class="max-h-80 overflow-y-auto">
<div
v-if="notifications.length === 0"
class="px-4 py-8 text-center text-sm text-muted-foreground"
>
<div v-if="notifications.length === 0" class="px-4 py-8 text-center text-sm text-muted-foreground">
Tidak ada notifikasi
</div>
<div
v-for="notification in notifications"
:key="notification.id"
<div v-for="notification in notifications" :key="notification.id"
class="group flex items-start gap-3 border-b px-4 py-3 transition-colors hover:bg-accent"
:class="{ 'bg-primary/5': !notification.is_read }"
>
:class="{ 'bg-primary/5': !notification.is_read }">
<!-- Unread dot -->
<div
class="mt-1.5 size-2 shrink-0 rounded-full"
:class="notification.is_read ? 'bg-transparent' : 'bg-primary'"
/>
<div class="mt-1.5 size-2 shrink-0 rounded-full"
:class="notification.is_read ? 'bg-transparent' : 'bg-primary'" />
<!-- Content -->
<div
class="min-w-0 flex-1 cursor-pointer"
@click="openNotification(notification)"
>
<div class="min-w-0 flex-1 cursor-pointer" @click="openNotification(notification)">
<p class="text-sm font-medium leading-tight">
{{ notification.title }}
</p>
<p
v-if="notification.body"
class="mt-0.5 text-xs leading-snug text-muted-foreground line-clamp-2"
>
<p v-if="notification.body"
class="mt-0.5 text-xs leading-snug text-muted-foreground">
{{ notification.body }}
</p>
<p class="mt-1 text-[10px] text-muted-foreground">
@ -261,14 +244,12 @@ onUnmounted(() => {
<!-- Actions -->
<div
class="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100"
>
class="flex shrink-0 items-center gap-0.5 opacity-0 transition-opacity group-hover:opacity-100">
<Tooltip v-if="!notification.is_read">
<TooltipTrigger as-child>
<button
class="rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
@click.stop="markAsRead(notification)"
>
@click.stop="markAsRead(notification)">
<Eye class="size-3.5" />
</button>
</TooltipTrigger>
@ -278,8 +259,7 @@ onUnmounted(() => {
<TooltipTrigger as-child>
<button
class="rounded p-1 text-muted-foreground hover:bg-muted hover:text-destructive"
@click.stop="deleteNotification(notification.id)"
>
@click.stop="deleteNotification(notification.id)">
<X class="size-3.5" />
</button>
</TooltipTrigger>