Refactor notification system: add API endpoints for creating and listing notifications, enhance asset management with new icons and logo, and update .gitignore to exclude unnecessary files.
This commit is contained in:
131
server/api/public/get-notification-list.get.js
Normal file
131
server/api/public/get-notification-list.get.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import { z } from "zod";
|
||||
import prisma from "~/server/utils/prisma";
|
||||
|
||||
const ENV = useRuntimeConfig();
|
||||
|
||||
function requireApiKey(event) {
|
||||
const headers = getRequestHeaders(event);
|
||||
const provided = headers["x-api-key"] || headers["X-API-Key"];
|
||||
const expected = ENV.notificationApiKey;
|
||||
if (!expected) {
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage:
|
||||
"Notification API is not configured (missing NUXT_NOTIFICATION_API_KEY environment variable)",
|
||||
});
|
||||
}
|
||||
if (!provided || provided !== expected) {
|
||||
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
||||
}
|
||||
}
|
||||
|
||||
const listSchema = z.object({
|
||||
page: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((v) => (v ? parseInt(v) : 1))
|
||||
.default("1"),
|
||||
limit: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((v) => (v ? parseInt(v) : 20))
|
||||
.default("20"),
|
||||
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 {
|
||||
requireApiKey(event);
|
||||
const params = listSchema.parse(getQuery(event) || {});
|
||||
|
||||
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 } },
|
||||
];
|
||||
}
|
||||
|
||||
const total = await prisma.notifications.count({ where });
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
const items = notifications.map((n) => {
|
||||
const totalRecipients = n.notification_recipients.length;
|
||||
const delivered = n.notification_recipients.filter(
|
||||
(r) => r.status === "delivered"
|
||||
).length;
|
||||
const successRate =
|
||||
totalRecipients > 0
|
||||
? Math.round((delivered / totalRecipients) * 100)
|
||||
: 0;
|
||||
return {
|
||||
id: n.id,
|
||||
title: n.title,
|
||||
category: n.notification_categories?.name || "Uncategorized",
|
||||
channels: n.notification_channels.map((c) => c.channel_type),
|
||||
priority: n.priority,
|
||||
status: n.status,
|
||||
recipients: totalRecipients,
|
||||
successRate,
|
||||
createdAt: n.created_at,
|
||||
};
|
||||
});
|
||||
|
||||
const totalPages = Math.ceil(total / params.limit);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
notifications: items,
|
||||
pagination: {
|
||||
page: params.page,
|
||||
totalPages,
|
||||
totalItems: total,
|
||||
hasMore: params.page < totalPages,
|
||||
},
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Invalid query parameters",
|
||||
data: error.errors,
|
||||
});
|
||||
}
|
||||
if (error.statusCode) throw error;
|
||||
throw createError({
|
||||
statusCode: 500,
|
||||
statusMessage: "Failed to fetch notifications",
|
||||
data: { error: error.message },
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user