From 2cc31b6bc622a991538ed49d862c8e14aecb24d0 Mon Sep 17 00:00:00 2001 From: Konstantinos Kopanidis Date: Sun, 21 Jun 2026 18:21:05 +0300 Subject: [PATCH] fix(ui): align communications admin API paths with v0.17 module Update push and email Admin API clients to match the unified communications module routes, with graceful degradation where backend endpoints are missing. --- src/components/email/records/email-status.tsx | 62 ++------------- src/lib/api/email/index.ts | 55 +++++++------ src/lib/api/notifications/index.ts | 79 +++++++++++++------ 3 files changed, 96 insertions(+), 100 deletions(-) diff --git a/src/components/email/records/email-status.tsx b/src/components/email/records/email-status.tsx index 54ea82ac9..7936751b2 100644 --- a/src/components/email/records/email-status.tsx +++ b/src/components/email/records/email-status.tsx @@ -1,66 +1,18 @@ 'use client'; -import { useEffect, useState } from 'react'; import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { RefreshCw } from 'lucide-react'; -import { fetchEmailStatus } from '@/lib/api/email'; interface EmailStatusProps { emailId: string; } -export function EmailStatus({ emailId }: Readonly) { - const [status, setStatus] = useState(null); - const [loading, setLoading] = useState(false); - - const fetchStatus = async () => { - setLoading(true); - try { - const statusData = await fetchEmailStatus(emailId); - setStatus(statusData.statusInfo); - } catch (error) { - console.error('Failed to fetch email status:', error); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - fetchStatus(); - }, [emailId]); - - const getStatusBadge = () => { - if (!status) return Unknown; - - switch (status.status) { - case 'delivered': - return Delivered; - case 'failed': - return Failed; - case 'pending': - return ( - - Pending - - ); - default: - return Unknown; - } - }; - +export function EmailStatus(_props: Readonly) { return ( -
- {getStatusBadge()} - -
+ + Unavailable + ); } diff --git a/src/lib/api/email/index.ts b/src/lib/api/email/index.ts index 9cc94f274..83e266ba5 100644 --- a/src/lib/api/email/index.ts +++ b/src/lib/api/email/index.ts @@ -71,9 +71,7 @@ export const createTemplate = async (data: { }; export const deleteTemplates = async (ids: string[]) => { - return (await getApiClient()) - .delete('/email/templates', { params: { ids } }) - .then(res => res.data); + await Promise.all(ids.map(id => deleteTemplate(id))); }; export const deleteTemplate = async (id: string) => { @@ -107,7 +105,7 @@ export const getExternalTemplates = async (args: { count: number; }; return (await getApiClient()) - .get('/email/externalTemplates', { params: args }) + .get('/email/templates/external', { params: args }) .then(res => res.data); }; @@ -117,17 +115,14 @@ export const syncTemplates = async () => { count: number; }; return (await getApiClient()) - .patch('/email/syncExternalTemplates') + .post('/email/templates/external/sync') .then(res => res.data); }; -export const uploadTemplate = async (id: string) => { - return (await getApiClient()) - .post('/email/templates/upload', { _id: id }) - .then(res => res.data) - .catch(err => { - throw new Error(err.response?.data.message ?? err.message); - }); +export const uploadTemplate = async (_id: string) => { + throw new Error( + 'Template upload to the email provider is not available on the unified communications module' + ); }; export const sendEmail = async (data: EmailPayload) => { @@ -136,16 +131,21 @@ export const sendEmail = async (data: EmailPayload) => { export const reSendEmail = async (emailRecordId: string) => { return (await getApiClient()) - .post(`/email/resend`, { emailRecordId }) + .post(`/email/resend`, { id: emailRecordId }) .then(res => res.data); }; -export const fetchEmailStatus = async (messageId: string) => { - return (await getApiClient()) - .get<{ - statusInfo: any; - }>(`/email/status`, { params: { messageId } }) - .then(res => res.data); +const resolveEmailListSearch = (args: { + messageId?: string; + templateId?: string; + receiver?: string; + sender?: string; +}): string | undefined => { + if (args.receiver) return args.receiver; + if (args.messageId?.match(/^[a-fA-F\d]{24}$/)) return args.messageId; + if (args.templateId?.match(/^[a-fA-F\d]{24}$/)) return args.templateId; + if (args.sender) return args.sender; + return args.messageId; }; export const fetchRecords = async (args: { @@ -162,10 +162,19 @@ export const fetchRecords = async (args: { sort?: string; }) => { type Response = { - records: EmailRecord[]; + emailDocuments: EmailRecord[]; count: number; }; - return (await getApiClient()) - .get('/email/record', { params: args }) - .then(res => res.data); + const search = resolveEmailListSearch(args); + const res = await ( + await getApiClient() + ).get('/email/emails', { + params: { + skip: args.skip, + limit: args.limit, + sort: args.sort, + ...(search ? { search } : {}), + }, + }); + return { records: res.data.emailDocuments, count: res.data.count }; }; diff --git a/src/lib/api/notifications/index.ts b/src/lib/api/notifications/index.ts index 64ee21a01..45ae220e9 100644 --- a/src/lib/api/notifications/index.ts +++ b/src/lib/api/notifications/index.ts @@ -12,6 +12,22 @@ import { type ConfigResponse = { config: NotificationSettings }; +type PushSendParams = { + userId: string; + title: string; + body?: string; + data?: Record; + platform?: string; + doNotStore?: boolean; + isSilent?: boolean; +}; + +const postPushSend = async (params: PushSendParams) => { + const client = await getApiClient(); + const res = await client.post('/push/send', params); + return res.data; +}; + export const getNotificationSettings = async (): Promise => { const res = await ( await getApiClient() @@ -37,6 +53,7 @@ export const patchNotificationSettings = async ( return afterPatchServing(options); }; + export const getTokens = async ( skip: number, limit: number, @@ -48,7 +65,7 @@ export const getTokens = async ( ): Promise<{ tokens: NotificationToken[]; count: number }> => { const res = await ( await getApiClient() - ).get(`/pushNotifications/token`, { + ).get(`/push/tokens`, { params: { skip, limit, @@ -64,50 +81,68 @@ export const getTokenById = async ( ): Promise => { const res = await ( await getApiClient() - ).get(`/pushNotifications/token/${id}`, { + ).get<{ tokenDocuments: NotificationToken }>(`/push/tokens/${id}`, { params: { populate, }, }); - return res.data; + return res.data.tokenDocuments; }; export const sendNotifications = async (params: { userIds: string[]; title: string; body?: string; - data?: Record; + data?: Record; isSilent?: boolean; platform?: string; doNotStore?: boolean; -}): Promise => { - const res = await ( - await getApiClient() - ).post(`/pushNotifications/sendToManyDevices`, { - ...params, - }); - return res.data; +}): Promise => { + const { userIds, title, body, data, isSilent, platform, doNotStore } = params; + const results = await Promise.allSettled( + userIds.map(userId => + postPushSend({ + userId, + title, + body, + data, + isSilent, + platform, + doNotStore, + }) + ) + ); + const failures = results.filter(r => r.status === 'rejected'); + if (failures.length > 0) { + throw new Error( + `Failed to send to ${failures.length} of ${userIds.length} recipient(s)` + ); + } }; export const sendPushNotification = async (data: Record) => { - const res = await ( - await getApiClient() - ).post('/pushNotifications/send', data); - return res.data; + return postPushSend(data as PushSendParams); }; export const sendManyPushNotifications = async ( - data: Record + notifications: PushSendParams[] ) => { - const res = await ( - await getApiClient() - ).post('/pushNotifications/sendMany', data); - return res.data; + const results = await Promise.allSettled( + notifications.map(notification => postPushSend(notification)) + ); + const failures = results.filter(r => r.status === 'rejected'); + if (failures.length > 0) { + throw new Error( + `Failed to send ${failures.length} of ${notifications.length} notification(s)` + ); + } }; export const getPushTokensForUser = async (userId: string) => { const res = await ( await getApiClient() - ).get(`/pushNotifications/token/user/${userId}`); - return res.data; + ).get<{ tokens: NotificationToken[]; count: number }>(`/push/tokens`, { + params: { search: userId }, + }); + return { tokens: res.data.tokens }; };