feat(#36): Notification rework with single and all comments mark as read
This commit is contained in:
193
legalconsenthub/stores/useNotificationStore.ts
Normal file
193
legalconsenthub/stores/useNotificationStore.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { NotificationDto } from '~~/.api-client'
|
||||
import { useNotificationApi } from '~/composables/notification/useNotificationApi'
|
||||
import { useLogger } from '~/composables/useLogger'
|
||||
import { useUserStore } from './useUserStore'
|
||||
|
||||
export const useNotificationStore = defineStore('Notification', () => {
|
||||
const logger = useLogger().withTag('notificationStore')
|
||||
const userStore = useUserStore()
|
||||
const { user } = useUserSession()
|
||||
|
||||
const {
|
||||
getNotifications,
|
||||
getUnreadNotifications,
|
||||
getUnreadNotificationCount,
|
||||
markAllNotificationsAsRead,
|
||||
markNotificationAsRead,
|
||||
clearAllNotifications,
|
||||
deleteNotification
|
||||
} = useNotificationApi()
|
||||
|
||||
// State
|
||||
const notifications = ref<NotificationDto[]>([])
|
||||
const unreadNotifications = ref<NotificationDto[]>([])
|
||||
const unreadCount = ref<number>(0)
|
||||
const isLoading = ref(false)
|
||||
|
||||
// Getters
|
||||
const hasUnread = computed(() => unreadCount.value > 0)
|
||||
const organizationId = computed(() => userStore.selectedOrganization?.id)
|
||||
const userId = computed(() => user.value?.keycloakId)
|
||||
|
||||
// Actions
|
||||
async function fetchNotifications(page: number = 0, size: number = 20) {
|
||||
if (!organizationId.value) {
|
||||
logger.warn('No organization selected')
|
||||
return
|
||||
}
|
||||
isLoading.value = true
|
||||
try {
|
||||
const response = await getNotifications(organizationId.value, page, size)
|
||||
notifications.value = response.content || []
|
||||
return response
|
||||
} catch (error) {
|
||||
logger.error('Failed to fetch notifications:', error)
|
||||
throw error
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUnreadNotifications() {
|
||||
if (!organizationId.value) {
|
||||
logger.warn('No organization selected')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const response = await getUnreadNotifications(organizationId.value)
|
||||
unreadNotifications.value = response || []
|
||||
return response
|
||||
} catch (error) {
|
||||
logger.error('Failed to fetch unread notifications:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchUnreadCount() {
|
||||
if (!userId.value || !organizationId.value) {
|
||||
logger.warn('No user or organization selected')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const count = await getUnreadNotificationCount(userId.value, organizationId.value)
|
||||
unreadCount.value = count || 0
|
||||
return count
|
||||
} catch (error) {
|
||||
logger.error('Failed to fetch unread count:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function markAllAsRead() {
|
||||
if (!organizationId.value) {
|
||||
logger.warn('No organization selected')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await markAllNotificationsAsRead(organizationId.value)
|
||||
unreadCount.value = 0
|
||||
unreadNotifications.value = []
|
||||
notifications.value = notifications.value.map((n) => ({ ...n, isRead: true }))
|
||||
} catch (error) {
|
||||
logger.error('Failed to mark all as read:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function markAsRead(notificationId: string) {
|
||||
if (!organizationId.value) {
|
||||
logger.warn('No organization selected')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await markNotificationAsRead(notificationId, organizationId.value)
|
||||
const index = notifications.value.findIndex((n) => n.id === notificationId)
|
||||
if (index !== -1 && notifications.value[index]) {
|
||||
notifications.value[index].isRead = true
|
||||
}
|
||||
// Remove from unread notifications
|
||||
unreadNotifications.value = unreadNotifications.value.filter((n) => n.id !== notificationId)
|
||||
|
||||
if (unreadCount.value > 0) {
|
||||
unreadCount.value--
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to mark notification as read:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function handleNotificationClick(notification: NotificationDto) {
|
||||
if (!notification.isRead) {
|
||||
await markAsRead(notification.id)
|
||||
}
|
||||
if (notification.clickTarget) {
|
||||
await navigateTo(notification.clickTarget)
|
||||
}
|
||||
}
|
||||
|
||||
function startPeriodicRefresh(intervalMs: number = 30000) {
|
||||
const interval = setInterval(() => {
|
||||
void fetchUnreadCount()
|
||||
}, intervalMs)
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(interval)
|
||||
})
|
||||
|
||||
return interval
|
||||
}
|
||||
|
||||
async function deleteAllNotifications() {
|
||||
try {
|
||||
await clearAllNotifications()
|
||||
notifications.value = []
|
||||
unreadNotifications.value = []
|
||||
unreadCount.value = 0
|
||||
} catch (error) {
|
||||
logger.error('Failed to delete all notifications:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteSingleNotification(notificationId: string) {
|
||||
try {
|
||||
// Check if notification was unread before deleting
|
||||
const notification = notifications.value.find((n) => n.id === notificationId)
|
||||
const wasUnread = notification && !notification.isRead
|
||||
|
||||
await deleteNotification(notificationId)
|
||||
notifications.value = notifications.value.filter((n) => n.id !== notificationId)
|
||||
unreadNotifications.value = unreadNotifications.value.filter((n) => n.id !== notificationId)
|
||||
|
||||
// Update unread count if the deleted notification was unread
|
||||
if (wasUnread && unreadCount.value > 0) {
|
||||
unreadCount.value--
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Failed to delete notification:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
// State
|
||||
notifications,
|
||||
unreadNotifications,
|
||||
unreadCount,
|
||||
isLoading,
|
||||
// Getters
|
||||
hasUnread,
|
||||
// Actions
|
||||
fetchNotifications,
|
||||
fetchUnreadNotifications,
|
||||
fetchUnreadCount,
|
||||
markAllAsRead,
|
||||
markAsRead,
|
||||
handleNotificationClick,
|
||||
startPeriodicRefresh,
|
||||
deleteAllNotifications,
|
||||
deleteSingleNotification
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user