Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fit bug fix notifications #88

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,9 +39,90 @@ 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 } });
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: { userId: userId },
attributes: ['id'],
});

if (notifications.length === 0) {
res.status(404).json({
ok: false,
message: 'No notifications found for this user',
});
return;
}
const deletedCount = await Notification.destroy({
where: { id: notifications.map(n => n.id) },
});

res.status(200).json({
ok: true,
message: `Successfully deleted ${deletedCount} notification(s)`,
});
} catch (error) {
logger.error('Error deleting notifications:', error);
sendInternalErrorResponse(res, error);
}
};
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('/delete/:userId', deleteAllNotifications);

export default route;
Loading