feat(email): read-only "Sent emails" tab over email_queue

Add a paginated, filterable view of the email_queue (recipient, type,
status, queued/sent timestamps, error, event link) as a third tab in
Email config, beside SMTP + Templates. Filters: status, recipient/type
search, created-at range. email_data is never exposed. Pairs with the
"Send queued emails now" flush — flush, then watch what sent/failed.
This commit is contained in:
Luca
2026-06-02 13:58:54 +02:00
parent 8d14441df4
commit 603ba1e504
6 changed files with 361 additions and 2 deletions
+37
View File
@@ -1,5 +1,27 @@
import { api } from '../config/api';
export type EmailQueueStatus = 'pending' | 'sent' | 'failed';
export interface EmailQueueItem {
id: number;
recipientEmail: string;
emailType: string;
status: EmailQueueStatus;
createdAt: string;
scheduledAt: string | null;
sentAt: string | null;
errorMessage: string | null;
retryCount: number;
eventId: number | null;
eventName: string | null;
eventSlug: string | null;
}
export interface EmailQueueListResponse {
items: EmailQueueItem[];
pagination: { total: number; page: number; pageSize: number; totalPages: number };
}
export interface EmailConfig {
smtp_host: string;
smtp_port: number;
@@ -84,6 +106,21 @@ export const emailService = {
return response.data;
},
/** Read-only "Sent emails" feed — paginated view of the email_queue
* table with filters. email_data is never returned. */
async listQueue(params: {
status?: EmailQueueStatus;
emailType?: string;
q?: string;
from?: string;
to?: string;
page?: number;
pageSize?: number;
} = {}): Promise<EmailQueueListResponse> {
const response = await api.get<EmailQueueListResponse>('/admin/email/queue', { params });
return response.data;
},
// Get all email templates
async getTemplates(): Promise<EmailTemplate[]> {
const response = await api.get<EmailTemplate[]>('/admin/email/templates');