@@ -5,12 +5,13 @@ import { prisma } from '../config/prisma.js';
55import { EmailService } from '../services/EmailService.js' ;
66import { createNotification } from './inAppNotificationController.js' ;
77import { sendAlertEmails as sendAlertEmailNotifications } from '../services/emailNotificationService.js' ;
8+ import { CacheService , CacheKeys , CacheTTL } from '../utils/cache.js' ;
89
910const isAdmin = ( role ?: OrganizationRole ) => role === 'ADMIN' ;
1011
1112/**
12- * @desc Get all alerts (public shows only published, admins see all)
13- * @route GET /api/alerts?priority
13+ * @desc Get all alerts with pagination
14+ * @route GET /api/alerts?priority&page=1&limit=20
1415 * @access Public (optional authentication)
1516 */
1617export const getAlerts = async ( req : AuthenticatedRequest , res : Response ) => {
@@ -40,8 +41,31 @@ export const getAlerts = async (req: AuthenticatedRequest, res: Response) => {
4041 }
4142 }
4243
44+ const page = parseInt ( req . query . page as string ) || 1 ;
45+ const limit = parseInt ( req . query . limit as string ) || 20 ;
46+ const skip = ( page - 1 ) * limit ;
47+
4348 const { priority, isPublished } = req . query ;
4449
50+ const cacheKey = CacheKeys . alerts (
51+ page ,
52+ limit ,
53+ isAuthenticatedAdmin
54+ ? isPublished === 'true'
55+ ? true
56+ : isPublished === 'false'
57+ ? false
58+ : undefined
59+ : true ,
60+ priority as string
61+ ) ;
62+ const cachedData = await CacheService . get < any > ( cacheKey ) ;
63+
64+ if ( cachedData ) {
65+ console . log ( `Returning cached alerts (admin: ${ isAuthenticatedAdmin } )` ) ;
66+ return res . status ( 200 ) . json ( cachedData ) ;
67+ }
68+
4569 const where : any = {
4670 ...( priority && { priority : priority as AlertPriority } ) ,
4771
@@ -51,13 +75,31 @@ export const getAlerts = async (req: AuthenticatedRequest, res: Response) => {
5175 isPublished !== undefined && { isPublished : isPublished === 'true' } ) ,
5276 } ;
5377
54- const alerts = await prisma . alert . findMany ( {
55- where,
56- orderBy : [ { priority : 'asc' } , { createdAt : 'desc' } ] ,
57- } ) ;
78+ const [ alerts , total ] = await Promise . all ( [
79+ prisma . alert . findMany ( {
80+ where,
81+ orderBy : [ { priority : 'asc' } , { createdAt : 'desc' } ] ,
82+ take : limit ,
83+ skip,
84+ } ) ,
85+ prisma . alert . count ( { where } ) ,
86+ ] ) ;
87+
88+ const response = {
89+ data : alerts ,
90+ pagination : {
91+ total,
92+ page,
93+ limit,
94+ totalPages : Math . ceil ( total / limit ) ,
95+ hasMore : skip + alerts . length < total ,
96+ } ,
97+ } ;
98+
99+ await CacheService . set ( cacheKey , response , CacheTTL . ALERTS_LIST ) ;
58100
59101 console . log ( `Returning ${ alerts . length } alerts (admin: ${ isAuthenticatedAdmin } )` ) ;
60- res . status ( 200 ) . json ( alerts ) ;
102+ res . status ( 200 ) . json ( response ) ;
61103 } catch ( error ) {
62104 console . error ( 'Error fetching alerts:' , error ) ;
63105 res . status ( 500 ) . json ( { error : 'Failed to fetch alerts' } ) ;
@@ -200,6 +242,8 @@ export const createAlert = async (req: AuthenticatedRequest, res: Response) => {
200242 } ,
201243 } ) ;
202244
245+ await CacheService . deletePattern ( CacheKeys . alertsAll ( ) ) ;
246+
203247 if ( newAlert . isPublished ) {
204248 try {
205249 await createNotification ( 'ALERT' , newAlert . title , newAlert . id ) ;
@@ -248,7 +292,9 @@ export const updateAlert = async (req: AuthenticatedRequest, res: Response) => {
248292 } ,
249293 } ) ;
250294
251- // If alert is being published for the first time, send email notifications
295+ await CacheService . deletePattern ( CacheKeys . alertsAll ( ) ) ;
296+ await CacheService . delete ( CacheKeys . alertById ( id ) ) ;
297+
252298 if ( updatedAlert . isPublished && ! existingAlert . isPublished ) {
253299 await sendAlertEmails ( updatedAlert ) ;
254300 }
@@ -267,7 +313,6 @@ export const updateAlert = async (req: AuthenticatedRequest, res: Response) => {
267313 */
268314export const deleteAlert = async ( req : AuthenticatedRequest , res : Response ) => {
269315 try {
270- // Ensure user is authenticated
271316 if ( ! req . user ?. id ) {
272317 return res . status ( 401 ) . json ( { error : 'Authentication required' } ) ;
273318 }
@@ -284,6 +329,10 @@ export const deleteAlert = async (req: AuthenticatedRequest, res: Response) => {
284329 }
285330
286331 await prisma . alert . delete ( { where : { id } } ) ;
332+
333+ await CacheService . deletePattern ( CacheKeys . alertsAll ( ) ) ;
334+ await CacheService . delete ( CacheKeys . alertById ( id ) ) ;
335+
287336 res . status ( 204 ) . end ( ) ;
288337 } catch ( error ) {
289338 console . error ( 'Error deleting alert:' , error ) ;
@@ -325,6 +374,9 @@ export const publishAlert = async (req: AuthenticatedRequest, res: Response) =>
325374 } ,
326375 } ) ;
327376
377+ await CacheService . deletePattern ( CacheKeys . alertsAll ( ) ) ;
378+ await CacheService . delete ( CacheKeys . alertById ( id ) ) ;
379+
328380 try {
329381 await sendAlertEmailNotifications ( publishedAlert . id ) ;
330382 console . log ( 'Alert notifications sent successfully' ) ;
@@ -346,7 +398,6 @@ export const publishAlert = async (req: AuthenticatedRequest, res: Response) =>
346398 */
347399async function sendAlertEmails ( alert : any ) : Promise < void > {
348400 try {
349- // Get all active organizations with membershipActive = true
350401 const activeOrganizations = await prisma . organization . findMany ( {
351402 where : {
352403 membershipActive : true ,
@@ -362,17 +413,13 @@ async function sendAlertEmails(alert: any): Promise<void> {
362413 } ,
363414 } ) ;
364415
365- // Filter organizations by matching tags
366416 let targetOrganizations = activeOrganizations ;
367417
368- // If alert has tags, only send to organizations with matching tags
369418 if ( alert . tags && alert . tags . length > 0 ) {
370419 targetOrganizations = activeOrganizations . filter ( org => {
371- // Check if organization has any matching tags with the alert
372420 return alert . tags . some ( ( alertTag : string ) => org . tags . includes ( alertTag ) ) ;
373421 } ) ;
374422 }
375- // If alert has no tags, it's a broadcast alert sent to all active organizations
376423
377424 console . log (
378425 `Sending alert "${ alert . title } " to ${ targetOrganizations . length } organizations` +
0 commit comments