351 lines
8.5 KiB
TypeScript
351 lines
8.5 KiB
TypeScript
|
|
// src/api/services/NotificationService.ts
|
||
|
|
import { apiClient } from '../base/apiClient';
|
||
|
|
import {
|
||
|
|
ApiResponse,
|
||
|
|
NotificationSettings,
|
||
|
|
} from '../types/api';
|
||
|
|
|
||
|
|
export interface NotificationCreate {
|
||
|
|
type: 'email' | 'whatsapp' | 'push';
|
||
|
|
recipient_email?: string;
|
||
|
|
recipient_phone?: string;
|
||
|
|
recipient_push_token?: string;
|
||
|
|
subject?: string;
|
||
|
|
message: string;
|
||
|
|
template_id?: string;
|
||
|
|
template_data?: Record<string, any>;
|
||
|
|
scheduled_for?: string;
|
||
|
|
broadcast?: boolean;
|
||
|
|
priority?: 'low' | 'normal' | 'high';
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface NotificationResponse {
|
||
|
|
id: string;
|
||
|
|
type: string;
|
||
|
|
recipient_email?: string;
|
||
|
|
recipient_phone?: string;
|
||
|
|
subject?: string;
|
||
|
|
message: string;
|
||
|
|
status: 'pending' | 'sent' | 'delivered' | 'failed';
|
||
|
|
created_at: string;
|
||
|
|
sent_at?: string;
|
||
|
|
delivered_at?: string;
|
||
|
|
error_message?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface NotificationHistory {
|
||
|
|
id: string;
|
||
|
|
type: string;
|
||
|
|
recipient: string;
|
||
|
|
subject?: string;
|
||
|
|
status: string;
|
||
|
|
created_at: string;
|
||
|
|
sent_at?: string;
|
||
|
|
delivered_at?: string;
|
||
|
|
opened_at?: string;
|
||
|
|
clicked_at?: string;
|
||
|
|
error_message?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface NotificationTemplate {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
description: string;
|
||
|
|
type: 'email' | 'whatsapp' | 'push';
|
||
|
|
subject?: string;
|
||
|
|
content: string;
|
||
|
|
variables: string[];
|
||
|
|
is_system: boolean;
|
||
|
|
is_active: boolean;
|
||
|
|
created_at: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface NotificationStats {
|
||
|
|
total_sent: number;
|
||
|
|
total_delivered: number;
|
||
|
|
total_failed: number;
|
||
|
|
delivery_rate: number;
|
||
|
|
open_rate: number;
|
||
|
|
click_rate: number;
|
||
|
|
by_type: {
|
||
|
|
email: { sent: number; delivered: number; opened: number; clicked: number };
|
||
|
|
whatsapp: { sent: number; delivered: number; read: number };
|
||
|
|
push: { sent: number; delivered: number; opened: number };
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BulkNotificationRequest {
|
||
|
|
type: 'email' | 'whatsapp' | 'push';
|
||
|
|
recipients: {
|
||
|
|
email?: string;
|
||
|
|
phone?: string;
|
||
|
|
push_token?: string;
|
||
|
|
template_data?: Record<string, any>;
|
||
|
|
}[];
|
||
|
|
template_id?: string;
|
||
|
|
subject?: string;
|
||
|
|
message?: string;
|
||
|
|
scheduled_for?: string;
|
||
|
|
batch_name?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface BulkNotificationStatus {
|
||
|
|
id: string;
|
||
|
|
batch_name?: string;
|
||
|
|
total_recipients: number;
|
||
|
|
sent: number;
|
||
|
|
delivered: number;
|
||
|
|
failed: number;
|
||
|
|
status: 'queued' | 'processing' | 'completed' | 'failed';
|
||
|
|
created_at: string;
|
||
|
|
completed_at?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export class NotificationService {
|
||
|
|
/**
|
||
|
|
* Send single notification
|
||
|
|
*/
|
||
|
|
async sendNotification(notification: NotificationCreate): Promise<NotificationResponse> {
|
||
|
|
const response = await apiClient.post<ApiResponse<NotificationResponse>>(
|
||
|
|
'/notifications/send',
|
||
|
|
notification
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Send bulk notifications
|
||
|
|
*/
|
||
|
|
async sendBulkNotifications(request: BulkNotificationRequest): Promise<BulkNotificationStatus> {
|
||
|
|
const response = await apiClient.post<ApiResponse<BulkNotificationStatus>>(
|
||
|
|
'/notifications/bulk',
|
||
|
|
request
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get notification history
|
||
|
|
*/
|
||
|
|
async getNotificationHistory(params?: {
|
||
|
|
type?: string;
|
||
|
|
status?: string;
|
||
|
|
startDate?: string;
|
||
|
|
endDate?: string;
|
||
|
|
page?: number;
|
||
|
|
limit?: number;
|
||
|
|
}): Promise<{
|
||
|
|
notifications: NotificationHistory[];
|
||
|
|
total: number;
|
||
|
|
page: number;
|
||
|
|
pages: number;
|
||
|
|
}> {
|
||
|
|
const response = await apiClient.get<ApiResponse<any>>('/notifications/history', { params });
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get notification by ID
|
||
|
|
*/
|
||
|
|
async getNotification(notificationId: string): Promise<NotificationResponse> {
|
||
|
|
const response = await apiClient.get<ApiResponse<NotificationResponse>>(
|
||
|
|
`/notifications/${notificationId}`
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Retry failed notification
|
||
|
|
*/
|
||
|
|
async retryNotification(notificationId: string): Promise<NotificationResponse> {
|
||
|
|
const response = await apiClient.post<ApiResponse<NotificationResponse>>(
|
||
|
|
`/notifications/${notificationId}/retry`
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Cancel scheduled notification
|
||
|
|
*/
|
||
|
|
async cancelNotification(notificationId: string): Promise<void> {
|
||
|
|
await apiClient.post(`/notifications/${notificationId}/cancel`);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get notification statistics
|
||
|
|
*/
|
||
|
|
async getNotificationStats(params?: {
|
||
|
|
startDate?: string;
|
||
|
|
endDate?: string;
|
||
|
|
type?: string;
|
||
|
|
}): Promise<NotificationStats> {
|
||
|
|
const response = await apiClient.get<ApiResponse<NotificationStats>>(
|
||
|
|
'/notifications/stats',
|
||
|
|
{ params }
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get bulk notification status
|
||
|
|
*/
|
||
|
|
async getBulkStatus(batchId: string): Promise<BulkNotificationStatus> {
|
||
|
|
const response = await apiClient.get<ApiResponse<BulkNotificationStatus>>(
|
||
|
|
`/notifications/bulk/${batchId}/status`
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get notification templates
|
||
|
|
*/
|
||
|
|
async getTemplates(params?: {
|
||
|
|
type?: string;
|
||
|
|
active?: boolean;
|
||
|
|
page?: number;
|
||
|
|
limit?: number;
|
||
|
|
}): Promise<{
|
||
|
|
templates: NotificationTemplate[];
|
||
|
|
total: number;
|
||
|
|
page: number;
|
||
|
|
pages: number;
|
||
|
|
}> {
|
||
|
|
const response = await apiClient.get<ApiResponse<any>>('/notifications/templates', { params });
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get template by ID
|
||
|
|
*/
|
||
|
|
async getTemplate(templateId: string): Promise<NotificationTemplate> {
|
||
|
|
const response = await apiClient.get<ApiResponse<NotificationTemplate>>(
|
||
|
|
`/notifications/templates/${templateId}`
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create notification template
|
||
|
|
*/
|
||
|
|
async createTemplate(template: {
|
||
|
|
name: string;
|
||
|
|
description: string;
|
||
|
|
type: 'email' | 'whatsapp' | 'push';
|
||
|
|
subject?: string;
|
||
|
|
content: string;
|
||
|
|
variables?: string[];
|
||
|
|
}): Promise<NotificationTemplate> {
|
||
|
|
const response = await apiClient.post<ApiResponse<NotificationTemplate>>(
|
||
|
|
'/notifications/templates',
|
||
|
|
template
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update notification template
|
||
|
|
*/
|
||
|
|
async updateTemplate(
|
||
|
|
templateId: string,
|
||
|
|
updates: Partial<NotificationTemplate>
|
||
|
|
): Promise<NotificationTemplate> {
|
||
|
|
const response = await apiClient.put<ApiResponse<NotificationTemplate>>(
|
||
|
|
`/notifications/templates/${templateId}`,
|
||
|
|
updates
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete notification template
|
||
|
|
*/
|
||
|
|
async deleteTemplate(templateId: string): Promise<void> {
|
||
|
|
await apiClient.delete(`/notifications/templates/${templateId}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get user notification preferences
|
||
|
|
*/
|
||
|
|
async getPreferences(): Promise<NotificationSettings> {
|
||
|
|
const response = await apiClient.get<ApiResponse<NotificationSettings>>(
|
||
|
|
'/notifications/preferences'
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update user notification preferences
|
||
|
|
*/
|
||
|
|
async updatePreferences(preferences: Partial<NotificationSettings>): Promise<NotificationSettings> {
|
||
|
|
const response = await apiClient.put<ApiResponse<NotificationSettings>>(
|
||
|
|
'/notifications/preferences',
|
||
|
|
preferences
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test notification delivery
|
||
|
|
*/
|
||
|
|
async testNotification(type: 'email' | 'whatsapp' | 'push', recipient: string): Promise<{
|
||
|
|
success: boolean;
|
||
|
|
message: string;
|
||
|
|
delivery_time_ms?: number;
|
||
|
|
}> {
|
||
|
|
const response = await apiClient.post<ApiResponse<any>>(
|
||
|
|
'/notifications/test',
|
||
|
|
{ type, recipient }
|
||
|
|
);
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get delivery webhooks
|
||
|
|
*/
|
||
|
|
async getWebhooks(params?: {
|
||
|
|
type?: string;
|
||
|
|
status?: string;
|
||
|
|
page?: number;
|
||
|
|
limit?: number;
|
||
|
|
}): Promise<{
|
||
|
|
webhooks: {
|
||
|
|
id: string;
|
||
|
|
notification_id: string;
|
||
|
|
event_type: string;
|
||
|
|
status: string;
|
||
|
|
payload: any;
|
||
|
|
received_at: string;
|
||
|
|
}[];
|
||
|
|
total: number;
|
||
|
|
page: number;
|
||
|
|
pages: number;
|
||
|
|
}> {
|
||
|
|
const response = await apiClient.get<ApiResponse<any>>('/notifications/webhooks', { params });
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Subscribe to notification events
|
||
|
|
*/
|
||
|
|
async subscribeToEvents(events: string[], webhookUrl: string): Promise<{
|
||
|
|
subscription_id: string;
|
||
|
|
events: string[];
|
||
|
|
webhook_url: string;
|
||
|
|
created_at: string;
|
||
|
|
}> {
|
||
|
|
const response = await apiClient.post<ApiResponse<any>>('/notifications/subscribe', {
|
||
|
|
events,
|
||
|
|
webhook_url: webhookUrl,
|
||
|
|
});
|
||
|
|
return response.data!;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Unsubscribe from notification events
|
||
|
|
*/
|
||
|
|
async unsubscribeFromEvents(subscriptionId: string): Promise<void> {
|
||
|
|
await apiClient.delete(`/notifications/subscribe/${subscriptionId}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export const notificationService = new NotificationService();
|