diff --git a/pages/api/email.ts b/pages/api/email.ts index 7aae223..e77134e 100644 --- a/pages/api/email.ts +++ b/pages/api/email.ts @@ -4,8 +4,10 @@ import { getToken } from "next-auth/jwt"; import type { NextApiRequest, NextApiResponse } from 'next'; import { createRouter, expressWrapper } from "next-connect"; const common = require('../../src/helpers/common'); -const email = require('../../src/helpers/'); +const emailHelper = require('../../src/helpers/email'); +import fs from 'fs'; +import path from 'path'; const handlebars = require("handlebars"); const router = createRouter(); @@ -51,7 +53,7 @@ export default async function handler(req, res) { if (!user) { return res.status(404).json({ message: "User not found" }); } - + var emailaction = req.query.emailaction; switch (action) { case "send_coverme_request": // Send CoverMe request to the user @@ -72,84 +74,121 @@ export default async function handler(req, res) { //send email to all subscribed publishers for (let i = 0; i < subscribedPublishers.length; i++) { //send email to subscribed publisher - //send email to subscribed publisher - const emailResponse = await common.sendEmail(subscribedPublishers[i].email, "CoverMe Request", - "User: " + user.email + " sent a CoverMe request: " + - shiftId + " " + assignmentId + " " + date); - } - - break; - case "coverme_accept": - // Update the user status to accepted - console.log("User: " + user.firstName + " " + user.lastName + " accepted the CoverMe request"); - //validate shiftId and assignmentId - let shiftId = req.query.shiftId; - let assignmentId = req.query.assignmentId; - if (!shiftId || !assignmentId) { - return res.status(400).json({ message: "Shift ID or Assignment ID is not provided" }); - } - - //get the assignment - const assignment = await prisma.assignment.findUnique({ - where: { - id: parseInt(assignmentId) + let shift = await prisma.shift.findUnique({ + where: { + id: parseInt(shiftId) + }, + include: { + cartEvent: { + include: { + location: true + } + }, + } } - }); - if (!assignment) { - return res.status(404).json({ message: "Assignment not found" }); - } - if (assignment.shiftId != parseInt(shiftId)) { - return res.status(400).json({ message: "Shift ID does not match" }); + ); + + let acceptUrl = process.env.NEXTAUTH_URL + "/api/emailActions?action=coverme_accept&userId=" + user.id + "&shiftId=" + shiftId + "&assignmentId=" + assignmentId; + + let model = { + user: user, + shiftId: shiftId, + assignmentId: assignmentId, + acceptUrl: acceptUrl, + prefix: subscribedPublishers[i].isMale ? "Брат" : "Сестра", + firstName: subscribedPublishers[i].firstName, + lastName: subscribedPublishers[i].lastName, + placeName: shift.cartEvent.location.name, + dateStr: date.toLocaleDateString(), + sentDate: date.toLocaleTimeString() + }; + emailHelper.SendEmailHandlebars(subscribedPublishers[i].email, "coverMe", model); } - - - - // await prisma.user.update({ - // where: { - // id: parseInt(userId) - // }, - // data: { - // status: "accepted", - // acceptedAt: date - // } - // }); break; - - //POST - case "send_report": //we can send report form in the emails to the user. process the POSTED data here - // Send report form to the user - //get from POST data: locationId, date, placementCount, videoCount, returnVisitInfoCount, conversationCount - let locationId = req.body.locationId; - let date = req.body.date; - let placementCount = req.body.placementCount; - let videoCount = req.body.videoCount; - let returnVisitInfoCount = req.body.returnVisitInfoCount; - let conversationCount = req.body.conversationCount; - - console.log("User: " + user.email + " sent a report: " + - locationId + " " + date + " " + - placementCount + " " + videoCount + " " + - returnVisitInfoCount + " " + conversationCount); - - //save the report in the database - await prisma.report.create({ - data: { - userId: parseInt(userId), - locationId: parseInt(locationId), - date: date, - placementCount: parseInt(placementCount), - videoCount: parseInt(videoCount), - returnVisitInfoCount: parseInt(returnVisitInfoCount), - conversationCount: parseInt(conversationCount) - } - }); - + case "email_response": + //get email action + if (!emailaction) { + return res.status(400).json({ message: "Email action is not provided" }); + } break; - default: return res.status(400).json({ message: "Invalid action" }); } + + + + if (action !== "email_response") { + switch (emailaction) { + case "coverme_accept": + // Update the user status to accepted + console.log("User: " + user.firstName + " " + user.lastName + " accepted the CoverMe request"); + //validate shiftId and assignmentId + let shiftId = req.query.shiftId; + let assignmentId = req.query.assignmentId; + if (!shiftId || !assignmentId) { + return res.status(400).json({ message: "Shift ID or Assignment ID is not provided" }); + } + + //get the assignment + const assignment = await prisma.assignment.findUnique({ + where: { + id: parseInt(assignmentId) + } + }); + if (!assignment) { + return res.status(404).json({ message: "Assignment not found" }); + } + if (assignment.shiftId != parseInt(shiftId)) { + return res.status(400).json({ message: "Shift ID does not match" }); + } + + // await prisma.user.update({ + // where: { + // id: parseInt(userId) + // }, + // data: { + // status: "accepted", + // acceptedAt: date + // } + // }); + break; + + //POST + case "send_report": //we can send report form in the emails to the user. process the POSTED data here + // Send report form to the user + //get from POST data: locationId, date, placementCount, videoCount, returnVisitInfoCount, conversationCount + let locationId = req.body.locationId; + let date = req.body.date; + let placementCount = req.body.placementCount; + let videoCount = req.body.videoCount; + let returnVisitInfoCount = req.body.returnVisitInfoCount; + let conversationCount = req.body.conversationCount; + + console.log("User: " + user.email + " sent a report: " + + locationId + " " + date + " " + + placementCount + " " + videoCount + " " + + returnVisitInfoCount + " " + conversationCount); + + //save the report in the database + await prisma.report.create({ + data: { + userId: parseInt(userId), + locationId: parseInt(locationId), + date: date, + placementCount: parseInt(placementCount), + videoCount: parseInt(videoCount), + returnVisitInfoCount: parseInt(returnVisitInfoCount), + conversationCount: parseInt(conversationCount) + } + }); + + break; + } + // //send email response to the user + // const emailResponse = await common.sendEmail(user.email, "Email Action Processed", + // "Your email action was processed successfully"); + } return res.status(200).json({ message: "User action processed" }); } diff --git a/src/helpers/email.js b/src/helpers/email.js index f73ef5f..09c4e82 100644 --- a/src/helpers/email.js +++ b/src/helpers/email.js @@ -39,6 +39,53 @@ exports.SendEmail = async function (to, subject, text, html) { }; }; +exports.SendEmailHandlebars = async function (to, templateName, model) { + // Ensure the sender and mailtrapTestClient are correctly defined or imported + + // Load and compile the main template + const mainTemplateSource = fs.readFileSync(path.join(__dirname, 'src', 'templates', 'emails', 'main.hbs'), 'utf8'); + const mainTemplate = Handlebars.compile(mainTemplateSource); + + // Dynamically load and compile the specified template + const templateSource = fs.readFileSync(path.join(__dirname, 'src', 'templates', 'emails', `${templateName}.hbs`), 'utf8'); + + // Extract subject and optional text version from the template source + const subjectMatch = templateSource.match(/{{!-- Subject: (.*) --}}/); + const textMatch = templateSource.match(/{{!-- Text: ([\s\S]*?) --}}/); + + const subject = subjectMatch ? subjectMatch[1].trim() : 'Default Subject'; + const textVersion = textMatch ? textMatch[1].trim() : null; + + // Remove the subject and text annotations from the template source + const cleanTemplateSource = templateSource.replace(/{{!-- Subject: .* --}}/, '').replace(/{{!-- Text: [\s\S]*? --}}/, ''); + + // Compile the cleaned template + const template = Handlebars.compile(cleanTemplateSource); + + // Render the specified template with the provided model + const templateHtml = template(model); + + // Render the main template, inserting the specific template HTML + const html = mainTemplate({ body: templateHtml }); + + // Generate a plain text version if not explicitly provided + const text = textVersion || html.replace(/<[^>]*>?/gm, ''); // Simple regex to strip HTML tags. Might need refinement. + + const message = { + from: sender, // Ensure 'sender' is defined + to, + subject, + text, + html, + }; + + // Assuming mailtrapTestClient is correctly set up to send emails + await mailtrapTestClient + .send(message) + .then(console.log) + .catch(console.error); +}; + exports.SendEmail_Test = async function (to, subject, text, html) { const message = { from: sender, diff --git a/src/templates/emails/coverMe.hbs b/src/templates/emails/coverMe.hbs index e69de29..90a58e8 100644 --- a/src/templates/emails/coverMe.hbs +++ b/src/templates/emails/coverMe.hbs @@ -0,0 +1,24 @@ +{{!-- Subject: Your email subject here --}} +{{!-- Text: Plain text version of your email. If not provided, HTML tags will be stripped from the HTML version for the +text version. --}} + +
+

{{firstName}} {{lastName}} търси зместник за {{placeName}}!

+

Здравейте,

+

{{prefix}} {{firstName}} {{lastName}} търси заместник за своята смяна на {{dateStr}} на {{placeName}}.

+ {{!--

Shift Details:

--}} + {{!--

Date: {{date}}
Time: {{time}}
Location: {{placeName}}

--}} +

С натискането на бутона по-долу можете да премете да го замествате. Вие, той/тя и останалите участници в смяната + ще бъдат уведумени чрез имейл за промяната. Вашата помощ е високо ценена.

+

+ Приеми + смяната +

+ {{!--

Thank you very much for considering my request.

+

Best regards,
{{name}}

--}} +
+ \ No newline at end of file diff --git a/src/templates/emails/main.hbs b/src/templates/emails/main.hbs new file mode 100644 index 0000000..80249dd --- /dev/null +++ b/src/templates/emails/main.hbs @@ -0,0 +1,25 @@ + + + + + + + Email Template + + + +
+

Company Name

+
+ +
+ {{{body}}} +
+ + + + + \ No newline at end of file