Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | /** * Notifications API Routes * * GET /api/notifications - Get user's notifications * DELETE /api/notifications - Delete all read notifications */ import { NextRequest, NextResponse } from 'next/server'; import { withAuth, withErrorHandling, successResponse, ApiSuccessResponse, } from '@/lib/api'; import { RouteContext } from '@/lib/api/middleware'; import { prisma } from '@/lib/prisma'; import { Session } from 'next-auth'; import type { NotificationType } from '@/lib/notifications/types'; interface NotificationWithMeta { id: string; userId: number; type: NotificationType; title: string; message: string; link: string | null; read: boolean; readAt: Date | null; createdAt: Date; metadata?: Record<string, unknown>; } interface NotificationsResponseData { notifications: NotificationWithMeta[]; unreadCount: number; } /** * GET /api/notifications * * Get paginated notifications for the authenticated user. * Includes unread count for badge display. */ async function handleGet( request: NextRequest, _context: RouteContext | undefined, session: Session ): Promise<NextResponse<ApiSuccessResponse<NotificationsResponseData>>> { const userId = session.user.id; const { searchParams } = new URL(request.url); const page = Math.max(1, parseInt(searchParams.get('page') || '1')); const limit = Math.min(50, Math.max(1, parseInt(searchParams.get('limit') || '20'))); const unreadOnly = searchParams.get('unread') === 'true'; const where = { userId, ...(unreadOnly && { read: false }), }; const [notifications, total, unreadCount] = await Promise.all([ prisma.notification.findMany({ where, orderBy: { createdAt: 'desc' }, skip: (page - 1) * limit, take: limit, }), prisma.notification.count({ where }), prisma.notification.count({ where: { userId, read: false }, }), ]); const transformedNotifications: NotificationWithMeta[] = notifications.map((n) => ({ id: n.id, userId: n.userId, type: n.type as NotificationType, title: n.title, message: n.message, link: n.link, read: n.read, readAt: null, createdAt: n.createdAt, metadata: undefined, })); // Return using paginatedResponse with custom shape return successResponse({ notifications: transformedNotifications, unreadCount, }, { meta: { page, limit, total, pages: Math.ceil(total / limit), hasNext: page < Math.ceil(total / limit), hasPrev: page > 1, }, }); } /** * DELETE /api/notifications * * Delete all read notifications for the authenticated user. */ async function handleDelete( _request: NextRequest, _context: RouteContext | undefined, session: Session ): Promise<NextResponse<ApiSuccessResponse<{ deletedCount: number }>>> { const userId = session.user.id; const result = await prisma.notification.deleteMany({ where: { userId, read: true, }, }); return successResponse({ deletedCount: result.count }); } export const GET = withErrorHandling(withAuth(handleGet)); export const DELETE = withErrorHandling(withAuth(handleDelete)); |