Files
Nas-Notification/server/api/notifications/draft.post.js

235 lines
7.3 KiB
JavaScript

import prisma from "~/server/utils/prisma";
export default defineEventHandler(async (event) => {
try {
// Read request body
const body = await readBody(event);
// Get current user
const user = event.context.user;
if (!user || !user.userID) {
throw createError({
statusCode: 401,
statusMessage: 'Authentication required'
});
}
// Prepare data for saving
const draftData = {
title: body.title || 'Untitled Draft',
type: body.type || 'single',
priority: body.priority || 'medium',
category: body.category,
channels: Array.isArray(body.channels) ? body.channels : [],
emailSubject: body.emailSubject || null,
deliveryType: body.deliveryType || 'immediate',
scheduledAt: body.scheduledAt || null,
timezone: body.timezone || 'UTC',
audienceType: body.audienceType || 'all',
specificUsers: body.specificUsers || null,
userSegments: Array.isArray(body.userSegments) ? body.userSegments : [],
excludeUnsubscribed: body.excludeUnsubscribed !== false, // default true
contentType: body.contentType || 'new',
selectedTemplate: body.selectedTemplate || null,
emailContent: body.emailContent || null,
callToActionText: body.callToActionText || null,
callToActionUrl: body.callToActionUrl || null,
pushTitle: body.pushTitle || null,
pushBody: body.pushBody || null,
draftId: body.draftId // For updating existing drafts
};
// Use Prisma transaction
const result = await prisma.$transaction(async (tx) => {
let notificationId = draftData.draftId;
// Get category if provided
let categoryId = null;
if (draftData.category) {
const category = await tx.notification_categories.findFirst({
where: { value: draftData.category }
});
if (category) {
categoryId = category.id;
}
}
// Get template if provided
let templateId = null;
if (draftData.contentType === 'template' && draftData.selectedTemplate) {
const template = await tx.notification_templates.findFirst({
where: {
value: draftData.selectedTemplate,
is_active: true
}
});
if (template) {
templateId = template.id;
}
}
if (notificationId) {
// Check if the draft exists and belongs to the user
const existingDraft = await tx.notifications.findFirst({
where: {
id: notificationId,
created_by: user.userID.toString(),
status: 'draft'
}
});
if (!existingDraft) {
throw createError({
statusCode: 404,
statusMessage: 'Draft not found or you do not have permission to update it'
});
}
// Update existing draft
const updatedDraft = await tx.notifications.update({
where: { id: notificationId },
data: {
title: draftData.title,
type: draftData.type,
priority: draftData.priority,
category_id: categoryId,
delivery_type: draftData.deliveryType,
scheduled_at: draftData.scheduledAt ? new Date(draftData.scheduledAt) : null,
timezone: draftData.timezone,
audience_type: draftData.audienceType,
specific_users: draftData.specificUsers,
exclude_unsubscribed: draftData.excludeUnsubscribed,
content_type: draftData.contentType,
template_id: templateId,
email_subject: draftData.emailSubject,
email_content: draftData.emailContent,
call_to_action_text: draftData.callToActionText,
call_to_action_url: draftData.callToActionUrl,
push_title: draftData.pushTitle,
push_body: draftData.pushBody,
updated_at: new Date()
}
});
notificationId = updatedDraft.id;
} else {
// Create new draft
const newDraft = await tx.notifications.create({
data: {
title: draftData.title,
type: draftData.type,
priority: draftData.priority,
category_id: categoryId,
delivery_type: draftData.deliveryType,
scheduled_at: draftData.scheduledAt ? new Date(draftData.scheduledAt) : null,
timezone: draftData.timezone,
audience_type: draftData.audienceType,
specific_users: draftData.specificUsers,
exclude_unsubscribed: draftData.excludeUnsubscribed,
respect_do_not_disturb: true,
enable_tracking: true,
content_type: draftData.contentType,
template_id: templateId,
email_subject: draftData.emailSubject,
email_content: draftData.emailContent,
call_to_action_text: draftData.callToActionText,
call_to_action_url: draftData.callToActionUrl,
push_title: draftData.pushTitle,
push_body: draftData.pushBody,
created_by: user.userID.toString(),
status: 'draft'
}
});
notificationId = newDraft.id;
}
// Update channels
if (draftData.channels && draftData.channels.length > 0) {
// Delete existing channels
await tx.notification_channels.deleteMany({
where: { notification_id: notificationId }
});
// Insert new channels
await tx.notification_channels.createMany({
data: draftData.channels.map(channel => ({
notification_id: notificationId,
channel_type: channel
}))
});
}
// Update segments
if (draftData.userSegments && draftData.userSegments.length > 0) {
// Delete existing segments
await tx.notification_user_segments.deleteMany({
where: { notification_id: notificationId }
});
// Insert new segments
for (const segment of draftData.userSegments) {
const segmentData = await tx.user_segments.findFirst({
where: {
value: segment,
is_active: true
}
});
if (segmentData) {
await tx.notification_user_segments.create({
data: {
notification_id: notificationId,
segment_id: segmentData.id
}
});
}
}
}
return {
id: notificationId
};
});
return {
success: true,
data: {
id: result.id,
message: 'Draft saved successfully'
}
};
} catch (error) {
console.error('Error saving draft:', error);
// Handle Prisma errors
if (error.code && error.code.startsWith('P')) {
throw createError({
statusCode: 400,
statusMessage: 'Database operation failed',
data: {
error: error.message,
code: error.code
}
});
}
// Handle known errors with status codes
if (error.statusCode) {
throw error;
}
// Generic server error
throw createError({
statusCode: 500,
statusMessage: 'Failed to save draft',
data: {
error: error.message
}
});
} finally {
}
});