Skip to content

Commit

Permalink
Creating notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
Favor-star committed May 7, 2024
1 parent 608d497 commit bc8de9f
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 3 deletions.
55 changes: 55 additions & 0 deletions src/controllers/notificationsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Request, Response } from 'express';
import Notification from '../database/models/notification';
import { sendInternalErrorResponse } from '../validations';
import logger from '../logs/config';
import Role from '../database/models/role';
import { NotificationAttributes, NotificationCreationAttributes } from '../database/models/notification';
Role.afterCreate((role, options) => {
try {
console.log('Role was created successfully', role);
// Any additional logic you want to execute after a Role is created
} catch (error) {
console.error('Error occurred after creating Role:', error);
}
});

export const getNotifications = async (req: Request, res: Response): Promise<void> => {
try {
const { userId } = req.params;
const notifications = await Notification.findAll({ where: { userId } });
if (notifications.length === 0) {
logger.error('No notifications were found');
res.status(404).json({
ok: false,
message: 'No notifications that were found',
});
return;
}
res.status(200).json({ ok: true, data: notifications });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
return;
}
};

export const markNotificationAsRead = async (req: Request, res: Response): Promise<void> => {
const { id } = req.params;
const { isRead } = req.body;
try {
const notification = await Notification.findByPk(id);
if (!notification) {
res.status(401).json({
ok: false,
errorMessage: 'No such notification that were found! Try again',
});
return;
}
notification.isRead = isRead;
await notification.save();
res.status(200).json({ ok: true, message: 'Notification were updated successfully' });
} catch (error) {
logger.error(error);
sendInternalErrorResponse(res, error);
}
};
23 changes: 21 additions & 2 deletions src/controllers/productsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import uploadImage from '../helpers/claudinary';
import { sendInternalErrorResponse } from '../validations';
import { Product, ProductAttributes } from '../database/models/Product';
import { Size, SizeAttributes } from '../database/models/Size';
import Notification from '../database/models/notification';
import User from '../database/models/user';
import { sendEmail } from '../helpers/send-email';

export const createProduct = async (req: Request, res: Response) => {
try {
Expand All @@ -23,8 +26,8 @@ export const createProduct = async (req: Request, res: Response) => {
});
}
// handle images
const productImages = ['asdf', 'asdf', 'asdf', 'asdf'];
const images: unknown = req.files;
const productImages = [];
const images = req.files;
if (images instanceof Array && images.length > 3) {
for (const image of images) {
const imageBuffer: Buffer = image.buffer;
Expand Down Expand Up @@ -69,3 +72,19 @@ export const createSize = async (req: Request, res: Response) => {
sendInternalErrorResponse(res, error);
}
};
//HOOKS TO MANAGE NOTIFICATIONS AFTER OPERATIONS ARE MADE ON PRODUCT

Product.afterCreate(async product => {
const notification = await Notification.create({
message: `Product called: ${product.name} was created successfully!`,
isRead: false,
userId: product.sellerId,
});
console.log(notification);
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"));
}
console.log('The product was successfully created', { email: user.email, name: user.firstName });
sendEmail('added_product_notification', { email: user.email, name: user.firstName });
});
46 changes: 46 additions & 0 deletions src/database/migrations/20240507222727-create-notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';

const { UUIDV4 } = require('sequelize');

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('Notifications', {
id: {
allowNull: false,
primaryKey: true,
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
},
message: {
type: Sequelize.STRING,
allowNull: false,
},
isRead: {
type: Sequelize.BOOLEAN,
allowNull: false,
},
userId: {
type: Sequelize.UUID,
allowNull: false,
references: {
model: 'Users',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable('Notifications');
},
};
55 changes: 55 additions & 0 deletions src/database/models/notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Model, Optional, DataTypes, UUIDV4 } from 'sequelize';
import sequelize from './index';

export interface NotificationAttributes {
id: string;
userId: string;
message: string;
isRead: boolean;
}

export interface NotificationCreationAttributes extends Optional<NotificationAttributes, 'id'> {}

class Notification extends Model<NotificationAttributes, NotificationCreationAttributes> {
public id!: string;
public message!: string;
public userId!: string;
public isRead!: boolean;
public readonly createdAt: Date | undefined;
public readonly updatedAt: Date | undefined;
}
Notification.init(
{
id: {
type: DataTypes.UUID,
defaultValue: UUIDV4,
primaryKey: true,
allowNull: false,
unique: true,
},
message: {
type: DataTypes.STRING,
allowNull: false,
},
isRead: {
type: DataTypes.BOOLEAN,
allowNull: false,
},
userId: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'Users',
key: 'id',
},
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
},
},
{
sequelize: sequelize,
timestamps: true,
}
);

export default Notification;
19 changes: 19 additions & 0 deletions src/helpers/send-email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,25 @@ export const sendEmail = async (type: string, data: IData) => {
mailOptions.subject = 'Verification code';
mailOptions.html = emailContent;
break;
case 'added_product_notification':
email = {
body: {
name: data.name,
intro: `Your product has been added successfully!`,
action: {
instructions: 'To view your product on platform, Click here:',
button: {
color: '#22BC66',
text: 'View on the platform',
link: 'https://e-commerce-mavericks.com/login',
},
},
outro: 'Thank you for working with us. If you need any help, please free to contact us!',
},
};
mailOptions.subject = 'Product added successfully';
mailOptions.html = mailGenerator.generate(email);
break;
}
const info = await transporter.sendMail(mailOptions);
logger.info('Send Mailer', info);
Expand Down
3 changes: 2 additions & 1 deletion src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import authRoute from './authRoute';
import roleRoute from './roleRoute';
import { productRouter } from './productRoutes';
import { categoryRouter } from './categoryRouter';

import notificationRoutes from './notificationRoutes';
const router = Router();

router.use('/users', userRoute);
router.use('/auth', authRoute);
router.use('/roles', roleRoute);
router.use('/products', productRouter);
router.use('/category', categoryRouter);
router.use('/notifications', notificationRoutes);
export default router;
9 changes: 9 additions & 0 deletions src/routes/notificationRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from 'express';
import { getNotifications, markNotificationAsRead } from '../controllers/notificationsController';

const route = express.Router();

route.get('/:userId', getNotifications);
route.patch('/:id', markNotificationAsRead);

export default route;

0 comments on commit bc8de9f

Please sign in to comment.