Skip to content

Commit

Permalink
Added more hooks to manage notifications for products lifecycle
Browse files Browse the repository at this point in the history
  • Loading branch information
Favor-star committed Jul 8, 2024
1 parent 44883ed commit cd96c1f
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 4 deletions.
85 changes: 84 additions & 1 deletion src/controllers/notificationsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Request, Response } from 'express';
import Notification from '../database/models/notification';
import { sendInternalErrorResponse } from '../validations';
import logger from '../logs/config';
import sequelize from '../database/models';
import { Transaction } from 'sequelize';

export const getNotifications = async (req: Request, res: Response): Promise<void> => {
try {
Expand Down Expand Up @@ -37,7 +39,88 @@ export const markNotificationAsRead = async (req: Request, res: Response): Promi
}
notification.isRead = isRead;
await notification.save();
res.status(200).json({ ok: true, message: 'Notification were updated successfully' });
res.status(200).json({ ok: true, message: 'Notification were updated successfully', data: notification });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const markAllNotificationsAsRead = async (req: Request, res: Response) => {
const { userId } = req.params;
const { isRead } = req.body;
try {
const allNotifications = await Notification.findAll({ where: { userId } });
console.log(allNotifications);
await Promise.all(
allNotifications.map(async notification => {
notification.isRead = isRead;
return notification.save();
})
);
res.status(200).json({ ok: true, message: 'all notifications marked successfully' });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
export const getSingleNotification = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
try {
const oneNotification = await Notification.findByPk(id);
if (!oneNotification) {
res.status(404).json({
ok: false,
message: "Notification can't be found",
});
return;
}
res.status(200).json({
ok: true,
message: 'Notifications was found successfully',
data: oneNotification,
});
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};

export const deleteSingleNotification = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
try {
await Notification.destroy({
where: {
id,
},
});
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};

export const deleteAllNotifications = async (req: Request, res: Response): Promise<void> => {
const { userId } = req.params;
try {
const notifications = await Notification.findAll({
where: {
id: userId,
},
});
if (notifications.length === 0) {
res.status(404).json({
ok: false,
message: "Notifications for this user can't be found",
});
return;
}
for (const notification of notifications) {
await notification.destroy();
}
res.status(200).json({
ok: true,
message: 'All notifications were successfully deleted',
});
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
Expand Down
28 changes: 27 additions & 1 deletion src/controllers/productsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,33 @@ Product.afterCreate(async product => {
}
sendEmail('added_product_notification', { email: user.email, name: user.firstName });
});

Product.afterUpdate(async product => {
const notification = await Notification.create({
message: `Product called: ${product.name} was updated successfully`,
isRead: false,
userId: product.sellerId,
});
const user = await User.findOne({
where: { id: product.sellerId },
attributes: ['email', 'firstName', 'lastName'],
});
if (!user) {
return Promise.reject(new Error("User cannot be found! So the email won't be send successfully"));
}
sendEmail('updated_product_notification', { email: user.email, name: user.firstName });
});
Product.afterDestroy(async product => {
const notification = await Notification.create({
message: 'Product was deleted successfully',
isRead: false,
userId: product.sellerId,
});
const user = await User.findOne({ where: { id: product.sellerId }, attributes: ['email', 'firstName', 'lastName'] });
if (!user) {
return Promise.reject(new Error("User can't be found, so the email won't be sent successfully"));
}
sendEmail('deleted_product_notification', { email: user.email, name: user.firstName });
});
// Review a product (feedback + rating)
export const provideReviewToProduct = async (req: Request, res: Response) => {
try {
Expand Down
127 changes: 127 additions & 0 deletions src/docs/notifications.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
tags:
- name: Notifications
description: Managing notifications for product's lifecycle changes

paths:
/api/notifications/{userId}:
get:
description: Get all notifications based on the the user's ID
summmary: Get all notifications
security:
- bearerAuth: []
tags:
- Notifications
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The id of the user
responses:
'200':
description: Notifications fetched successfully
content:
application/json:
schema:
type: object
properties:
id:
type: string
isRead:
type: boolean
message:
type: string
userId:
type: string
'404':
description: No notifications were found
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
delete:
description: User should be able to delete all notifications at once
summary: Delete all notifications at once
tags:
- Notifications
parameters:
- in: path
name: userId
required: true
schema:
type: string
description: The user ID
responses:
'200':
description: All notifications were successfully deleted
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
'404':
description: Notifications for this user wcan't be found
content:
application/json:
schema:
type: object
properties:
ok:
type: boolean
message:
type: string
patch:
description: User should be able to updates all notifications at once
summary: Updates all notifications at once
tags:
- Notifications
parameters:
- in: path
name: userId
required: true
description: Updates all notifications
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
isRead:
type: boolean
example: true
/api/notifications/{id}:
patch:
description: User should be able to update notification, provided the notification ID
summary: Update the notification status
tags:
- Notifications
parameters:
- in: path
name: id
required: true
schema:
type: string
description: The notification id
requestBody:
description: Update the notification
required: true
content:
application/json:
schema:
type: object
properties:
isRead:
type: boolean
40 changes: 39 additions & 1 deletion src/helpers/send-email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ export const sendEmail = async (type: string, data: IData) => {
button: {
color: '#22BC66',
text: 'View on the platform',
link: 'https://e-commerce-mavericks.com/login',
link: process.env.URL_HOST as string,
},
},
outro: 'Thank you for working with us. If you need any help, please free to contact us!',
Expand All @@ -241,6 +241,44 @@ export const sendEmail = async (type: string, data: IData) => {
mailOptions.subject = 'Product added successfully';
mailOptions.html = mailGenerator.generate(email);
break;
case 'updated_product_notification':
email = {
body: {
name: data.name,
intro: `Your product has been updated successfully!`,
action: {
instructions: 'To view your product on platform, Click here:',
button: {
color: '#22BC66',
text: 'View on the platform',
link: process.env.URL_HOST as string,
},
},
outro: 'Thank you for working with us. If you need any help, please free to contact us!',
},
};
mailOptions.subject = 'Product updated successfully';
mailOptions.html = mailGenerator.generate(email);
break;
case 'deleted_product_notification':
email = {
body: {
name: data.name,
intro: `Your product has been deleted successfully!`,
action: {
instructions: 'To view your other products on platform, Click here:',
button: {
color: '#22BC66',
text: 'View on the platform',
link: process.env.URL_HOST as string,
},
},
outro: 'Thank you for working with us. If you need any help, please free to contact us!',
},
};
mailOptions.subject = 'Product deleted successfully';
mailOptions.html = mailGenerator.generate(email);
break;

case 'password_prompt':
email = {
Expand Down
13 changes: 12 additions & 1 deletion src/routes/notificationRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import express from 'express';
import { getNotifications, markNotificationAsRead } from '../controllers/notificationsController';
import {
deleteAllNotifications,
deleteSingleNotification,
getNotifications,
getSingleNotification,
markAllNotificationsAsRead,
markNotificationAsRead,
} from '../controllers/notificationsController';

const route = express.Router();

route.get('/:userId', getNotifications);
route.patch('/:id', markNotificationAsRead);
route.patch('/update/:userId', markAllNotificationsAsRead);
route.get('/:id', getSingleNotification);
route.delete('/:id', deleteSingleNotification);
route.delete('/:userId', deleteAllNotifications);

export default route;

0 comments on commit cd96c1f

Please sign in to comment.