import { z } from "zod"; import prisma from "~/server/utils/prisma"; // Query parameter validation schema const listNotificationSchema = z.object({ page: z .string() .transform((val) => parseInt(val) || 1) .optional(), limit: z .string() .transform((val) => parseInt(val) || 20) .optional(), status: z.string().optional(), priority: z.string().optional(), category: z.string().optional(), search: z.string().optional(), sortBy: z.string().default("created_at"), sortOrder: z.enum(["asc", "desc"]).default("desc"), }); export default defineEventHandler(async (event) => { try { // Parse and validate query parameters const queryParams = getQuery(event) || {}; const params = listNotificationSchema.parse(queryParams); // Build the where clause for filtering const where = {}; if (params.status) { where.status = params.status; } if (params.priority) { where.priority = params.priority; } if (params.category) { where.notification_categories = { value: params.category }; } if (params.search) { where.OR = [ { title: { contains: params.search } }, { email_subject: { contains: params.search } }, { push_title: { contains: params.search } } ]; } // Get total count for pagination const total = await prisma.notifications.count({ where }); // Fetch notifications with relations const notifications = await prisma.notifications.findMany({ where, select: { id: true, title: true, priority: true, status: true, delivery_type: true, scheduled_at: true, created_at: true, notification_categories: { select: { name: true } }, notification_channels: { select: { channel_type: true } }, notification_recipients: { select: { status: true } } }, orderBy: { [params.sortBy]: params.sortOrder }, skip: (params.page - 1) * params.limit, take: params.limit }); // Format the response with only essential fields const formattedNotifications = notifications.map(notification => { const totalRecipients = notification.notification_recipients.length; const deliveredCount = notification.notification_recipients.filter( r => r.status === 'delivered' ).length; const successRate = totalRecipients > 0 ? Math.round((deliveredCount / totalRecipients) * 100) : 0; return { title: notification.title, category: notification.notification_categories?.name || 'Uncategorized', channels: notification.notification_channels.map(c => c.channel_type), priority: notification.priority, status: notification.status, recipients: totalRecipients, // successRate: { // successRate, // delivered: deliveredCount, // total: totalRecipients // }, createdAt: notification.created_at, action: notification.id, }; }); // Calculate pagination metadata const totalPages = Math.ceil(total / params.limit); return { success: true, data: { notifications: formattedNotifications, pagination: { page: params.page, totalPages, totalItems: total, hasMore: params.page < totalPages }, }, }; } catch (error) { console.error("Error fetching notifications:", 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 notifications", data: { error: error.message } }); } finally { } });