Files
BRETT/app/components/NotificationBell.vue
T
2026-10-03 20:07:49 +02:00

84 lines
3.0 KiB
Vue

<script setup lang="ts">
import { Button } from '@/components/ui/button'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
import type { AppNotification } from '@/composables/useNotifications'
const { notifications, unreadCount, markRead } = useNotifications()
const open = ref(false)
const timeAgo = useTimeAgo()
async function goTo(n: AppNotification) {
open.value = false
await markRead(n.id)
await navigateTo(`/thread/${n.uploadId}#comment-${n.commentId}`)
}
</script>
<template>
<Popover v-model:open="open">
<PopoverTrigger as-child>
<Button variant="ghost" size="icon" class="relative" aria-label="Benachrichtigungen">
<Icon name="ph:bell-fill" class="size-5" />
<span
v-if="unreadCount"
class="absolute -top-1 -right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-accent px-1 text-[10px] font-semibold text-accent-foreground"
>{{ unreadCount > 9 ? '9+' : unreadCount }}</span>
</Button>
</PopoverTrigger>
<PopoverContent align="end" class="w-80 gap-0 p-0">
<div class="max-h-96 overflow-y-auto">
<p v-if="!notifications.length" class="px-4 py-6 text-center text-sm text-muted-foreground">
Keine Benachrichtigungen.
</p>
<button
v-for="n in notifications"
:key="n.id"
type="button"
class="flex w-full items-center gap-3 border-b px-4 py-3 text-left text-sm transition-colors last:border-b-0 hover:bg-accent/10"
@click="goTo(n)"
>
<div class="size-12 shrink-0 overflow-hidden rounded-md bg-muted">
<NuxtImg
v-if="n.thumbUrl"
:src="n.thumbUrl"
:alt="n.actorName"
width="96"
height="96"
fit="cover"
class="h-full w-full object-cover"
/>
<video
v-else-if="n.uploadType === 'video'"
:src="n.url"
preload="metadata"
muted
playsinline
class="h-full w-full object-cover"
/>
<div v-else class="flex h-full w-full items-center justify-center">
<Icon name="ph:link-fill" class="size-4 text-muted-foreground" />
</div>
</div>
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-1.5">
<span
class="truncate font-medium"
:style="n.actorColor ? { color: n.actorColor } : undefined"
>{{ n.actorName }}</span>
<span class="shrink-0 text-muted-foreground">{{ n.isMention ? 'hat dich erwähnt' : 'hat kommentiert' }}</span>
<span class="ml-auto shrink-0 text-xs text-muted-foreground">{{ timeAgo(n.createdAt) }}</span>
</div>
<p class="mt-0.5 line-clamp-2 break-words text-muted-foreground">
{{ n.content }}
</p>
</div>
</button>
</div>
</PopoverContent>
</Popover>
</template>