2026-07-23 05:11:16 +02:00
|
|
|
/**
|
|
|
|
|
* Notification hooks: list, unread count, mark read, delete, types, preferences.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
|
|
import { apiGet, apiPatch, apiDelete } from './client';
|
|
|
|
|
import { PaginatedResponse } from './types';
|
|
|
|
|
|
2026-07-24 14:23:28 +02:00
|
|
|
// ── Types matching backend schemas ──
|
|
|
|
|
|
|
|
|
|
export interface NotificationItem {
|
|
|
|
|
id: string;
|
|
|
|
|
type: string;
|
|
|
|
|
title: string;
|
|
|
|
|
body?: string | null;
|
|
|
|
|
read_at?: string | null;
|
|
|
|
|
created_at?: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-23 05:11:16 +02:00
|
|
|
export interface NotificationTypeItem {
|
|
|
|
|
type_key: string;
|
|
|
|
|
plugin_name: string;
|
|
|
|
|
category: string;
|
|
|
|
|
label: string;
|
|
|
|
|
description: string | null;
|
|
|
|
|
is_enabled_by_default: boolean;
|
|
|
|
|
is_enabled: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-24 14:23:28 +02:00
|
|
|
export interface UnreadCountResponse {
|
|
|
|
|
count: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface NotificationPreferenceItem {
|
|
|
|
|
type_key: string;
|
|
|
|
|
is_enabled: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-23 05:11:16 +02:00
|
|
|
export function useNotifications() {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ['notifications'],
|
2026-07-24 14:23:28 +02:00
|
|
|
queryFn: () => apiGet<PaginatedResponse<NotificationItem>>('/notifications'),
|
2026-07-23 05:11:16 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useUnreadNotificationCount() {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ['notifications', 'unread-count'],
|
2026-07-24 14:23:28 +02:00
|
|
|
queryFn: async () => {
|
|
|
|
|
const data = await apiGet<UnreadCountResponse>('/notifications/unread-count');
|
|
|
|
|
return data.count;
|
|
|
|
|
},
|
2026-07-23 05:11:16 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useMarkNotificationRead() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: (id: string) => apiPatch(`/notifications/${id}/read`),
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['notifications'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useDeleteNotification() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: (id: string) => apiDelete(`/notifications/${id}`),
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['notifications'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useNotificationTypes() {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ['notification-types'],
|
|
|
|
|
queryFn: () => apiGet<{ items: NotificationTypeItem[] }>('/notifications/types'),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useNotificationPreferences() {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ['notification-preferences'],
|
2026-07-24 14:23:28 +02:00
|
|
|
queryFn: () => apiGet<{ items: NotificationPreferenceItem[] }>('/notifications/preferences'),
|
2026-07-23 05:11:16 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useUpdateNotificationPreference() {
|
|
|
|
|
const queryClient = useQueryClient();
|
|
|
|
|
return useMutation({
|
|
|
|
|
mutationFn: ({ typeKey, isEnabled }: { typeKey: string; isEnabled: boolean }) =>
|
|
|
|
|
apiPatch(`/notifications/preferences/${typeKey}`, { is_enabled: isEnabled }),
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['notification-preferences'] });
|
|
|
|
|
queryClient.invalidateQueries({ queryKey: ['notification-types'] });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|