This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/components/notifications/NotificationList.vue

125 lines
2.7 KiB
Vue

<template>
<div class="notifications">
<NavbarTriggerButton
:pressed="modalIsOpen"
ref="toggleButton"
:aria-label="modalIsOpen ? $t('notification.hideNotifications') : $t('notification.showNotifications')"
@click="togglePopup"
>
<span v-if="hasUnreadNotifications" class="unread-indicator" />
<icon icon="bell"/>
</NavbarTriggerButton>
<!-- FIXME: create dedicated dropdown menu -->
<CustomTransition name="fade">
<div class="notifications-list" v-if="modalIsOpen" ref="popup">
<h3 class="head">{{ $t('notification.title') }}</h3>
<NotificationItem
v-for="n in notifications"
:key="n.id"
class="notification-item"
:notification="n"
@markNotificationAsRead="emit('markNotificationAsRead', n)"
/>
<p class="nothing" v-if="notifications.length === 0">
{{ $t('notification.none') }}<br/>
<span class="explainer">
{{ $t('notification.explainer') }}
</span>
</p>
</div>
</CustomTransition>
</div>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import {onClickOutside} from '@vueuse/core'
import type {INotification} from '@/modelTypes/INotification'
import CustomTransition from '@/components/misc/CustomTransition.vue'
import NavbarTriggerButton from '@/components/home/NavbarTriggerButton.vue'
import NotificationItem from '@/components/notifications/NotificationItem.vue'
defineProps<{
notifications: INotification[],
hasUnreadNotifications: boolean,
}>()
const emit = defineEmits<{
(e: 'markNotificationAsRead', notification: INotification): void
}>()
const modalIsOpen = ref(false)
const popup = ref(null)
const toggleButton = ref(null)
function togglePopup() {
modalIsOpen.value = !modalIsOpen.value
}
onClickOutside(
popup,
() => {
if (!modalIsOpen.value) {
return
}
modalIsOpen.value = false
},
{ignore: [toggleButton]},
)
</script>
<style lang="scss" scoped>
.unread-indicator {
position: absolute;
top: .75rem;
right: 1.15rem;
width: .75rem;
height: .75rem;
background: var(--primary);
border-radius: 100%;
border: 2px solid var(--white);
}
.notifications-list {
position: fixed;
right: 1rem;
margin-top: 1rem;
max-height: 400px;
overflow-y: auto;
background: var(--white);
width: 350px;
max-width: calc(100vw - 2rem);
padding: .75rem .25rem;
border-radius: $radius;
box-shadow: var(--shadow-sm);
font-size: .85rem;
@media screen and (max-width: $tablet) {
max-height: calc(100vh - 1rem - #{$navbar-height});
}
}
.head {
font-family: $vikunja-font;
font-size: 1rem;
}
.notification-item:last-child {
margin-bottom: .25rem;
}
.nothing {
text-align: center;
padding: 1rem 0;
color: var(--grey-500);
}
.explainer {
font-size: .75rem;
}
</style>