131 lines
4.2 KiB
Vue
131 lines
4.2 KiB
Vue
<script setup>
|
|
import {formatTimeAgo} from '@vueuse/core'
|
|
|
|
const { isNotificationsSlideoverOpen } = useDashboard()
|
|
const toast = useToast()
|
|
const desktopPush = useDesktopPush()
|
|
|
|
watch(isNotificationsSlideoverOpen, async (newVal,oldVal) => {
|
|
if(newVal === true) {
|
|
await setup()
|
|
}
|
|
})
|
|
|
|
const notifications = ref([])
|
|
|
|
const setup = async () => {
|
|
try {
|
|
notifications.value = await useNuxtApp().$api("/api/notifications")
|
|
await desktopPush.loadConfig()
|
|
} catch (e) {
|
|
notifications.value = []
|
|
}
|
|
}
|
|
|
|
setup()
|
|
|
|
const setNotificationAsRead = async (notification) => {
|
|
try {
|
|
await useNuxtApp().$api(`/api/notifications/${notification.id}/read`, {
|
|
method: "POST"
|
|
})
|
|
} catch (e) {
|
|
// noop: endpoint optional in older/newer backend variants
|
|
}
|
|
setup()
|
|
|
|
}
|
|
|
|
const enableDesktopPush = async () => {
|
|
const success = await desktopPush.subscribe()
|
|
|
|
toast.add({
|
|
title: success ? "Desktop Push aktiviert" : "Desktop Push konnte nicht aktiviert werden",
|
|
description: desktopPush.error.value || undefined,
|
|
color: success ? "success" : "error"
|
|
})
|
|
}
|
|
|
|
const sendTestPush = async () => {
|
|
try {
|
|
await desktopPush.sendTestPush()
|
|
toast.add({ title: "Testbenachrichtigung gesendet", color: "success" })
|
|
await setup()
|
|
} catch (error) {
|
|
toast.add({
|
|
title: "Testbenachrichtigung fehlgeschlagen",
|
|
description: error?.data?.error || error?.message,
|
|
color: "error"
|
|
})
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<USlideover v-model:open="isNotificationsSlideoverOpen" title="Benachrichtigungen" side="right">
|
|
<template #body>
|
|
<div class="mb-4 rounded-md border border-default bg-muted p-3">
|
|
<div class="flex items-start justify-between gap-3">
|
|
<div class="min-w-0">
|
|
<p class="text-sm font-medium text-highlighted">
|
|
Desktop Push
|
|
</p>
|
|
<p class="mt-1 text-xs text-muted">
|
|
<span v-if="!desktopPush.supported.value">Dieser Browser unterstützt Desktop Push nicht.</span>
|
|
<span v-else-if="!desktopPush.configured.value">Desktop Push ist im Backend noch nicht konfiguriert.</span>
|
|
<span v-else-if="desktopPush.permission.value === 'granted'">Benachrichtigungen sind im Browser erlaubt.</span>
|
|
<span v-else>Aktiviere Browser-Benachrichtigungen für FEDEO.</span>
|
|
</p>
|
|
</div>
|
|
<div class="flex shrink-0 gap-2">
|
|
<UButton
|
|
icon="i-heroicons-bell-alert"
|
|
size="xs"
|
|
color="primary"
|
|
variant="soft"
|
|
:loading="desktopPush.loading.value"
|
|
:disabled="!desktopPush.supported.value || !desktopPush.configured.value"
|
|
@click="enableDesktopPush"
|
|
>
|
|
Aktivieren
|
|
</UButton>
|
|
<UButton
|
|
icon="i-heroicons-paper-airplane"
|
|
size="xs"
|
|
color="neutral"
|
|
variant="outline"
|
|
:disabled="desktopPush.permission.value !== 'granted'"
|
|
@click="sendTestPush"
|
|
>
|
|
Test
|
|
</UButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<NuxtLink
|
|
v-for="notification in notifications"
|
|
:key="notification.id"
|
|
:to="notification.payload?.link || notification.link || '/'"
|
|
class="p-3 rounded-md hover:bg-gray-50 dark:hover:bg-gray-800/50 cursor-pointer flex items-center gap-3 relative"
|
|
@click="setNotificationAsRead(notification)"
|
|
>
|
|
<UChip color="primary" :show="!notification.read && !notification.readAt" inset>
|
|
<UAvatar alt="FEDEO" size="md" />
|
|
</UChip>
|
|
|
|
<div class="text-sm flex-1">
|
|
<p class="flex items-center justify-between">
|
|
<span class="text-gray-900 dark:text-white font-medium">{{notification.title}}</span>
|
|
|
|
<time :datetime="notification.date || notification.createdAt || notification.created_at" class="text-gray-500 dark:text-gray-400 text-xs" v-text="formatTimeAgo(new Date(notification.createdAt || notification.created_at))" />
|
|
</p>
|
|
<p class="text-gray-500 dark:text-gray-400">
|
|
{{ notification.message }}
|
|
</p>
|
|
</div>
|
|
</NuxtLink>
|
|
</template>
|
|
</USlideover>
|
|
</template>
|