Skip to content

Commit 7a575de

Browse files
committed
🐛 notifications and some error messages
1 parent 50f351d commit 7a575de

File tree

6 files changed

+216
-114
lines changed

6 files changed

+216
-114
lines changed

graphql/notification.graphql

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@ enum NotificationType {
22
FOLLOWING
33
}
44

5+
type UserAvatar {
6+
id: ID!
7+
name: String!
8+
profilePicture: String
9+
}
10+
511
type Notification {
612
id: ID!
713
description: String!
814
createdAt: DateTime!
915
seenAt: DateTime
1016
seenStatus: Boolean!
11-
user: User
17+
User: UserAvatar
1218
userId: ID
1319
notificationType: NotificationType!
20+
otherUserId: ID
21+
OtherUser: UserAvatar
1422
}
1523

1624
input SeeNotificationInput {

prisma/schema.prisma

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ model User {
2626
followedBy User[] @relation("FollowingUser", fields: [followedByIds], references: [id])
2727
followedByIds String[] @db.ObjectId
2828
notifications Notification[]
29+
othersNotifications Notification[] @relation("NotificationOtherUser")
2930
}
3031

3132
model Token {
@@ -55,4 +56,6 @@ model Notification {
5556
User User? @relation(fields: [userId], references: [id])
5657
userId String? @db.ObjectId
5758
notificationType NotificationType
59+
otherUserId String? @db.ObjectId
60+
OtherUser User? @relation("NotificationOtherUser", fields: [otherUserId], references: [id])
5861
}

src/graphql.types.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -293,15 +293,23 @@ export class GithubGraphsOutput {
293293
statsGraph: GithubStatistics;
294294
}
295295

296+
export class UserAvatar {
297+
id: string;
298+
name: string;
299+
profilePicture?: Nullable<string>;
300+
}
301+
296302
export class Notification {
297303
id: string;
298304
description: string;
299305
createdAt: DateTime;
300306
seenAt?: Nullable<DateTime>;
301307
seenStatus: boolean;
302-
user?: Nullable<User>;
308+
User?: Nullable<UserAvatar>;
303309
userId?: Nullable<string>;
304310
notificationType: NotificationType;
311+
otherUserId?: Nullable<string>;
312+
OtherUser?: Nullable<UserAvatar>;
305313
}
306314

307315
export class NotificationOutput {
+5-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Mutation, Resolver, Context, Args, Query } from '@nestjs/graphql';
2+
import { getToken } from 'src/constants/decode';
23
import { SeeNotificationInput, SeeNotificationsInput } from 'src/graphql.types';
34
import { NotificationService } from './notification.service';
45

@@ -11,10 +12,7 @@ export class NotificationResolver {
1112
@Args('input') input: SeeNotificationInput,
1213
@Context() context,
1314
) {
14-
const token = context?.req?.headers?.authorization.split(' ')[1];
15-
if (!token) {
16-
throw new Error('Invalid request, token not found');
17-
}
15+
const token = getToken(context);
1816
await this.notificationService.seeNotification(input.notificationId, token);
1917
return 'Notification seen';
2018
}
@@ -24,10 +22,7 @@ export class NotificationResolver {
2422
@Args('input') input: SeeNotificationsInput,
2523
@Context() context,
2624
) {
27-
const token = context?.req?.headers?.authorization.split(' ')[1];
28-
if (!token) {
29-
throw new Error('Invalid request, token not found');
30-
}
25+
const token = getToken(context);
3126
await this.notificationService.seeNotifications(
3227
input.notificationIds,
3328
token,
@@ -37,11 +32,9 @@ export class NotificationResolver {
3732

3833
@Query('notifications')
3934
async notifications(@Context() context) {
40-
const token = context?.req?.headers?.authorization.split(' ')[1];
41-
if (!token) {
42-
throw new Error('Invalid request, token not found');
43-
}
35+
const token = getToken(context);
4436
const notifications = await this.notificationService.notifications(token);
37+
console.log(notifications);
4538
return notifications;
4639
}
4740
}
+139-67
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,172 @@
11
import { Injectable } from '@nestjs/common';
2+
import { NotificationType } from 'src/graphql.types';
23
import { PrismaService } from 'prisma/prisma.service';
34
import { decode } from 'src/constants/decode';
5+
import { NotificationOutput } from 'src/graphql.types';
6+
import { HttpException, HttpStatus } from '@nestjs/common';
47

58
@Injectable()
69
export class NotificationService {
710
constructor(private prisma: PrismaService) {}
811

912
async sendNotification(
10-
userId: string,
13+
toUser: string,
1114
description: string,
12-
type: 'FOLLOWING',
13-
) {
14-
await this.prisma.user.update({
15-
where: { id: userId },
16-
data: {
17-
notifications: {
18-
create: {
19-
description,
20-
notificationType: type,
15+
type: NotificationType,
16+
fromUser?: string,
17+
): Promise<void> {
18+
try {
19+
await this.prisma.notification.deleteMany({
20+
where: {
21+
userId: toUser,
22+
notificationType: type,
23+
otherUserId: fromUser,
24+
},
25+
});
26+
} catch {
27+
throw new HttpException(
28+
'Error occurred while deleting previous notifications',
29+
HttpStatus.INTERNAL_SERVER_ERROR,
30+
);
31+
}
32+
try {
33+
await this.prisma.notification.create({
34+
data: {
35+
description,
36+
notificationType: type,
37+
User: {
38+
connect: {
39+
id: toUser,
40+
},
41+
},
42+
OtherUser: {
43+
connect: {
44+
id: fromUser,
45+
},
2146
},
2247
},
23-
},
24-
});
48+
});
49+
} catch {
50+
throw new HttpException(
51+
'Error occurred while sending notification',
52+
HttpStatus.INTERNAL_SERVER_ERROR,
53+
);
54+
}
2555
}
2656

2757
async seeNotification(notificationId: string, token: string) {
2858
await decode(token, this.prisma);
29-
const notification = await this.prisma.notification.update({
30-
where: {
31-
id: notificationId,
32-
},
33-
data: {
34-
seenStatus: true,
35-
seenAt: new Date(),
36-
},
37-
});
38-
return notification;
59+
try {
60+
const notification = await this.prisma.notification.update({
61+
where: {
62+
id: notificationId,
63+
},
64+
data: {
65+
seenStatus: true,
66+
seenAt: new Date(),
67+
},
68+
});
69+
return notification;
70+
} catch {
71+
throw new HttpException(
72+
'Error occurred while marking notification as seen',
73+
HttpStatus.INTERNAL_SERVER_ERROR,
74+
);
75+
}
3976
}
4077

4178
async seeNotifications(notificationIds: string[], token: string) {
4279
await decode(token, this.prisma);
43-
const notifications = await this.prisma.notification.updateMany({
44-
where: {
45-
id: {
46-
in: notificationIds,
80+
try {
81+
const notifications = await this.prisma.notification.updateMany({
82+
where: {
83+
id: {
84+
in: notificationIds,
85+
},
86+
},
87+
data: {
88+
seenStatus: true,
89+
seenAt: new Date(),
4790
},
48-
},
49-
data: {
50-
seenStatus: true,
51-
seenAt: new Date(),
52-
},
53-
});
54-
return notifications;
91+
});
92+
return notifications;
93+
} catch {
94+
throw new HttpException(
95+
'Error occurred while marking notifications as seen',
96+
HttpStatus.INTERNAL_SERVER_ERROR,
97+
);
98+
}
5599
}
56100

57-
async notifications(token: string) {
101+
async notifications(token: string): Promise<NotificationOutput> {
58102
const user = await decode(token, this.prisma);
59-
const notifs = await this.prisma.user.findUnique({
60-
where: {
61-
id: user.id,
62-
},
63-
select: {
64-
notifications: {
65-
orderBy: {
66-
createdAt: 'desc',
67-
},
103+
this.deleteSeenPreviousNotifications();
104+
try {
105+
const notifs = await this.prisma.user.findUnique({
106+
where: {
107+
id: user.id,
68108
},
69-
},
70-
});
71-
const unseenNotifs = await this.prisma.user.count({
72-
where: {
73-
id: user.id,
74-
notifications: {
75-
some: {
76-
seenStatus: false,
109+
select: {
110+
notifications: {
111+
orderBy: {
112+
createdAt: 'desc',
113+
},
114+
select: {
115+
id: true,
116+
description: true,
117+
notificationType: true,
118+
seenStatus: true,
119+
createdAt: true,
120+
OtherUser: {
121+
select: {
122+
id: true,
123+
name: true,
124+
profilePicture: true,
125+
},
126+
},
127+
User: {
128+
select: {
129+
id: true,
130+
name: true,
131+
profilePicture: true,
132+
},
133+
},
134+
},
77135
},
78136
},
79-
},
80-
});
81-
return {
82-
notifications: notifs?.notifications,
83-
unseenNotifications: unseenNotifs,
84-
};
137+
});
138+
let unseenNotifications = 0;
139+
for (const notif of notifs?.notifications) {
140+
if (notif.seenStatus === false) unseenNotifications++;
141+
}
142+
return {
143+
unseenNotifications: unseenNotifications,
144+
notifications:
145+
notifs?.notifications as NotificationOutput['notifications'],
146+
};
147+
} catch {
148+
throw new HttpException(
149+
'Error occurred while fetching notifications',
150+
HttpStatus.INTERNAL_SERVER_ERROR,
151+
);
152+
}
85153
}
86154

87-
/**
88-
* Delete all notifications that were seen 48 hours ago
89-
*/
90155
async deleteSeenPreviousNotifications() {
91-
await this.prisma.notification.deleteMany({
92-
where: {
93-
seenStatus: true,
94-
seenAt: {
95-
lt: new Date(new Date().getTime() - 48 * 60 * 60 * 1000),
156+
try {
157+
await this.prisma.notification.deleteMany({
158+
where: {
159+
seenStatus: true,
160+
seenAt: {
161+
lt: new Date(new Date().getTime() - 24 * 60 * 60 * 1000),
162+
},
96163
},
97-
},
98-
});
164+
});
165+
} catch (err) {
166+
throw new HttpException(
167+
'Error occurred while deleting previous notifications',
168+
HttpStatus.INTERNAL_SERVER_ERROR,
169+
);
170+
}
99171
}
100172
}

0 commit comments

Comments
 (0)