104 lines
3.0 KiB
JavaScript
104 lines
3.0 KiB
JavaScript
import { computed, ref, watch } from 'vue';
|
|
import { defineStore } from 'pinia';
|
|
import { useAuthStore } from '@/features/auth/stores/authStore.js';
|
|
import { useWorkspaceStore } from '@/features/workspaces/stores/workspaceStore.js';
|
|
import { useClient } from '@/plugins/api.js';
|
|
import { isFeedbackNotification } from '@/features/notifications/notificationRoutes.js';
|
|
|
|
export const useNotificationsStore = defineStore('notifications', () => {
|
|
const authStore = useAuthStore();
|
|
const workspaceStore = useWorkspaceStore();
|
|
const client = useClient();
|
|
|
|
const items = ref([]);
|
|
const isLoading = ref(false);
|
|
const error = ref(null);
|
|
|
|
const unreadCount = computed(() =>
|
|
items.value.filter(item => !item.readAt).length
|
|
);
|
|
|
|
const recentItems = computed(() => items.value.slice(0, 6));
|
|
const unreadFeedbackReportIds = computed(() =>
|
|
new Set(
|
|
items.value
|
|
.filter(item => !item.readAt && isFeedbackNotification(item) && item.entityId)
|
|
.map(item => item.entityId)
|
|
)
|
|
);
|
|
|
|
function reset() {
|
|
items.value = [];
|
|
error.value = null;
|
|
}
|
|
|
|
async function fetchNotifications() {
|
|
if (!authStore.isAuthenticated) {
|
|
reset();
|
|
return;
|
|
}
|
|
|
|
isLoading.value = true;
|
|
error.value = null;
|
|
|
|
try {
|
|
const response = await client.get('/api/notifications');
|
|
|
|
items.value = response.data ?? [];
|
|
} catch (fetchError) {
|
|
console.error('Failed to fetch notifications:', fetchError);
|
|
items.value = [];
|
|
error.value = 'Failed to load notifications.';
|
|
} finally {
|
|
isLoading.value = false;
|
|
}
|
|
}
|
|
|
|
async function markAsRead(notificationId) {
|
|
try {
|
|
await client.post(`/api/notifications/${notificationId}/read`);
|
|
items.value = items.value.map(item =>
|
|
item.id === notificationId
|
|
? { ...item, readAt: item.readAt ?? new Date().toISOString() }
|
|
: item
|
|
);
|
|
} catch (markError) {
|
|
console.error('Failed to mark notification as read:', markError);
|
|
}
|
|
}
|
|
|
|
async function markFeedbackReportAsRead(reportId) {
|
|
const unreadNotifications = items.value.filter(item =>
|
|
!item.readAt && isFeedbackNotification(item) && item.entityId === reportId
|
|
);
|
|
|
|
await Promise.all(unreadNotifications.map(item => markAsRead(item.id)));
|
|
}
|
|
|
|
watch(
|
|
() => [authStore.isAuthenticated, workspaceStore.activeWorkspaceId],
|
|
async ([isAuthenticated, workspaceId]) => {
|
|
if (!isAuthenticated) {
|
|
reset();
|
|
return;
|
|
}
|
|
|
|
await fetchNotifications();
|
|
},
|
|
{ immediate: true }
|
|
);
|
|
|
|
return {
|
|
items,
|
|
recentItems,
|
|
unreadFeedbackReportIds,
|
|
unreadCount,
|
|
isLoading,
|
|
error,
|
|
reset,
|
|
fetchNotifications,
|
|
markAsRead,
|
|
markFeedbackReportAsRead,
|
|
};
|
|
});
|