225 lines
6.3 KiB
JavaScript

import prisma from "~/server/utils/prisma";
export default defineEventHandler(async (event) => {
try {
// Get notification ID from route parameters
const notificationId = getRouterParam(event, "id");
if (!notificationId) {
throw createError({
statusCode: 400,
statusMessage: "Notification ID is required",
});
}
// Get current user (assuming auth middleware provides this)
const user = event.context.user;
if (!user) {
throw createError({
statusCode: 401,
statusMessage: "Authentication required",
});
}
// Fetch notification with all related data using Prisma
const notification = await prisma.notifications.findFirst({
where: {
id: notificationId,
created_by: user.id,
},
include: {
notification_categories: {
select: {
name: true,
value: true,
},
},
notification_templates: {
select: {
name: true,
subject: true,
email_content: true,
push_title: true,
push_body: true,
variables: true,
},
},
notification_channels: {
select: {
channel_type: true,
},
},
notification_user_segments: {
include: {
user_segments: {
select: {
value: true,
},
},
},
},
notification_recipients: {
select: {
status: true,
opened_at: true,
clicked_at: true,
},
},
},
});
if (!notification) {
throw createError({
statusCode: 404,
statusMessage:
"Notification not found or you do not have permission to access it",
});
}
// Calculate analytics
const totalRecipients = notification.notification_recipients.length;
const sentCount = notification.notification_recipients.filter(
(r) => r.status === "sent"
).length;
const deliveredCount = notification.notification_recipients.filter(
(r) => r.status === "delivered"
).length;
const failedCount = notification.notification_recipients.filter(
(r) => r.status === "failed"
).length;
const openedCount = notification.notification_recipients.filter(
(r) => r.opened_at !== null
).length;
const clickedCount = notification.notification_recipients.filter(
(r) => r.clicked_at !== null
).length;
// Calculate success rate
const successRate =
totalRecipients > 0
? Math.round((deliveredCount / totalRecipients) * 100)
: 0;
// Format the response
const formattedNotification = {
id: notification.id,
title: notification.title,
type: notification.type,
priority: notification.priority,
status: notification.status,
category: {
name: notification.notification_categories?.name || "Uncategorized",
value: notification.notification_categories?.value,
},
channels: notification.notification_channels.map((c) => c.channel_type),
deliveryType: notification.delivery_type,
scheduledAt: notification.scheduled_at,
timezone: notification.timezone,
expiresAt: notification.expires_at,
// A/B Testing
enableAbTesting: notification.enable_ab_testing,
abTestSplit: notification.ab_test_split,
abTestName: notification.ab_test_name,
// Tracking
enableTracking: notification.enable_tracking,
// Audience
audienceType: notification.audience_type,
specificUsers: notification.specific_users,
userSegments: notification.notification_user_segments.map(
(s) => s.user_segments.value
),
userStatus: notification.user_status,
registrationPeriod: notification.registration_period,
excludeUnsubscribed: notification.exclude_unsubscribed,
respectDoNotDisturb: notification.respect_do_not_disturb,
// Content
contentType: notification.content_type,
template: notification.notification_templates
? {
id: notification.template_id,
name: notification.notification_templates.name,
subject: notification.notification_templates.subject,
emailContent: notification.notification_templates.email_content,
pushTitle: notification.notification_templates.push_title,
pushBody: notification.notification_templates.push_body,
variables: notification.notification_templates.variables,
}
: null,
// Email Content
emailSubject: notification.email_subject,
emailContent: notification.email_content,
callToActionText: notification.call_to_action_text,
callToActionUrl: notification.call_to_action_url,
// Push Content
pushTitle: notification.push_title,
pushBody: notification.push_body,
pushImageUrl: notification.push_image_url,
// Analytics
analytics: {
estimatedReach: notification.estimated_reach,
actualSent: notification.actual_sent,
totalRecipients,
sentCount,
deliveredCount,
failedCount,
openedCount,
clickedCount,
successRate,
openRate:
totalRecipients > 0
? Math.round((openedCount / totalRecipients) * 100)
: 0,
clickRate:
totalRecipients > 0
? Math.round((clickedCount / totalRecipients) * 100)
: 0,
},
// Metadata
createdBy: notification.created_by,
createdAt: notification.created_at,
updatedAt: notification.updated_at,
sentAt: notification.sent_at,
};
return {
success: true,
data: formattedNotification,
};
} catch (error) {
console.error("Error fetching notification:", error);
if (error.code?.startsWith("P")) {
throw createError({
statusCode: 400,
statusMessage: "Database operation failed",
data: {
error: error.message,
code: error.code,
},
});
}
if (error.statusCode) {
throw error;
}
throw createError({
statusCode: 500,
statusMessage: "Failed to fetch notification",
data: {
error: error.message,
},
});
} finally {
await prisma.$disconnect();
}
});