import { Controller, Get, Body, Param, UseGuards, Query, Patch, Put, Post } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiParam, ApiQuery, ApiHeader } from '@nestjs/swagger'; import { NotificationService } from '../services/notification.service'; import { NotificationPreferenceService } from '../services/notification-preference.service'; import { AuthGuard } from '../../auth/guards/auth.guard'; import { UserId } from '../../../common/decorators/user-id.decorator'; import { AdminAuthGuard } from '../../auth/guards/adminAuth.guard'; import { RestId } from '../../../common/decorators/rest-id.decorator'; import { UpdatePreferenceDto } from '../dto/update-preference.dto'; import { CreatePreferenceDto } from '../dto/create-preference.dto'; import { AdminId } from 'src/common/decorators/admin-id.decorator'; import { API_HEADER_SLUG } from 'src/common/constants/index'; import { NotificationMessage } from 'src/common/enums/message.enum'; import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard'; import { Permissions } from 'src/common/decorators/permissions.decorator'; import { Permission } from 'src/common/enums/permission.enum'; @ApiTags('notifications') @Controller() export class NotificationsController { constructor( private readonly notificationService: NotificationService, private readonly preferenceService: NotificationPreferenceService, ) { } @UseGuards(AuthGuard) @ApiBearerAuth() @Get('public/notifications') @ApiOperation({ summary: 'Get user restaurant notifications' }) @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Number of items to return (default: 50)' }) @ApiQuery({ name: 'cursor', required: false, type: String, description: 'Cursor for pagination (ID of the last item from previous page)', }) @ApiQuery({ name: 'status', required: false, enum: ['seen', 'unseen'], description: 'Filter by notification status' }) async getUserNotifications( @UserId() userId: string, @RestId() restaurantId: string, @Query('limit') limit?: number, @Query('cursor') cursor?: string, @Query('status') status?: 'seen' | 'unseen', ) { return await this.notificationService.findByUserAndRestaurant( userId, restaurantId, limit ? parseInt(limit.toString(), 10) : 50, cursor, status, ); } @UseGuards(AuthGuard) @ApiBearerAuth() @Get('public/notifications/unseen-count') @ApiOperation({ summary: 'Get unseen notifications count for user' }) async getUserUnseenCount(@UserId() userId: string, @RestId() restaurantId: string) { const count = await this.notificationService.countUnseenByUserAndRestaurant(userId, restaurantId); return { count }; } @UseGuards(AuthGuard) @ApiBearerAuth() @Put('public/notifications/:id') @ApiOperation({ summary: 'Read a notification ' }) @ApiParam({ name: 'id', description: 'Notification ID' }) async readNotificationUser(@RestId() restaurantId: string, @Param('id') id: string, @UserId() userId: string) { await this.notificationService.readNotificationAsUser(id, userId, restaurantId); return { message: NotificationMessage.READ_SUCCESS }; } @UseGuards(AuthGuard) @ApiBearerAuth() @Put('public/notifications/read/all') @ApiOperation({ summary: 'Read all notification ' }) async readAllNotificationUser(@RestId() restaurantId: string, @UserId() userId: string) { await this.notificationService.readAllNotifsAsUser(userId, restaurantId); return { message: NotificationMessage.READ_SUCCESS }; } /* ***************** Admin Endpoints ***************** */ @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Get('admin/notifications') @ApiOperation({ summary: 'Get Admin notifications' }) @ApiQuery({ name: 'limit', required: false, type: Number }) @ApiQuery({ name: 'cursor', required: false, type: String, description: 'Cursor for pagination (ID of the last item from previous page)', }) @ApiQuery({ name: 'status', required: false, enum: ['seen', 'unseen'], description: 'Filter by notification status' }) async getAdminNotifications( @AdminId() adminId: string, @RestId() restaurantId: string, @Query('limit') limit?: number, @Query('cursor') cursor?: string, @Query('status') status?: 'seen' | 'unseen', ) { const parsedLimit = limit ? parseInt(limit.toString(), 10) : 50; return await this.notificationService.findByRestaurant(restaurantId, adminId, parsedLimit, cursor, status); } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Get('admin/notifications/unseen-count') @ApiOperation({ summary: 'Get unseen notifications count for admin' }) async getAdminUnseenCount(@AdminId() adminId: string, @RestId() restaurantId: string) { const count = await this.notificationService.countUnseenByRestaurant(adminId, restaurantId); return { count }; } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Put('admin/notifications/:id') @ApiOperation({ summary: 'Read a notification ' }) @ApiParam({ name: 'id', description: 'Notification ID' }) async readNotificationAdmin(@RestId() restaurantId: string, @AdminId() adminId: string, @Param('id') id: string) { await this.notificationService.readNotificationAdmin(id, adminId, restaurantId); return { message: NotificationMessage.READ_SUCCESS }; } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Put('admin/notifications/read/all') @ApiOperation({ summary: 'Read all notification ' }) async readAllNotificationAdmin(@RestId() restaurantId: string, @AdminId() adminId: string, @Param('id') id: string) { await this.notificationService.readAllNotifsAsAdmin(adminId, restaurantId); return { message: NotificationMessage.READ_SUCCESS }; } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.MANAGE_SETTINGS) @Get('admin/notification-preferences') @ApiOperation({ summary: 'Get all notification preferences for a restaurant' }) async getPreferences(@RestId() restaurantId: string) { return this.preferenceService.findByRestaurant(restaurantId); } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.MANAGE_SETTINGS) @Patch('admin/notification-preferences/:id') @ApiOperation({ summary: 'Update notification channels' }) @ApiParam({ name: 'id', description: 'Notification preference ID' }) async updatePreference( @RestId() restaurantId: string, @Param('id') preferenceId: string, @Body() dto: UpdatePreferenceDto, ) { return this.preferenceService.updatePreference(preferenceId, restaurantId, dto); } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.MANAGE_SETTINGS) @Post('admin/notification-preferences') @ApiOperation({ summary: 'Create notification preference' }) async createPreference( @RestId() restaurantId: string, @Body() dto: CreatePreferenceDto, ) { return this.preferenceService.create(restaurantId, dto); } @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Get('admin/notifications/sms-usage') @ApiOperation({ summary: 'Get SMS usage for my restaurant' }) async getRestaurantSmsUsage(@RestId() restaurantId: string) { const smsCount = await this.notificationService.getSmsCountByRestaurantId(restaurantId); return { smsCount }; } // super admin endpoints @UseGuards(SuperAdminAuthGuard) @ApiBearerAuth() @Get('super-admin/notifications/sms-count') @ApiOperation({ summary: 'Get SMS count for each restaurant with pagination' }) @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number (default: 1)', minimum: 1 }) @ApiQuery({ name: 'limit', required: false, type: Number, description: 'Items per page (default: 10)', minimum: 1 }) async getSmsCount( @Query('page') page?: number, @Query('limit') limit?: number, ) { const parsedPage = page ? parseInt(page.toString(), 10) : 1; const parsedLimit = limit ? parseInt(limit.toString(), 10) : 10; return await this.notificationService.getSmsCountByRestaurant(parsedPage, parsedLimit); } }