diff --git a/src/controllers/notificationsController.ts b/src/controllers/notificationsController.ts new file mode 100644 index 00000000..baec83a1 --- /dev/null +++ b/src/controllers/notificationsController.ts @@ -0,0 +1,96 @@ +import { Request, Response } from 'express'; +import Notification from '../database/models/notification'; +import User from '../database/models/user'; +import { sendInternalErrorResponse, validateFields } from '../validations'; +import logger from '../logs/config'; +import EventEmitter from 'node:events'; +import Role from '../database/models/role'; + +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); + } +}); + +// const eventEmitter = new EventEmitter(); +// const getNotifications = async (req:Request, res:Response) => { +// const { userId } = req.params; +// const userNotifications = await User.findOne() + +// const notifications = await Notification.findAll() +// } +// const getAllnotifications = async (req: Request, res: Response) => { +// try { +// const notifications = await Notification.findAll(); +// if (!notifications) { +// res.status(404).json({ ok: false, message: 'Notifications could not be found' }); +// return; +// } +// res.status(200).json({ ok: true, data: notifications }); +// } catch (error) { +// res.status(404).json({ ok: false, message: 'Notifications could not be found' }); +// } +// }; +// const createNotifications = async (req: Request, res: Response) => { +// try { +// const { message, isRead } = req.body; +// const missingFields = validateFields(req, ['message', 'isRead']); +// if (missingFields.length !== 0) { +// logger.error(`Missing required fields: ${missingFields.join(', ')}`); +// res.status(400).json({ +// ok: false, +// message: `Missing required fields: ${missingFields.join(', ')}.`, +// }); +// return; +// } +// const notification = await Notification.create({ message, isRead }); + +// if (!notification) { +// throw new Error('Notification could not be created successfully'); +// } + +// res.status(201).json({ +// ok: true, +// data: notification, +// }); +// } catch (error) { +// logger.error('Notification could not be created', error); +// sendInternalErrorResponse(res, error); +// return; +// } +// }; + +// // const eventEmitter.emit + +// //CREATE AN EVENT EMMITER IN YOUR PRODUCT CONTROLLERS WHICH USES HOOKS [AFTERUPDATE, AFTERCREATE]. +// //THEN THE EVEN GET CAPTURED IN YOUR NOTIFICATION CONTROLLERS, +// //ONCE CAPTURED, THE CONTROLLER CREATEA NOTIFICATION AND SENDS IT VIA EMAIL, AND THEN RETURN A RESPONSE THAT INCLUDES THAT NOT. +// //THEN THERE WILL BE ONE GET ROUTE TO WORK ON FRONTEND +// //ALSO ANOTHER DELETE ROUTE TO DELETE THE NOTIFICATIONS FROM THE DATABASE + +// // Role.afterCreate(async product => { +// // const { id, name } = product; +// // //HERE, FIND THE PRODUCTS ID AND NAME TO ASSOCIATE WITH THE NOTIFICATION SENT +// // const notification = await Notification.create({ +// // message: `Product ${name} created successfully`, +// // isRead: false, +// // }); +// // }); +// // Role.afterUpdate(async product => { +// // const { id, name } = product; +// // const notification = await Notification.create({ +// // message: `Product ${name} was updated successfully!`, +// // isRead: false, +// // }); +// // }); + +// // Role.afterDestroy(async product => { +// // const { id, name } = product; +// // const notification = await Notification.create({ +// // message: `Product named ${name} was deleted successfully!`, +// // isRead: false, +// // }); +// // }); diff --git a/src/database/migrations/20240502174714-create-notification.js b/src/database/migrations/20240502174714-create-notification.js new file mode 100644 index 00000000..4412f310 --- /dev/null +++ b/src/database/migrations/20240502174714-create-notification.js @@ -0,0 +1,31 @@ +'use strict'; +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + await queryInterface.createTable('Notifications', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER, + }, + message: { + type: Sequelize.STRING, + }, + read: { + type: Sequelize.BOOLEAN, + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE, + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE, + }, + }); + }, + async down(queryInterface, Sequelize) { + await queryInterface.dropTable('Notifications'); + }, +}; diff --git a/src/database/models/notification.ts b/src/database/models/notification.ts new file mode 100644 index 00000000..9b5731ae --- /dev/null +++ b/src/database/models/notification.ts @@ -0,0 +1,45 @@ +import { Model, Optional, DataTypes, UUIDV4 } from 'sequelize'; +import sequelize from './index'; +import User from './user'; +export interface NotificationAttributes { + id: string; + message: string; + isRead: boolean; +} + +export interface NotificationCreationAttributes extends Optional {} + +class Notification extends Model { + public id!: string; + public message!: 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, + }, + }, + { + sequelize: sequelize, + timestamps: true, + } +); +User.hasMany(Notification); +Notification.belongsTo(User); + +export default Notification; diff --git a/src/helpers/send-email.ts b/src/helpers/send-email.ts index 9da0581c..d1543d1a 100644 --- a/src/helpers/send-email.ts +++ b/src/helpers/send-email.ts @@ -142,6 +142,25 @@ export const sendEmail = async (type: string, data: IData) => { mailOptions.subject = 'Reset password'; mailOptions.html = mailGenerator.generate(email); 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 your product', + link: 'https://e-commerce-mavericks.com/:id/products/:productID', + }, + }, + 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(info); diff --git a/src/helpers/sendNotifications.ts b/src/helpers/sendNotifications.ts new file mode 100644 index 00000000..89fa69e3 --- /dev/null +++ b/src/helpers/sendNotifications.ts @@ -0,0 +1,20 @@ +import { sendEmail } from './send-email'; +let product: any; +interface Product { + id: string; + name: string; +} +interface User { + name: string; + email: string; +} + +const sendNotifications = async (product: Product, user: User) => { + sendEmail('added_product_notification', user); + + return { + message: `Your product,${product.name} was added successfully`, + productId: product.id, + link: 'https://dummy productlink.com', + }; +};