This commit is contained in:
2026-01-08 21:36:15 +01:00
parent 05cf3bafd2
commit d689df0270
23 changed files with 25233 additions and 88 deletions

View File

@@ -0,0 +1,72 @@
import { Controller, Get, Post, Param, Req, Inject, HttpStatus, Res } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import type { Response } from 'express';
import { NotificationsService } from './NotificationsService';
type AuthenticatedRequest = {
user?: { userId: string };
};
@ApiTags('notifications')
@Controller('notifications')
export class NotificationsController {
constructor(
@Inject(NotificationsService) private readonly notificationsService: NotificationsService,
) {}
@Get('unread')
@ApiOperation({ summary: 'Get unread notifications for current user' })
@ApiResponse({ status: 200, description: 'List of unread notifications' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
async getUnreadNotifications(
@Req() req: AuthenticatedRequest,
@Res() res: Response,
): Promise<void> {
const userId = req.user?.userId;
if (!userId) {
res.status(HttpStatus.UNAUTHORIZED).json({ error: 'Unauthorized' });
return;
}
const notifications = await this.notificationsService.getUnreadNotifications(userId);
res.status(HttpStatus.OK).json({ notifications });
}
@Post('read/:notificationId')
@ApiOperation({ summary: 'Mark notification as read' })
@ApiResponse({ status: 200, description: 'Notification marked as read' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
async markAsRead(
@Param('notificationId') notificationId: string,
@Req() req: AuthenticatedRequest,
@Res() res: Response,
): Promise<void> {
const userId = req.user?.userId;
if (!userId) {
res.status(HttpStatus.UNAUTHORIZED).json({ error: 'Unauthorized' });
return;
}
await this.notificationsService.markAsRead(notificationId, userId);
res.status(HttpStatus.OK).json({ success: true });
}
@Get('all')
@ApiOperation({ summary: 'Get all notifications for current user' })
@ApiResponse({ status: 200, description: 'List of all notifications' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
async getAllNotifications(
@Req() req: AuthenticatedRequest,
@Res() res: Response,
): Promise<void> {
const userId = req.user?.userId;
if (!userId) {
res.status(HttpStatus.UNAUTHORIZED).json({ error: 'Unauthorized' });
return;
}
const notifications = await this.notificationsService.getAllNotifications(userId);
res.status(HttpStatus.OK).json({ notifications });
}
}

View File

@@ -1,9 +1,13 @@
import { Module } from '@nestjs/common';
import { NotificationsPersistenceModule } from '../../persistence/notifications/NotificationsPersistenceModule';
import { NotificationsController } from './NotificationsController';
import { NotificationsService } from './NotificationsService';
@Module({
imports: [NotificationsPersistenceModule],
exports: [NotificationsPersistenceModule],
controllers: [NotificationsController],
providers: [NotificationsService],
exports: [NotificationsPersistenceModule, NotificationsService],
})
export class NotificationsModule {}

View File

@@ -0,0 +1,35 @@
import { Inject, Injectable } from '@nestjs/common';
import type { INotificationRepository } from '@core/notifications/domain/repositories/INotificationRepository';
import { NOTIFICATION_REPOSITORY_TOKEN } from '../../persistence/notifications/NotificationsPersistenceTokens';
@Injectable()
export class NotificationsService {
constructor(
@Inject(NOTIFICATION_REPOSITORY_TOKEN)
private readonly notificationRepository: INotificationRepository,
) {}
async getUnreadNotifications(userId: string): Promise<Array<Record<string, unknown>>> {
const notifications = await this.notificationRepository.findUnreadByRecipientId(userId);
return notifications.map(n => n.toJSON() as Record<string, unknown>);
}
async getAllNotifications(userId: string): Promise<Array<Record<string, unknown>>> {
const notifications = await this.notificationRepository.findByRecipientId(userId);
return notifications.map(n => n.toJSON() as Record<string, unknown>);
}
async markAsRead(notificationId: string, userId: string): Promise<void> {
const notification = await this.notificationRepository.findById(notificationId);
if (!notification) {
throw new Error('Notification not found');
}
if (notification.recipientId !== userId) {
throw new Error('Unauthorized');
}
const updated = notification.markAsRead();
await this.notificationRepository.update(updated);
}
}