221 lines
5.2 KiB
TypeScript
221 lines
5.2 KiB
TypeScript
import apiClient from "./api/client";
|
|
|
|
export interface Notification {
|
|
id: string;
|
|
title: string;
|
|
body: string;
|
|
icon?: string;
|
|
url?: string;
|
|
sentAt?: string;
|
|
scheduledFor?: string;
|
|
isSent: boolean;
|
|
recipientId: string;
|
|
data?: Record<string, any>;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface NotificationSettings {
|
|
emailNotifications: boolean;
|
|
pushNotifications: boolean;
|
|
invoiceReminders: boolean;
|
|
paymentAlerts: boolean;
|
|
systemUpdates: boolean;
|
|
}
|
|
|
|
export interface SendPushNotificationRequest {
|
|
title: string;
|
|
body: string;
|
|
icon?: string;
|
|
url?: string;
|
|
recipientId?: string;
|
|
scheduledFor?: string;
|
|
data?: Record<string, any>;
|
|
}
|
|
|
|
export interface SendSmsNotificationRequest {
|
|
body: string;
|
|
recipientPhone?: string; // If null, system broadcast
|
|
scheduledFor?: string;
|
|
}
|
|
|
|
export interface SendEmailNotificationRequest {
|
|
subject: string;
|
|
body: string; // HTML or Plain text
|
|
recipientEmail?: string; // If null, system broadcast
|
|
scheduledFor?: string;
|
|
}
|
|
|
|
export interface SendBroadcastRequest {
|
|
title: string;
|
|
message: string;
|
|
audience: "all_end_users" | "system_users_only" | "everyone_with_access";
|
|
channels: ("push" | "sms" | "email")[];
|
|
}
|
|
export interface NotificationListResponse {
|
|
data: Notification[];
|
|
total: number;
|
|
}
|
|
class NotificationService {
|
|
/**
|
|
* Get all notifications for current user (Paginated)
|
|
*/
|
|
async getNotifications(params?: {
|
|
page?: number;
|
|
limit?: number;
|
|
type?: string;
|
|
status?: string;
|
|
search?: string;
|
|
}): Promise<Notification[]> {
|
|
const response = await apiClient.get<NotificationListResponse>("/notifications", {
|
|
params,
|
|
});
|
|
return response.data.data;
|
|
}
|
|
|
|
/**
|
|
* Get unread notification count
|
|
*/
|
|
async getUnreadCount(): Promise<number> {
|
|
const response = await apiClient.get<{ unreadCount: number }>(
|
|
"/notifications/unread-count",
|
|
);
|
|
return response.data.unreadCount;
|
|
}
|
|
|
|
/**
|
|
* Mark notification as read
|
|
*/
|
|
async markAsRead(id: string): Promise<void> {
|
|
await apiClient.post(`/notifications/${id}/read`);
|
|
}
|
|
|
|
/**
|
|
* Mark all notifications as read
|
|
*/
|
|
async markAllAsRead(): Promise<void> {
|
|
await apiClient.put("/notifications/mark-all-read");
|
|
}
|
|
|
|
/**
|
|
* Send multi-channel broadcast (ADMIN only)
|
|
*/
|
|
async sendBroadcast(
|
|
data: SendBroadcastRequest,
|
|
): Promise<{ success: boolean }> {
|
|
const response = await apiClient.post<{ success: boolean }>(
|
|
"/notifications/broadcast",
|
|
data,
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Send push notification (ADMIN only)
|
|
*/
|
|
async sendPushNotification(
|
|
data: SendPushNotificationRequest,
|
|
): Promise<Notification> {
|
|
const response = await apiClient.post<Notification>(
|
|
"/admin/notifications/send-push",
|
|
data,
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Send SMS notification (ADMIN only)
|
|
*/
|
|
async sendSmsNotification(
|
|
data: SendSmsNotificationRequest,
|
|
): Promise<{ success: boolean; messageId: string }> {
|
|
const response = await apiClient.post<{
|
|
success: boolean;
|
|
messageId: string;
|
|
}>("/admin/notifications/send-sms", data);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Send Email notification (ADMIN only)
|
|
*/
|
|
async sendEmailNotification(
|
|
data: SendEmailNotificationRequest,
|
|
): Promise<{ success: boolean; messageId: string }> {
|
|
const response = await apiClient.post<{
|
|
success: boolean;
|
|
messageId: string;
|
|
}>("/admin/notifications/send-email", data);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Subscribe to push notifications
|
|
*/
|
|
async subscribeToPush(subscription: PushSubscription): Promise<void> {
|
|
await apiClient.post("/notifications/subscribe", subscription);
|
|
}
|
|
|
|
/**
|
|
* Unsubscribe from push notifications
|
|
*/
|
|
async unsubscribeFromPush(endpoint: string): Promise<void> {
|
|
await apiClient.delete(
|
|
`/notifications/unsubscribe/${encodeURIComponent(endpoint)}`,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get notification settings
|
|
*/
|
|
async getSettings(): Promise<NotificationSettings> {
|
|
const response = await apiClient.get<NotificationSettings>(
|
|
"/notifications/settings",
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Update notification settings
|
|
*/
|
|
async updateSettings(
|
|
settings: Partial<NotificationSettings>,
|
|
): Promise<NotificationSettings> {
|
|
const response = await apiClient.put<NotificationSettings>(
|
|
"/notifications/settings",
|
|
settings,
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Send invoice reminder
|
|
*/
|
|
async sendInvoiceReminder(invoiceId: string): Promise<void> {
|
|
await apiClient.post(`/notifications/invoice/${invoiceId}/reminder`);
|
|
}
|
|
|
|
/**
|
|
* Export notifications (creates CSV from current data)
|
|
*/
|
|
async exportNotifications(notifications: Notification[]): Promise<Blob> {
|
|
const csvContent = [
|
|
["ID", "Title", "Body", "Status", "Created Date", "Sent Date"],
|
|
...notifications.map((n) => [
|
|
n.id,
|
|
n.title,
|
|
n.body,
|
|
n.isSent ? "Sent" : "Scheduled",
|
|
n.createdAt,
|
|
n.sentAt || "-",
|
|
]),
|
|
]
|
|
.map((row) => row.join(","))
|
|
.join("\n");
|
|
|
|
return new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
}
|
|
}
|
|
|
|
export const notificationService = new NotificationService();
|