Update various configuration files, components, and assets; enhance notification system and API endpoints; improve documentation and styles across the application.
This commit is contained in:
161
server/api/notifications/test-send.post.js
Normal file
161
server/api/notifications/test-send.post.js
Normal file
@@ -0,0 +1,161 @@
|
||||
import { z } from 'zod'
|
||||
import { sendEmailNotification } from '~/server/utils/emailService'
|
||||
|
||||
const testSendSchema = z.object({
|
||||
email: z.string().email('Valid email is required'),
|
||||
notificationId: z.string().uuid().optional(),
|
||||
testData: z.object({
|
||||
title: z.string(),
|
||||
channels: z.array(z.string()),
|
||||
emailSubject: z.string().optional(),
|
||||
emailContent: z.string().optional(),
|
||||
pushTitle: z.string().optional(),
|
||||
pushBody: z.string().optional(),
|
||||
callToActionText: z.string().optional(),
|
||||
callToActionUrl: z.string().optional()
|
||||
}).optional()
|
||||
})
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
const body = await readValidatedBody(event, testSendSchema.parse)
|
||||
const { $db } = useNitroApp()
|
||||
|
||||
let notificationData = body.testData
|
||||
|
||||
// If notificationId is provided, fetch from database
|
||||
if (body.notificationId) {
|
||||
const result = await $db.query(`
|
||||
SELECT n.*, nc.channel_type, nt.subject as template_subject,
|
||||
nt.email_content as template_email_content,
|
||||
nt.push_title as template_push_title,
|
||||
nt.push_body as template_push_body
|
||||
FROM notifications n
|
||||
LEFT JOIN notification_channels nc ON n.id = nc.notification_id
|
||||
LEFT JOIN notification_templates nt ON n.template_id = nt.id
|
||||
WHERE n.id = $1
|
||||
`, [body.notificationId])
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: 'Notification not found'
|
||||
})
|
||||
}
|
||||
|
||||
const notification = result.rows[0]
|
||||
const channels = result.rows.map(row => row.channel_type).filter(Boolean)
|
||||
|
||||
notificationData = {
|
||||
title: notification.title,
|
||||
channels,
|
||||
emailSubject: notification.email_subject || notification.template_subject,
|
||||
emailContent: notification.email_content || notification.template_email_content,
|
||||
pushTitle: notification.push_title || notification.template_push_title,
|
||||
pushBody: notification.push_body || notification.template_push_body,
|
||||
callToActionText: notification.call_to_action_text,
|
||||
callToActionUrl: notification.call_to_action_url
|
||||
}
|
||||
}
|
||||
|
||||
if (!notificationData) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: 'Either notificationId or testData is required'
|
||||
})
|
||||
}
|
||||
|
||||
const results = []
|
||||
|
||||
// Send test email
|
||||
if (notificationData.channels.includes('email') && notificationData.emailContent) {
|
||||
try {
|
||||
await sendEmailNotification({
|
||||
to: body.email,
|
||||
subject: notificationData.emailSubject || 'Test Notification',
|
||||
content: notificationData.emailContent,
|
||||
callToActionText: notificationData.callToActionText,
|
||||
callToActionUrl: notificationData.callToActionUrl
|
||||
})
|
||||
|
||||
results.push({
|
||||
channel: 'email',
|
||||
status: 'sent',
|
||||
message: 'Test email sent successfully'
|
||||
})
|
||||
} catch (error) {
|
||||
results.push({
|
||||
channel: 'email',
|
||||
status: 'failed',
|
||||
message: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Send test push notification
|
||||
if (notificationData.channels.includes('push') && notificationData.pushTitle) {
|
||||
try {
|
||||
await sendTestPush({
|
||||
email: body.email, // Use email to identify user for push
|
||||
title: notificationData.pushTitle,
|
||||
body: notificationData.pushBody
|
||||
})
|
||||
|
||||
results.push({
|
||||
channel: 'push',
|
||||
status: 'sent',
|
||||
message: 'Test push notification sent successfully'
|
||||
})
|
||||
} catch (error) {
|
||||
results.push({
|
||||
channel: 'push',
|
||||
status: 'failed',
|
||||
message: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
message: 'Test notifications processed',
|
||||
results
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error sending test notification:', error)
|
||||
|
||||
if (error.statusCode) {
|
||||
throw error
|
||||
}
|
||||
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: 'Failed to send test notification'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Mock push notification function - replace with your actual push service
|
||||
async function sendTestPush({ email, title, body }) {
|
||||
// This is a mock implementation
|
||||
// Replace with your actual push service (Firebase, OneSignal, etc.)
|
||||
|
||||
console.log('Sending test push notification:', {
|
||||
email,
|
||||
title,
|
||||
body
|
||||
})
|
||||
|
||||
// Simulate push sending delay
|
||||
await new Promise(resolve => setTimeout(resolve, 800))
|
||||
|
||||
// For demo purposes, we'll just log and return success
|
||||
// In a real implementation, you would:
|
||||
// 1. Find user's device tokens by email
|
||||
// 2. Send to push notification service
|
||||
// 3. Handle any errors appropriately
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user