feat(#9): Nuxt 4 migration

This commit is contained in:
2025-11-02 18:46:46 +01:00
parent 763b2f7b7f
commit 6d79c710a2
54 changed files with 2904 additions and 1416 deletions

View File

@@ -0,0 +1,144 @@
import type { NotificationDto } from '~~/.api-client'
import { useUserStore } from '~~/stores/useUserStore'
export const useNotification = () => {
const {
getNotifications,
getUnreadNotifications,
getUnreadNotificationCount,
markAllNotificationsAsRead,
markNotificationAsRead
} = useNotificationApi()
const userStore = useUserStore()
const organizationId = computed(() => userStore.selectedOrganization?.id)
const { user } = useUserSession()
const userId = computed(() => user.value?.keycloakId)
const notifications = ref<NotificationDto[]>([])
const unreadNotifications = ref<NotificationDto[]>([])
const unreadCount = ref<number>(0)
const isLoading = ref(false)
const fetchNotifications = async (page: number = 0, size: number = 20) => {
if (!organizationId.value) {
console.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) {
console.error('Failed to fetch notifications:', error)
throw error
} finally {
isLoading.value = false
}
}
const fetchUnreadNotifications = async () => {
if (!organizationId.value) {
console.warn('No organization selected')
return
}
try {
const response = await getUnreadNotifications(organizationId.value)
unreadNotifications.value = response || []
return response
} catch (error) {
console.error('Failed to fetch unread notifications:', error)
throw error
}
}
const fetchUnreadCount = async () => {
if (!userId.value || !organizationId.value) {
console.warn('No user or organization selected')
return
}
try {
const count = await getUnreadNotificationCount(userId.value, organizationId.value)
unreadCount.value = count || 0
return count
} catch (error) {
console.error('Failed to fetch unread count:', error)
throw error
}
}
const markAllAsRead = async () => {
if (!organizationId.value) {
console.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) {
console.error('Failed to mark all as read:', error)
throw error
}
}
const markAsRead = async (notificationId: string) => {
if (!organizationId.value) {
console.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].isRead = true
}
// Remove from unread notifications
unreadNotifications.value = unreadNotifications.value.filter((n) => n.id !== notificationId)
if (unreadCount.value > 0) {
unreadCount.value--
}
} catch (error) {
console.error('Failed to mark notification as read:', error)
throw error
}
}
const handleNotificationClick = async (notification: NotificationDto) => {
if (!notification.isRead) {
await markAsRead(notification.id)
}
if (notification.clickTarget) {
await navigateTo(notification.clickTarget)
}
}
const startPeriodicRefresh = (intervalMs: number = 30000) => {
const interval = setInterval(() => {
void fetchUnreadCount()
}, intervalMs)
onUnmounted(() => {
clearInterval(interval)
})
return interval
}
return {
notifications,
unreadNotifications,
unreadCount,
isLoading,
fetchNotifications,
fetchUnreadNotifications,
fetchUnreadCount,
markAllAsRead,
markAsRead,
handleNotificationClick,
startPeriodicRefresh
}
}

View File

@@ -0,0 +1,64 @@
import {
NotificationApi,
Configuration,
type NotificationDto,
type PagedNotificationDto,
type CreateNotificationDto
} from '~~/.api-client'
import { cleanDoubleSlashes, withoutTrailingSlash } from 'ufo'
import { wrappedFetchWrap } from '~/utils/wrappedFetch'
export function useNotificationApi() {
const appBaseUrl = useRuntimeConfig().app.baseURL
const { serverApiBasePath, clientProxyBasePath } = useRuntimeConfig().public
const basePath = withoutTrailingSlash(
cleanDoubleSlashes(
import.meta.client
? appBaseUrl + clientProxyBasePath
: useRequestURL().origin + clientProxyBasePath + serverApiBasePath
)
)
const notificationApiClient = new NotificationApi(
new Configuration({ basePath, fetchApi: wrappedFetchWrap(useRequestFetch()) })
)
async function createNotification(createNotificationDto: CreateNotificationDto): Promise<NotificationDto> {
return notificationApiClient.createNotification({ createNotificationDto })
}
async function getNotifications(organizationId: string, page?: number, size?: number): Promise<PagedNotificationDto> {
return notificationApiClient.getNotifications({ organizationId, page, size })
}
async function getUnreadNotifications(organizationId: string): Promise<NotificationDto[]> {
return notificationApiClient.getUnreadNotifications({ organizationId })
}
async function getUnreadNotificationCount(userId: string, organizationId: string): Promise<number> {
return notificationApiClient.getUnreadNotificationCount({ userId, organizationId })
}
async function markAllNotificationsAsRead(organizationId: string): Promise<void> {
return notificationApiClient.markAllNotificationsAsRead({ organizationId })
}
async function markNotificationAsRead(id: string, organizationId: string): Promise<NotificationDto> {
return notificationApiClient.markNotificationAsRead({ id, organizationId })
}
async function clearAllNotifications(organizationId: string): Promise<void> {
return notificationApiClient.clearAllNotifications({ organizationId })
}
return {
createNotification,
getNotifications,
getUnreadNotifications,
getUnreadNotificationCount,
markAllNotificationsAsRead,
markNotificationAsRead,
clearAllNotifications
}
}