324 lines
14 KiB
TypeScript
324 lines
14 KiB
TypeScript
// API endpoint to process email user actions - urls we send in emails to users
|
||
|
||
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 data = require('../../src/helpers/data');
|
||
const emailHelper = require('../../src/helpers/email');
|
||
const { v4: uuidv4 } = require('uuid');
|
||
const CON = require("../../src/helpers/const");
|
||
|
||
import fs from 'fs';
|
||
import path from 'path';
|
||
const handlebars = require("handlebars");
|
||
|
||
const router = createRouter<NextApiRequest, NextApiResponse>();
|
||
|
||
|
||
//action to accept coverme request from email
|
||
|
||
|
||
/**
|
||
*
|
||
* @param req import { NextApiRequest, NextApiResponse } from 'next'
|
||
* @param res import { NextApiRequest, NextApiResponse } from 'next'
|
||
*/
|
||
export default async function handler(req, res) {
|
||
const prisma = common.getPrismaClient();
|
||
|
||
const action = req.query.action;
|
||
const emailaction = req.query.emailaction;
|
||
// Retrieve and validate the JWT token
|
||
|
||
//response is a special action that does not require a token
|
||
if (action == "email_response") {
|
||
switch (emailaction) {
|
||
case "coverMeAccept":
|
||
//validate shiftId and assignmentId
|
||
let shiftId = req.query.shiftId;
|
||
let userId = req.query.userId;
|
||
let publisher = await prisma.publisher.findUnique({
|
||
where: {
|
||
id: userId
|
||
}
|
||
});
|
||
// Update the user status to accepted
|
||
console.log("User: " + publisher.firstName + " " + publisher.lastName + " accepted the CoverMe request");
|
||
|
||
let assignmentPID = req.query.assignmentPID;
|
||
if (!shiftId) {
|
||
return res.status(400).json({ message: "Shift ID is not provided" });
|
||
}
|
||
if (!assignmentPID) {
|
||
return res.status(400).json({ message: "Assignment PID is not provided" });
|
||
}
|
||
//check if the assignment request is still open
|
||
const assignment = await prisma.assignment.findFirst({
|
||
where: {
|
||
publicGuid: assignmentPID,
|
||
shiftId: parseInt(shiftId),
|
||
isConfirmed: false
|
||
},
|
||
include: {
|
||
shift: {
|
||
include: {
|
||
cartEvent: {
|
||
include: {
|
||
location: true
|
||
}
|
||
},
|
||
assignments: {
|
||
include: {
|
||
publisher: true
|
||
// {
|
||
// include: {
|
||
// email: true,
|
||
// firstName: true,
|
||
// lastName: true
|
||
// }
|
||
// }
|
||
}
|
||
}
|
||
}
|
||
},
|
||
publisher: true
|
||
}
|
||
});
|
||
|
||
if (!assignment) {
|
||
const messagePageUrl = `/message?message=${encodeURIComponent('Благодаря за желанието, но някой е отговорил на тази заявка за заместване и тя вече е неактивна')}&type=info&caption=${encodeURIComponent('Някой вече те изпревари. Заявката е вече обработена')}`;
|
||
res.redirect(messagePageUrl);
|
||
return;
|
||
}
|
||
|
||
let to = assignment.shift.assignments.map(a => a.publisher.email);
|
||
to.push(publisher.email);
|
||
|
||
// update the assignment. clear the guid, isConfirmed to true
|
||
await prisma.assignment.update({
|
||
where: {
|
||
id: assignment.id
|
||
},
|
||
data: {
|
||
publisherId: userId,
|
||
publicGuid: null, // if this exists, we consider the request open
|
||
isConfirmed: true
|
||
}
|
||
});
|
||
const newAssignment = await prisma.assignment.findFirst({
|
||
where: {
|
||
shiftId: parseInt(shiftId),
|
||
isConfirmed: true
|
||
},
|
||
include: {
|
||
shift: {
|
||
include: {
|
||
cartEvent: {
|
||
include: {
|
||
location: true
|
||
}
|
||
},
|
||
assignments: {
|
||
include: {
|
||
publisher: true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
|
||
|
||
const shiftStr = `${CON.weekdaysBG[assignment.shift.startTime.getDay()]} ${CON.GetDateFormat(assignment.shift.startTime)} at ${assignment.shift.cartEvent.location.name} from ${CON.GetTimeFormat(assignment.shift.startTime)} to ${CON.GetTimeFormat(assignment.shift.endTime)}`;
|
||
|
||
const newPubs = newAssignment.shift.assignments.map(a => ({
|
||
name: `${a.publisher.firstName} ${a.publisher.lastName}`,
|
||
phone: a.publisher.phone
|
||
}));
|
||
|
||
let model = {
|
||
user: publisher,
|
||
shiftStr: shiftStr,
|
||
shiftId: assignment.shiftId,
|
||
prefix: publisher.isMale ? "Брат" : "Сестра",
|
||
oldPubName: assignment.publisher.firstName + " " + assignment.publisher.lastName,
|
||
firstName: publisher.firstName,
|
||
lastName: publisher.lastName,
|
||
newPubs: newPubs,
|
||
placeName: assignment.shift.cartEvent.location.name,
|
||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
||
sentDate: common.getDateFormated(new Date())
|
||
};
|
||
|
||
emailHelper.SendEmailHandlebars(to, "coverMeAccepted", model);
|
||
|
||
const messagePageUrl = `/message?message=${encodeURIComponent('Вашата заявка за замстване е обработена успешно')}&type=info&caption=${encodeURIComponent('Благодаря!')}`;
|
||
res.redirect(messagePageUrl);
|
||
|
||
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");
|
||
}
|
||
else {
|
||
|
||
const token = await getToken({ req: req });
|
||
if (!token) {
|
||
// If no token or invalid token, return unauthorized status
|
||
return res.status(401).json({ message: "Unauthorized to call this API endpoint" });
|
||
}
|
||
|
||
const user = await prisma.publisher.findUnique({
|
||
where: {
|
||
email: token.email
|
||
}
|
||
});
|
||
|
||
switch (action) {
|
||
case "sendCoverMeRequestByEmail":
|
||
// Send CoverMe request to the user
|
||
//get from POST data: shiftId, assignmentId, date
|
||
//let shiftId = req.body.shiftId;
|
||
let assignmentId = req.body.assignmentId;
|
||
|
||
let toSubscribed = req.body.toSubscribed;
|
||
let toAvailable = req.body.toAvailable;
|
||
|
||
|
||
let assignment = await prisma.assignment.findUnique({
|
||
where: {
|
||
id: parseInt(assignmentId)
|
||
},
|
||
include: {
|
||
shift: {
|
||
include: {
|
||
cartEvent: {
|
||
include: {
|
||
location: true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
console.log("User: " + user.email + " sent a 'CoverMe' request for his assignment " + assignmentId + " - " + assignment.shift.cartEvent.location.name + " " + assignment.shift.startTime.toISOString());
|
||
|
||
|
||
// update the assignment. generate new publicGuid, isConfirmed to false
|
||
let newPublicGuid = uuidv4();
|
||
await prisma.assignment.update({
|
||
where: {
|
||
id: parseInt(assignmentId)
|
||
},
|
||
data: {
|
||
publicGuid: newPublicGuid, // if this exists, we consider the request open
|
||
isConfirmed: false
|
||
}
|
||
});
|
||
|
||
let subscribedPublishers = [], availablePublishers = [];
|
||
if (toSubscribed) {
|
||
//get all subscribed publisers
|
||
subscribedPublishers = await prisma.publisher.findMany({
|
||
where: {
|
||
isSubscribedToCoverMe: true
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
if (toAvailable) {
|
||
availablePublishers = await data.filterPublishersNew("id,firstName,lastName,email", new Date(assignment.shift.startTime), true, false);
|
||
|
||
}
|
||
//concat and remove duplicate emails
|
||
let pubsToSend = subscribedPublishers.concat(availablePublishers).
|
||
filter((item, index, self) =>
|
||
index === self.findIndex((t) => (
|
||
t.email === item.email //and exclude the user himself
|
||
)) //&& item.email !== user.email
|
||
);
|
||
console.log("Sending CoverMe request to " + pubsToSend.length + " publishers");
|
||
|
||
//send email to all subscribed publishers
|
||
for (let i = 0; i < pubsToSend.length; i++) {
|
||
|
||
//send email to subscribed publisher
|
||
let acceptUrl = process.env.NEXTAUTH_URL + "/api/email?action=email_response&emailaction=coverMeAccept&userId=" + pubsToSend[i].id + "&shiftId=" + assignment.shiftId + "&assignmentPID=" + newPublicGuid;
|
||
|
||
let model = {
|
||
user: user,
|
||
shiftId: assignment.shiftId,
|
||
acceptUrl: acceptUrl,
|
||
prefix: user.isMale ? "Брат" : "Сестра",
|
||
firstName: pubsToSend[i].firstName,
|
||
lastName: pubsToSend[i].lastName,
|
||
email: pubsToSend[i].email,
|
||
placeName: assignment.shift.cartEvent.location.name,
|
||
dateStr: common.getDateFormated(assignment.shift.startTime),
|
||
time: common.formatTimeHHmm(assignment.shift.startTime),
|
||
sentDate: common.getDateFormated(new Date())
|
||
};
|
||
let results = emailHelper.SendEmailHandlebars(
|
||
{
|
||
name: pubsToSend[i].firstName + " " + pubsToSend[i].lastName,
|
||
email: pubsToSend[i].email
|
||
}, "coverMe", model);
|
||
// if (results) {
|
||
// console.log("Error sending email: " + error);
|
||
// return res.status(500).json({ message: "Error sending email:" + error });
|
||
//}
|
||
|
||
if (results) {
|
||
console.log("Email sent to: " + pubsToSend[i].email);
|
||
}
|
||
|
||
}
|
||
res.status(200).json({ message: "CoverMe request sent" });
|
||
|
||
break;
|
||
default:
|
||
return res.status(400).json({ message: "Invalid action" });
|
||
}
|
||
|
||
return res.status(200).json({ message: "User action processed" });
|
||
}
|
||
|
||
}
|
||
router.use(expressWrapper(handler));
|
||
|