fitaiProto/apps/admin/src/app/api/notifications/route.ts

151 lines
3.7 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { auth } from "@clerk/nextjs/server";
import { getDatabase } from "@/lib/database";
import log from "@/lib/logger";
import { ensureUserSynced } from "@/lib/sync-user";
/**
* GET /api/notifications
* Get all notifications for the authenticated user
*/
export async function GET(req: NextRequest) {
try {
const { userId } = await auth();
if (!userId) {
log.warn("Unauthorized notification fetch attempt");
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
log.debug("Fetching notifications for user", { userId });
const db = await getDatabase();
const notifications = await db.getNotificationsByUserId(userId);
log.debug("Notifications fetched successfully", {
userId,
count: notifications.length,
});
return NextResponse.json({
success: true,
data: notifications,
meta: {
timestamp: new Date().toISOString(),
count: notifications.length,
},
});
} catch (error) {
log.error("Failed to fetch notifications", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}
/**
* POST /api/notifications
* Create a new notification (admin/system only)
*/
export async function POST(req: NextRequest) {
try {
const { userId } = await auth();
if (!userId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const body = await req.json();
const { targetUserId, title, message, type } = body;
if (!targetUserId || !title || !message || !type) {
return NextResponse.json(
{
error: "Missing required fields: targetUserId, title, message, type",
},
{ status: 400 },
);
}
// Validate notification type
const validTypes = [
"payment_reminder",
"attendance",
"promotion",
"system",
];
if (!validTypes.includes(type)) {
return NextResponse.json(
{
error: `Invalid notification type. Must be one of: ${validTypes.join(", ")}`,
},
{ status: 400 },
);
}
const db = await getDatabase();
const currentUser = await ensureUserSynced(userId, db);
if (!currentUser) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const canCreateNotifications =
currentUser.role === "superAdmin" ||
currentUser.role === "admin" ||
currentUser.role === "trainer";
if (!canCreateNotifications) {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const targetUser = await db.getUserById(targetUserId);
if (!targetUser) {
return NextResponse.json(
{ error: "Target user not found" },
{ status: 404 },
);
}
if (
currentUser.role !== "superAdmin" &&
(!currentUser.gymId || targetUser.gymId !== currentUser.gymId)
) {
return NextResponse.json(
{ error: "Forbidden - Cannot notify users from other gyms" },
{ status: 403 },
);
}
const notification = await db.createNotification({
id: crypto.randomUUID(),
userId: targetUserId,
title,
message,
type,
read: false,
});
log.info("Notification created", {
id: notification.id,
targetUserId,
type,
});
return NextResponse.json({
success: true,
data: notification,
meta: {
timestamp: new Date().toISOString(),
},
});
} catch (error) {
log.error("Failed to create notification", error);
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 },
);
}
}