intermittent commit

This commit is contained in:
2026-07-14 13:22:11 +02:00
parent 3444a4920f
commit 6163c8f733
24 changed files with 2367 additions and 0 deletions
+123
View File
@@ -0,0 +1,123 @@
import { apiFetch, type ApiSettings } from "@govoplan/core-webui";
export type NotificationDeliveryAttempt = {
id: string;
notification_id: string;
attempt_no: number;
channel: string;
provider?: string | null;
status: string;
started_at?: string | null;
finished_at?: string | null;
external_message_id?: string | null;
error?: string | null;
details: Record<string, unknown>;
created_at: string;
updated_at: string;
};
export type NotificationMessage = {
id: string;
tenant_id: string;
source_module: string;
source_resource_type: string;
source_resource_id?: string | null;
event_kind: string;
channel: string;
recipient?: string | null;
recipient_type?: string | null;
recipient_id?: string | null;
recipient_label?: string | null;
subject?: string | null;
body_text?: string | null;
body_html?: string | null;
action_url?: string | null;
priority: number;
status: string;
not_before_at?: string | null;
queued_at?: string | null;
sent_at?: string | null;
failed_at?: string | null;
read_at?: string | null;
acknowledged_at?: string | null;
cancelled_at?: string | null;
attempt_count: number;
last_error?: string | null;
external_message_id?: string | null;
payload: Record<string, unknown>;
metadata: Record<string, unknown>;
attempts: NotificationDeliveryAttempt[];
created_at: string;
updated_at: string;
};
export type NotificationListResponse = {
notifications: NotificationMessage[];
};
export type NotificationSummary = {
total: number;
unread: number;
pending: number;
failed: number;
show_unread_badge?: boolean;
};
export type NotificationPreferences = {
tenant_id: string;
user_id: string;
show_unread_badge: boolean;
email_enabled: boolean;
email_digest_enabled: boolean;
muted_source_modules: string[];
metadata: Record<string, unknown>;
};
export type NotificationDeliveryResult = {
notification?: NotificationMessage | null;
processed: number;
sent: number;
failed: number;
skipped: number;
errors: string[];
};
export function listNotifications(settings: ApiSettings, filters: { status?: string; channel?: string; source_module?: string; recipient_id?: string; limit?: number } = {}): Promise<NotificationListResponse> {
const params = new URLSearchParams();
if (filters.status) params.set("status", filters.status);
if (filters.channel) params.set("channel", filters.channel);
if (filters.source_module) params.set("source_module", filters.source_module);
if (filters.recipient_id) params.set("recipient_id", filters.recipient_id);
if (filters.limit) params.set("limit", String(filters.limit));
const query = params.toString();
return apiFetch<NotificationListResponse>(settings, `/api/v1/notifications${query ? `?${query}` : ""}`);
}
export function notificationSummary(settings: ApiSettings): Promise<NotificationSummary> {
return apiFetch<NotificationSummary>(settings, "/api/v1/notifications/summary");
}
export function getNotificationPreferences(settings: ApiSettings): Promise<NotificationPreferences> {
return apiFetch<NotificationPreferences>(settings, "/api/v1/notifications/preferences/me");
}
export function updateNotificationPreferences(settings: ApiSettings, payload: Partial<Pick<NotificationPreferences, "show_unread_badge" | "email_enabled" | "email_digest_enabled" | "muted_source_modules" | "metadata">>): Promise<NotificationPreferences> {
return apiFetch<NotificationPreferences>(settings, "/api/v1/notifications/preferences/me", {
method: "PUT",
body: JSON.stringify(payload)
});
}
export function updateNotification(settings: ApiSettings, notificationId: string, payload: { status?: "read" | "acknowledged" | "cancelled"; metadata?: Record<string, unknown> | null }): Promise<NotificationMessage> {
return apiFetch<NotificationMessage>(settings, `/api/v1/notifications/${notificationId}`, {
method: "PATCH",
body: JSON.stringify(payload)
});
}
export function deliverPendingNotifications(settings: ApiSettings, limit = 50): Promise<NotificationDeliveryResult> {
return apiFetch<NotificationDeliveryResult>(settings, "/api/v1/notifications/deliver-pending", {
method: "POST",
body: JSON.stringify({ limit })
});
}