Skip to content

Commit fa65459

Browse files
committed
created the notification feature for users
1 parent fd682b3 commit fa65459

File tree

5 files changed

+108
-12
lines changed

5 files changed

+108
-12
lines changed

src/shared/schema/user.schema.ts

+24-11
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@ export type UserDocument = HydratedDocument<User>;
3030

3131
@Schema({ timestamps: true })
3232
export class User {
33+
34+
@Prop({ type: Types.ObjectId, ref: 'User', required: true })
35+
userId: string
36+
37+
@Prop({ required: true })
38+
message: string;
39+
40+
@Prop({ default: false })
41+
read: boolean;
42+
43+
@Prop({ type: [{ message: String, read: Boolean, createdAt: Date }], default: [] })
44+
notifications: { message: string; read: boolean; createdAt: Date }[];
45+
3346
@Prop({ index: true })
3447
firstName: string;
3548

@@ -65,8 +78,8 @@ export class User {
6578

6679
@Prop({ index: true })
6780
gender: string;
68-
69-
81+
82+
7083

7184
@Prop({
7285
type: {
@@ -116,15 +129,15 @@ export class User {
116129

117130
@Prop(raw(SocialsRawSchema))
118131
socials: Socials;
119-
120-
@Prop({
121-
index: true,
122-
default: VerificationStatus.NOT_VERIFIED
123-
})
124-
verificationStatus: VerificationStatus;
125-
126-
@Prop({ type: Date })
127-
nextVerificationRequestDate: Date;
132+
133+
@Prop({
134+
index: true,
135+
default: VerificationStatus.NOT_VERIFIED
136+
})
137+
verificationStatus: VerificationStatus;
138+
139+
@Prop({ type: Date })
140+
nextVerificationRequestDate: Date;
128141
}
129142

130143
export const UserSchema = SchemaFactory.createForClass(User);
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { ApiProperty } from "@nestjs/swagger";
2+
import { IsNotEmpty, IsString } from "class-validator";
3+
4+
export class CreateNotificationDto {
5+
@ApiProperty()
6+
@IsString()
7+
@IsNotEmpty()
8+
message: any;
9+
10+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { IsMongoId, IsNotEmpty } from 'class-validator';
2+
3+
export class UpdateNotificationDto {
4+
@IsMongoId()
5+
@IsNotEmpty()
6+
message: string;
7+
read: boolean;
8+
}

src/users/users.controller.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ import { ApiReq, userRoles, userStatuses } from 'src/shared/interfaces';
1717
import { CreateUserDto } from 'src/shared/dtos/create-user.dto';
1818
import { UserChangePasswordDto } from './dto/user-change-password.dto';
1919
import { UserAddPhotoDto } from './dto/user-add-photo.dto';
20+
import { CreateNotificationDto } from './dto/create-notification.dto';
2021

2122
@ApiTags('users')
2223
@Controller('users')
2324
export class UsersController {
24-
constructor(private readonly usersService: UsersService) {}
25+
constructor(private readonly usersService: UsersService) { }
2526

2627
@Post()
2728
create(@Request() req: ApiReq, @Body() createUserDto: CreateUserDto) {
@@ -127,4 +128,33 @@ export class UsersController {
127128
) {
128129
return this.usersService.requestVerification(req, userId);
129130
}
131+
132+
@ApiBearerAuth()
133+
@UseGuards(JwtUsersGuard)
134+
@Post(':userId/create-notification')
135+
async createNotification(
136+
@Param('userId') userId: string,
137+
@Body() createNotificationDto: CreateNotificationDto,
138+
139+
) {
140+
const { message } = createNotificationDto;
141+
return this.usersService.createNotification(userId, message)
142+
}
143+
144+
@ApiBearerAuth()
145+
@UseGuards(JwtUsersGuard)
146+
@Get(':userId/get-notifications')
147+
async getAllNotificationsForUser(
148+
@Param('userId') userId: string
149+
) {
150+
return this.usersService.getAllNotificationsForUser(userId);
151+
}
152+
153+
@Patch(':userId/is-read-notifications/:notificationId')
154+
async markNotificationAsRead(
155+
@Param('userId') userId: string,
156+
@Param('notificationId') notificationId: string,
157+
) {
158+
return this.usersService.markNotificationAsRead(userId, notificationId);
159+
}
130160
}

src/users/users.service.ts

+35
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import {
3030
} from 'src/shared/interfaces';
3131
import { UserInviteDto } from './dto/user-invite.dto';
3232
import { VerificationStatus } from 'src/shared/interfaces/user.type';
33+
import { UpdateNotificationDto } from './dto/update-notification.dto';
34+
import { CreateNotificationDto } from './dto/create-notification.dto';
3335
@Injectable()
3436
export class UsersService {
3537
constructor(
@@ -299,5 +301,38 @@ export class UsersService {
299301
//5. Save the updated user
300302
await user.save();
301303
}
304+
305+
async createNotification(userId: string, message: string) {
306+
const notification = { message: message, read: false, createdAt: new Date() };
307+
return this.userModel.findOneAndUpdate(
308+
{ _id: userId },
309+
{ $push: { notifications: notification } },
310+
{ new: true }
311+
).exec();
312+
313+
}
314+
315+
async getAllNotificationsForUser(userId) {
316+
const user = await this.userModel.findById(userId, 'notifications').exec();
317+
if (!user) {
318+
throw new NotFoundException(`User with ID ${userId} not found`);
319+
}
320+
return user.notifications;
321+
}
322+
async updateNotification(userId: string, notificationId: string, updateNotificationDto: UpdateNotificationDto): Promise<User> {
323+
return this.userModel.findOneAndUpdate(
324+
{ _id: userId, 'notifications._id': notificationId },
325+
{ $set: { 'notifications.$.message': updateNotificationDto.message } },
326+
{ new: true }
327+
).exec();
328+
}
329+
async markNotificationAsRead(userId: string, notificationId: string): Promise<User> {
330+
return this.userModel.findOneAndUpdate(
331+
{ _id: userId, 'notifications._id': notificationId },
332+
{ $set: { 'notifications.$.read': true } },
333+
{ new: true }
334+
).exec();
335+
}
336+
302337
}
303338

0 commit comments

Comments
 (0)