143 lines
3.6 KiB
TypeScript
143 lines
3.6 KiB
TypeScript
/**
|
|
* Notification API Service
|
|
* Fetches notifications from /api/v1/notifications/ endpoints
|
|
*/
|
|
|
|
import { fetchAPI } from './api';
|
|
|
|
// ============================================================================
|
|
// TYPES
|
|
// ============================================================================
|
|
|
|
// Notification types - match backend NotificationType choices
|
|
export type NotificationTypeAPI =
|
|
// AI Operations
|
|
| 'ai_cluster_complete'
|
|
| 'ai_cluster_failed'
|
|
| 'ai_ideas_complete'
|
|
| 'ai_ideas_failed'
|
|
| 'ai_content_complete'
|
|
| 'ai_content_failed'
|
|
| 'ai_images_complete'
|
|
| 'ai_images_failed'
|
|
| 'ai_prompts_complete'
|
|
| 'ai_prompts_failed'
|
|
// Workflow
|
|
| 'content_ready_review'
|
|
| 'content_published'
|
|
| 'content_publish_failed'
|
|
// WordPress Sync
|
|
| 'wordpress_sync_success'
|
|
| 'wordpress_sync_failed'
|
|
// Credits/Billing
|
|
| 'credits_low'
|
|
| 'credits_depleted'
|
|
// Setup
|
|
| 'site_setup_complete'
|
|
| 'keywords_imported'
|
|
// System
|
|
| 'system_info'
|
|
// Legacy/fallback
|
|
| 'ai_task'
|
|
| 'system'
|
|
| 'credit'
|
|
| 'billing'
|
|
| 'integration'
|
|
| 'content'
|
|
| 'info';
|
|
|
|
export type NotificationSeverityAPI = 'info' | 'success' | 'warning' | 'error';
|
|
|
|
export interface NotificationAPI {
|
|
id: number;
|
|
notification_type: NotificationTypeAPI;
|
|
severity: NotificationSeverityAPI;
|
|
title: string;
|
|
message: string;
|
|
is_read: boolean;
|
|
created_at: string;
|
|
read_at: string | null;
|
|
action_label: string | null;
|
|
action_url: string | null;
|
|
metadata: Record<string, unknown> | null;
|
|
related_object_type: string | null;
|
|
related_object_id: number | null;
|
|
}
|
|
|
|
export interface NotificationListResponse {
|
|
count: number;
|
|
next: string | null;
|
|
previous: string | null;
|
|
results: NotificationAPI[];
|
|
}
|
|
|
|
export interface UnreadCountResponse {
|
|
unread_count: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// API FUNCTIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Fetch notifications list
|
|
*/
|
|
export async function fetchNotifications(params?: {
|
|
page?: number;
|
|
page_size?: number;
|
|
is_read?: boolean;
|
|
notification_type?: NotificationTypeAPI;
|
|
}): Promise<NotificationListResponse> {
|
|
const searchParams = new URLSearchParams();
|
|
if (params?.page) searchParams.set('page', params.page.toString());
|
|
if (params?.page_size) searchParams.set('page_size', params.page_size.toString());
|
|
if (params?.is_read !== undefined) searchParams.set('is_read', params.is_read.toString());
|
|
if (params?.notification_type) searchParams.set('notification_type', params.notification_type);
|
|
|
|
const queryString = searchParams.toString();
|
|
const url = `/v1/notifications/${queryString ? `?${queryString}` : ''}`;
|
|
|
|
return fetchAPI(url);
|
|
}
|
|
|
|
/**
|
|
* Get unread notification count
|
|
*/
|
|
export async function fetchUnreadCount(): Promise<UnreadCountResponse> {
|
|
return fetchAPI('/v1/notifications/unread-count/');
|
|
}
|
|
|
|
/**
|
|
* Mark a single notification as read
|
|
*/
|
|
export async function markNotificationRead(id: number): Promise<NotificationAPI> {
|
|
return fetchAPI(`/v1/notifications/${id}/read/`, {
|
|
method: 'POST',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Mark all notifications as read
|
|
*/
|
|
export async function markAllNotificationsRead(): Promise<{ message: string; count: number }> {
|
|
return fetchAPI('/v1/notifications/read-all/', {
|
|
method: 'POST',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Delete a notification
|
|
*/
|
|
export async function deleteNotification(id: number): Promise<void> {
|
|
await fetchAPI(`/v1/notifications/${id}/`, {
|
|
method: 'DELETE',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Delete multiple notifications
|
|
*/
|
|
export async function deleteNotifications(ids: number[]): Promise<void> {
|
|
await Promise.all(ids.map(id => deleteNotification(id)));
|
|
}
|