93 lines
2.7 KiB
Vue
93 lines
2.7 KiB
Vue
<template>
|
|
<USlideover v-model:open="isOpen" title="Benachrichtigungen">
|
|
<template #body>
|
|
<div v-if="notifications.length === 0" class="text-center py-8 text-muted">
|
|
<UIcon name="i-heroicons-bell-slash" class="h-8 w-8 mx-auto mb-2" />
|
|
<p>Keine Benachrichtigungen</p>
|
|
</div>
|
|
|
|
<NuxtLink
|
|
v-for="notification in notifications"
|
|
:key="notification.id"
|
|
:to="notification.clickTarget"
|
|
class="px-3 py-2.5 rounded-md hover:bg-elevated/50 flex items-center gap-3 relative -mx-3 first:-mt-3 last:-mb-3"
|
|
@click="onNotificationClick(notification)"
|
|
>
|
|
<UChip
|
|
:color="notification.type === 'ERROR' ? 'error' : notification.type === 'WARNING' ? 'warning' : 'primary'"
|
|
:show="!notification.isRead"
|
|
inset
|
|
>
|
|
<UIcon
|
|
:name="
|
|
notification.type === 'ERROR'
|
|
? 'i-heroicons-x-circle'
|
|
: notification.type === 'WARNING'
|
|
? 'i-heroicons-exclamation-triangle'
|
|
: 'i-heroicons-information-circle'
|
|
"
|
|
class="h-6 w-6"
|
|
/>
|
|
</UChip>
|
|
|
|
<div class="text-sm flex-1">
|
|
<p class="flex items-center justify-between">
|
|
<span class="text-highlighted font-medium">{{ notification.title }}</span>
|
|
|
|
<time
|
|
:datetime="notification.createdAt.toISOString()"
|
|
class="text-muted text-xs"
|
|
v-text="formatTimeAgo(notification.createdAt)"
|
|
/>
|
|
</p>
|
|
|
|
<p class="text-dimmed">
|
|
{{ notification.message }}
|
|
</p>
|
|
|
|
<div class="flex items-center gap-2 mt-1">
|
|
<UBadge
|
|
:color="notification.type === 'ERROR' ? 'error' : notification.type === 'WARNING' ? 'warning' : 'info'"
|
|
variant="subtle"
|
|
size="xs"
|
|
>
|
|
{{ notification.type }}
|
|
</UBadge>
|
|
</div>
|
|
</div>
|
|
</NuxtLink>
|
|
</template>
|
|
</USlideover>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { formatTimeAgo } from '@vueuse/core'
|
|
import type { NotificationDto } from '~~/.api-client'
|
|
|
|
const emit = defineEmits<{
|
|
'update:modelValue': [value: boolean]
|
|
}>()
|
|
|
|
const props = defineProps<{
|
|
modelValue: boolean
|
|
}>()
|
|
|
|
const isOpen = computed({
|
|
get: () => props.modelValue,
|
|
set: (value) => emit('update:modelValue', value)
|
|
})
|
|
|
|
const { notifications, fetchNotifications, handleNotificationClick } = useNotification()
|
|
|
|
watch(isOpen, async (newValue) => {
|
|
if (newValue) {
|
|
await fetchNotifications()
|
|
}
|
|
})
|
|
|
|
function onNotificationClick(notification: NotificationDto) {
|
|
handleNotificationClick(notification)
|
|
emit('update:modelValue', false)
|
|
}
|
|
</script>
|