diff --git a/controllers/bookings.js b/controllers/bookings.js index 11f7155..73f238d 100644 --- a/controllers/bookings.js +++ b/controllers/bookings.js @@ -1,6 +1,11 @@ -const Booking = require("../models/Booking"); -const validateBookingInput = require("../validation/booking"); -const { bookingConfirmationEmail } = require("../utils/notification"); +const Booking = require('../models/Booking'); +const validateBookingInput = require('../validation/booking'); +const { + bookingConfirmationEmail, + adminSendEmailToClassVolunteers, +} = require('../utils/notification'); +const Class = require('../models/Class'); +const dayjs = require('dayjs'); exports.getBookings = async (req, res) => { try { const bookings = await Booking.find(); @@ -12,7 +17,7 @@ exports.getBookings = async (req, res) => { } catch (err) { return res.status(500).json({ success: false, - error: "Server Error", + error: 'Server Error', }); } }; @@ -24,7 +29,7 @@ exports.getClassBookings = async (req, res) => { if (!booking) { return res.status(404).json({ success: false, - error: "No booking found", + error: 'No booking found', }); } return res.status(200).json({ @@ -35,7 +40,7 @@ exports.getClassBookings = async (req, res) => { } catch (err) { return res.status(400).json({ success: false, - error: "Could not get class bookings", + error: 'Could not get class bookings', }); } }; @@ -55,12 +60,12 @@ exports.createBooking = async (req, res) => { return res.status(400).json({ success: false, message: - "Email already exists, You have already booked for this class, thanks!", + 'Email already exists, You have already booked for this class, thanks!', }); } else if (err) { return res.status(500).json({ success: false, - error: "Server Error", + error: 'Server Error', }); } else { const allBooking = await Booking.find({ classId: req.body.classId }); @@ -73,6 +78,10 @@ exports.createBooking = async (req, res) => { } const newBooking = await Booking.create(req.body); + const classInfo = await Class.findById(req.body.classId); + newBooking.classDate = dayjs(classInfo.date).format('DD/MM/YYYY'); + newBooking.classStartTime = classInfo.startTime; + newBooking.classEndTime = classInfo.endTime; await bookingConfirmationEmail(newBooking); return res.status(201).json({ success: true, @@ -84,7 +93,7 @@ exports.createBooking = async (req, res) => { } catch (err) { return res.status(500).json({ success: false, - error: "Server Error", + error: 'Server Error', }); } }; @@ -98,7 +107,7 @@ exports.deleteBooking = async (req, res) => { if (!booking) { return res.status(404).json({ success: false, - error: "No booking found", + error: 'No booking found', }); } @@ -111,7 +120,7 @@ exports.deleteBooking = async (req, res) => { } catch (err) { return res.status(500).json({ success: false, - error: "Server Error, could not delete booking", + error: 'Server Error, could not delete booking', }); } }; @@ -129,7 +138,7 @@ exports.updateBooking = async (req, res) => { if (!booking) { return res.status(400).json({ success: false, - error: "booking not found!", + error: 'booking not found!', }); } return res.status(200).json({ @@ -139,7 +148,38 @@ exports.updateBooking = async (req, res) => { } catch (err) { return res.status(400).json({ success: false, - error: "Could not update booking", + error: 'Could not update booking', }); } }; + +exports.sendEmailToAllVolunteers = async (req, res) => { + try { + const emailData = req.body; + if (emailData.subject === '' || emailData.emailText === '') { + return res.status(400).json("'Subject or email can not be empty.'"); + } + const classId = emailData.classId; + const classBookings = await Booking.find({ classId }); + if (classBookings && !classBookings.length > 0) { + return res.status(400).json({ + success: false, + message: + 'Sorry, there are no volunteers signed up for this class, thanks!', + }); + } + const emails = []; + classBookings.forEach((booking) => emails.push(booking.email)); + emailData.emails = emails; + await adminSendEmailToClassVolunteers(emailData); + return res.status(200).json({ + success: true, + message: 'An email notification is sent to all volunteers, thanks!', + }); + } catch (err) { + return res.status(400).json({ + success: false, + error: 'Could not Send Emails', + }); + } +}; \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 202c8df..a473a01 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1761,6 +1761,14 @@ "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==" }, + "@types/quill": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz", + "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==", + "requires": { + "parchment": "^1.1.2" + } + }, "@types/react": { "version": "16.9.44", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.44.tgz", @@ -3680,6 +3688,11 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "clone-deep": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", @@ -4032,6 +4045,15 @@ "sha.js": "^2.4.8" } }, + "create-react-class": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz", + "integrity": "sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==", + "requires": { + "loose-envify": "^1.3.1", + "object-assign": "^4.1.1" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -5807,6 +5829,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==" + }, "fast-glob": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", @@ -9547,6 +9574,11 @@ "tslib": "^1.10.0" } }, + "parchment": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", + "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==" + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -10892,6 +10924,36 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "quill": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", + "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", + "requires": { + "clone": "^2.1.1", + "deep-equal": "^1.0.1", + "eventemitter3": "^2.0.3", + "extend": "^3.0.2", + "parchment": "^1.1.4", + "quill-delta": "^3.6.2" + }, + "dependencies": { + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" + } + } + }, + "quill-delta": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", + "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", + "requires": { + "deep-equal": "^1.0.1", + "extend": "^3.0.2", + "fast-diff": "1.1.2" + } + }, "raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -11175,6 +11237,11 @@ "scheduler": "^0.19.1" } }, + "react-dom-factories": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz", + "integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA=" + }, "react-error-overlay": { "version": "6.0.8", "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", @@ -11190,6 +11257,19 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-quill": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-1.3.5.tgz", + "integrity": "sha512-/W/rNCW+6QpGz8yQ9tFK5Ka/h/No1RqrcOOvCIOR092OiKzRFlU2xbPEwiP3Wgy/Dx13pi1YhjReDMX/5uotJg==", + "requires": { + "@types/quill": "1.3.10", + "create-react-class": "^15.6.0", + "lodash": "^4.17.4", + "prop-types": "^15.5.10", + "quill": "^1.3.7", + "react-dom-factories": "^1.0.0" + } + }, "react-redux": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 34e5f83..36fd74f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "react": "^16.14.0", "react-dom": "^16.14.0", "react-hook-form": "^6.10.1", + "react-quill": "^1.3.5", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "^3.4.4", diff --git a/frontend/src/components/ClassCard/ClassCard.jsx b/frontend/src/components/ClassCard/ClassCard.jsx index ee85860..12cb60c 100644 --- a/frontend/src/components/ClassCard/ClassCard.jsx +++ b/frontend/src/components/ClassCard/ClassCard.jsx @@ -3,6 +3,7 @@ import { MonthNames } from "../../utils/MonthNames"; import { Link } from "react-router-dom"; import NewBookingForm from "../NewBookingForm/NewBookingForm.jsx"; import ClassVolunteersList from "../ClassVolunteersList/ClassVolunteersList.jsx"; +import EmailToAll from "./EmailToAll.jsx"; import axios from "axios"; import Alert from "../Alert/Alarm.jsx"; import Loading from "../Loading/Loading.jsx"; @@ -17,11 +18,16 @@ const ClassCard = ({ user, city, component, id, Class, WeekNumber }) => { const [alertStatus, setAlertStatus] = useState(false); const [alertType, setAlertType] = useState(""); const [alertMessage, setAlertMessage] = useState("message"); + const [sendEmail, setSendEmail] = useState(false); const closeConfirmationAlert = () => { setCancelStatus(false); }; + const emailClose = () => { + setSendEmail(false); + }; + const showAlert = (type, message) => { setAlertStatus(true); setAlertType(type); @@ -180,6 +186,19 @@ const ClassCard = ({ user, city, component, id, Class, WeekNumber }) => {
{user === users[0].id && ( + {component === "attendingvolunteers" && ( + + )}
)} + {sendEmail && ( + + )} {!["upcomingclass", "coursecalendar", "overview"].includes( component ) &&
} @@ -263,4 +285,4 @@ const ClassCard = ({ user, city, component, id, Class, WeekNumber }) => { ); }; -export default ClassCard; +export default ClassCard; \ No newline at end of file diff --git a/frontend/src/components/ClassCard/ClassCard.scss b/frontend/src/components/ClassCard/ClassCard.scss index f492bb5..c0bb384 100644 --- a/frontend/src/components/ClassCard/ClassCard.scss +++ b/frontend/src/components/ClassCard/ClassCard.scss @@ -3,6 +3,7 @@ .classcard-body { animation: FadeIn 500ms; + transition: 200ms; } .classcard-main { margin: 0 auto 30px auto; @@ -106,7 +107,7 @@ font-size: 15px; } -.URLs-container{ +.URLs-container { display: flex; flex-wrap: nowrap; } @@ -213,6 +214,16 @@ cursor: default; } } +.classcard-email-bottom { + @extend %btn-outline-success; + border-radius: 5px; + width: 60px; + height: 50px; + cursor: pointer; + margin-right: 10px; + font-size: 1rem; + outline: none; +} .classcard-cancel-bottom { @extend %btn-outline-danger; border-radius: 5px; @@ -313,7 +324,8 @@ } @media (min-width: 360px) { - .classcard-cancel-bottom { + .classcard-cancel-bottom, + .classcard-email-bottom { width: 90px; } .classcard-attend-bottom, @@ -338,7 +350,8 @@ .classcard-cancel-bottom, .classcard-edit-bottom, - .classcard-attend-bottom { + .classcard-attend-bottom, + .classcard-email-bottom { width: 150px; } } @@ -408,13 +421,15 @@ } .classcard-edit-bottom, .classcard-attend-bottom, + .classcard-email-bottom, .class-card-disable-attend-bottom { width: 80px; height: 50px; font-size: 1rem; } - .classcard-cancel-bottom { + .classcard-cancel-bottom, + .classcard-email-bottom { width: 80px; height: 50px; font-size: 1rem; @@ -509,7 +524,8 @@ font-size: 1rem; } - .classcard-cancel-bottom { + .classcard-cancel-bottom, + .classcard-email-bottom { width: 120px; height: 50px; font-size: 1rem; @@ -543,4 +559,4 @@ cursor: default; color: #aeaeae; } -} +} \ No newline at end of file diff --git a/frontend/src/components/ClassCard/EmailToAll.jsx b/frontend/src/components/ClassCard/EmailToAll.jsx new file mode 100644 index 0000000..c687497 --- /dev/null +++ b/frontend/src/components/ClassCard/EmailToAll.jsx @@ -0,0 +1,56 @@ +import React, { useRef } from "react"; +import ReactQuill from "react-quill"; +import axios from "axios"; +import "react-quill/dist/quill.snow.css"; +import "./EmailToAll.scss"; + +const EmailToAll = ({ Class, emailClose }) => { + const emailText = useRef([]); + const sendEmail = async (e) => { + e.preventDefault(); + if ( + emailText.current[0].value === undefined || + emailText.current[1].state.value === undefined || + emailText.current[0].value === "" || + emailText.current[1].state.value === "


" + ) { + alert("Please add your text to email!"); + } else { + + await axios.post("/api/v1/bookings/email/send", { + classId: Class._id, + subject: emailText.current[0].value, + emailText: emailText.current[1].state.value, + }); + emailClose(false); + } + }; + return ( +
+
+
+

Send Email to all volunteers

+ (emailText.current[0] = el)} + required + > + (emailText.current[1] = el)} + required + /> +
+ + +
+ ); +}; + +export default EmailToAll; \ No newline at end of file diff --git a/frontend/src/components/ClassCard/EmailToAll.scss b/frontend/src/components/ClassCard/EmailToAll.scss new file mode 100644 index 0000000..d456b0e --- /dev/null +++ b/frontend/src/components/ClassCard/EmailToAll.scss @@ -0,0 +1,78 @@ +@import "../../scss/mixins"; +@import "../../scss/buttons"; + +.email-body { + width: 60%; + height: 500px; + background-color: white; + border-radius: 10px; + margin: 50px 20% 0px 20%; + animation: FadeIn 500ms; +} +.close-bt { + width: 100%; + display: flex; + justify-content: flex-end; + align-items: center; + i { + margin: 15px 15px 0px 0px; + font-size: 25px; + color: rgb(61, 61, 61); + transition: 200ms; + } + i:hover { + color: #dc3545; + transition: 200ms; + cursor: pointer; + } +} +.subject-email { + margin: 15px; + overflow-y: scroll; + width: calc(100% - 30px); + p { + margin-bottom: 10px; + font-family: "Open Sans", sans-serif; + } +} +.subject { + text-indent: 17px; + width: 100%; + height: 50px; + border: none; + border-top: 1px solid #cccccc; + border-right: 1px solid #cccccc; + border-bottom: 0px; + border-left: 1px solid #cccccc; + outline: none; +} +.app .ql-editor { + height: 220px; +} +.ql-editor { + overflow-y: auto; +} + +.send{ + @extend %btn-send ; + border-radius: 5px; + width: 120px; + height: 40px; + font-family: "Open Sans", sans-serif; + margin-left: 15px; + cursor: pointer; + font-size: 1rem; + outline: none; + } + +.cancel{ + @extend %btn-cancel ; + border-radius: 5px; + width: 120px; + height: 40px; + font-family: "Open Sans", sans-serif; + margin-left: 15px; + cursor: pointer; + font-size: 1rem; + outline: none; + } \ No newline at end of file diff --git a/frontend/src/scss/_buttons.scss b/frontend/src/scss/_buttons.scss index 14e2097..0e95dea 100644 --- a/frontend/src/scss/_buttons.scss +++ b/frontend/src/scss/_buttons.scss @@ -93,6 +93,26 @@ } } +%btn-send { + background-color: $btn-success-bg-hover; + border: 1px solid $btn-success-border; + color: white; + transition: 200ms; + &:hover { + background-color: rgb(0, 155, 0); + } +} + +%btn-cancel { + background-color: white; + color: $btn-danger-border; + border: 1px solid $btn-danger-border; + transition: 200ms; + &:hover { + background-color: $btn-danger-bg-hover; + color: white; + } + %btn-no-bg { background-color: transparent; } diff --git a/routes/bookings.js b/routes/bookings.js index a96fd64..f547f63 100644 --- a/routes/bookings.js +++ b/routes/bookings.js @@ -1,4 +1,4 @@ -const express = require("express"); +const express = require('express'); const router = express.Router(); const { getBookings, @@ -6,14 +6,16 @@ const { createBooking, deleteBooking, updateBooking, -} = require("../controllers/bookings"); + sendEmailToAllVolunteers, +} = require('../controllers/bookings'); -router.route("/").get(getBookings).post(createBooking); +router.route('/').get(getBookings).post(createBooking); +router.route('/email/send').post(sendEmailToAllVolunteers); router - .route("/:id") + .route('/:id') .delete(deleteBooking) .put(updateBooking) .get(getClassBookings); -module.exports = router; +module.exports = router; \ No newline at end of file diff --git a/utils/emailTemplate/Class.planner.admin.notification.email.js b/utils/emailTemplate/Class.planner.admin.notification.email.js new file mode 100644 index 0000000..33ae673 --- /dev/null +++ b/utils/emailTemplate/Class.planner.admin.notification.email.js @@ -0,0 +1,152 @@ +exports.adminEmailNotification = (data) => { + return ` + + + + + + Admin Email Notification + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ cyf-email-05 + +
+
+
+
+
+ +

+ ${data} +

+ +

+ Please feel free to contact the coordinator,if there is + anything you wish to discuss before turning up for a class. +

+

+ Thank you and have a great time during the class. +

+
+

+ Best Regards, +

+

+ The CodeYourFuture Team +

+


+
+ http://codeyourfuture.io - Follow us + on + Facebook and + Twitter
+ Read more about our project on + FT, + + Wired, + + BBC Tech Tent, + UNHCR, + and + + NewsDeeply +

+
+
+
+
+
+
+ cyf_brand + +
+
+ + + + `; + }; \ No newline at end of file diff --git a/utils/emailTemplate/Class.planner.volunteer.confirmation.attending.email.js b/utils/emailTemplate/Class.planner.volunteer.confirmation.attending.email.js index 0295b3c..1ca00e5 100644 --- a/utils/emailTemplate/Class.planner.volunteer.confirmation.attending.email.js +++ b/utils/emailTemplate/Class.planner.volunteer.confirmation.attending.email.js @@ -57,7 +57,12 @@ exports.volunteerConfirmationEmail = (data) => { Dear ${data.fullName},

- This is a notification that you have signed up for a class as a ${data.roleName}. + This is a notification that you have signed up for a class as a ${data.roleName} on ${data.classDate} between ${data.classStartTime} and ${data.classEndTime} , + add to calendar + + add to calendar +

{ `; -}; +}; \ No newline at end of file diff --git a/utils/mailer.js b/utils/mailer.js index 4a4e32f..36c2ab1 100644 --- a/utils/mailer.js +++ b/utils/mailer.js @@ -1,41 +1,73 @@ -const { SESConfig } = require("./email-config"); -const { ses } = require("./email-config"); +const { SESConfig } = require('./email-config'); +const { ses } = require('./email-config'); exports.mailer = async (emailData) => { const to = - SESConfig.env === "development" + SESConfig.env === 'development' ? SESConfig.catchOnAllEmail : emailData.toEmail; const replyTo = - SESConfig.env === "development" + SESConfig.env === 'development' ? SESConfig.catchOnAllEmail : emailData.replyToEmail; try { - var params = { - Destination: { - ToAddresses: [to], - }, - Message: { - Body: { - Html: { - Charset: "UTF-8", - Data: emailData.html, + if (Array.isArray(to)) { + const groupedEmails = to; + return Promise.all( + groupedEmails.map(async (groupEmail) => { + let params = { + Destination: { + BccAddresses: [groupEmail], + }, + Message: { + Body: { + Html: { + Charset: 'UTF-8', + Data: emailData.html, + }, + Text: { + Charset: 'UTF-8', + Data: 'TEXT_FORMAT_BODY', + }, + }, + Subject: { + Charset: 'UTF-8', + Data: emailData.subject, + }, + }, + Source: SESConfig.sourceEmail, + ReplyToAddresses: [replyTo], + }; + return ses.sendEmail(params).promise(); + }) + ); + } else { + let params = { + Destination: { + ToAddresses: [to], + }, + Message: { + Body: { + Html: { + Charset: 'UTF-8', + Data: emailData.html, + }, + Text: { + Charset: 'UTF-8', + Data: 'TEXT_FORMAT_BODY', + }, }, - Text: { - Charset: "UTF-8", - Data: "TEXT_FORMAT_BODY", + Subject: { + Charset: 'UTF-8', + Data: emailData.subject, }, }, - Subject: { - Charset: "UTF-8", - Data: emailData.subject, - }, - }, - Source: SESConfig.sourceEmail, - ReplyToAddresses: [replyTo], - }; - return ses.sendEmail(params).promise(); + Source: SESConfig.sourceEmail, + ReplyToAddresses: [replyTo], + }; + return ses.sendEmail(params).promise(); + } } catch (err) { console.log(err); } -}; +}; \ No newline at end of file diff --git a/utils/notification.js b/utils/notification.js index 535eeb2..e301e55 100644 --- a/utils/notification.js +++ b/utils/notification.js @@ -1,11 +1,11 @@ const { volunteerConfirmationEmail, -} = require("./emailTemplate/Class.planner.volunteer.confirmation.attending.email"); +} = require('./emailTemplate/Class.planner.volunteer.confirmation.attending.email'); const { - cancelVolunteerBookingEmail, -} = require("./emailTemplate/Class.planner.volunteer.confirmation.attending.email"); -const { mailer } = require("./mailer"); -require("dotenv").config({ path: "./config/config.env" }); + adminEmailNotification, +} = require('./emailTemplate/Class.planner.admin.notification.email'); +const { mailer } = require('./mailer'); +require('dotenv').config({ path: './config/config.env' }); exports.bookingConfirmationEmail = async (data) => { try { @@ -21,3 +21,17 @@ exports.bookingConfirmationEmail = async (data) => { throw new Error(error); } }; +exports.adminSendEmailToClassVolunteers = async (data) => { + try { + const emailData = { + toEmail: data.emails, + subject: `CYF - ${data.subject}`, + html: adminEmailNotification(data.emailText), + replyToEmail: process.env.CATCH_ON_ALL_EMAIL, + }; + await mailer(emailData); + } catch (error) { + console.log(error); + throw new Error(error); + } +}; \ No newline at end of file