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