diff --git a/components/publisher/SearchReplacement.js b/components/publisher/SearchReplacement.js
new file mode 100644
index 0000000..527cbc0
--- /dev/null
+++ b/components/publisher/SearchReplacement.js
@@ -0,0 +1,147 @@
+import React, { useState, useEffect } from 'react';
+import axiosInstance from '../../src/axiosSecure';
+import { toast } from 'react-toastify';
+import { set } from 'date-fns';
+
+function SearchReplacement({ shiftId, assignmentId }) {
+ const [users, setUsers] = useState([]);
+ const [showModal, setShowModal] = useState(false);
+
+ const fetchUsers = async () => {
+ // Dummy endpoint and shiftId, replace with actual
+ const response = await axiosInstance.get('/api/?action=getPossibleShiftPublisherEmails&shiftId=' + shiftId);
+ setUsers(response.data);
+ setShowModal(true);
+ };
+
+ const sendCoverMeRequestByEmail = (selectedGroups) => {
+ // You can map 'selectedGroups' to determine which API calls to make
+ console.log("Selected Groups:", selectedGroups);
+ axiosInstance.post('/api/email?action=sendCoverMeRequestByEmail', {
+ assignmentId: assignmentId,
+ toSubscribed: selectedGroups.includes('subscribedPublishers'),
+ toAvailable: selectedGroups.includes('availablePublishers'),
+ }).then(response => {
+ console.log("response", response);
+ setShowModal(false);
+ //toast success and confirm the change
+ toast.success("Заявката за заместник е изпратена!", {
+ onClose: () => {
+ window.location.reload();
+ }
+ });
+ }).catch(error => {
+ console.log("error", error);
+ });
+ }
+
+ return (
+
+
+ {
+ showModal && (
+ setShowModal(false)}
+ onConfirm={sendCoverMeRequestByEmail}
+ subscribedPublishers={users.subscribedPublishers}
+ availablePublishers={users.availablePublishers}
+ />
+ // setShowModal(false)}
+ // onConfirm={(selectedUsers) => {
+ // console.log(selectedUsers); // Here you would call the email API
+ // setShowModal(false);
+ // }}
+ // />
+ )
+ }
+
+ );
+}
+
+function ConfirmationModal({ isOpen, onClose, onConfirm, subscribedPublishers, availablePublishers }) {
+ const [selectedGroups, setSelectedGroups] = useState([]);
+
+ const handleToggleGroup = (groupName) => {
+ setSelectedGroups(prev => {
+ if (prev.includes(groupName)) {
+ return prev.filter(name => name !== groupName);
+ } else {
+ return [...prev, groupName];
+ }
+ });
+ };
+
+ if (!isOpen) return null;
+
+ return (
+
+
+
+
Можете да изпратите заявка за заместник до следните групи:
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+
+}
+
+
+export default SearchReplacement;
diff --git a/next.config.js b/next.config.js
index 87288ce..2406980 100644
--- a/next.config.js
+++ b/next.config.js
@@ -5,7 +5,7 @@ const withPWA = require('next-pwa')({
register: true, // ?
publicExcludes: ["!_error*.js"], //?
- disable: process.env.NODE_ENV === 'development',
+ //disable: process.env.NODE_ENV === 'development',
})
module.exports = withPWA({
diff --git a/pages/api/email.ts b/pages/api/email.ts
index 9b1b533..9a10ef8 100644
--- a/pages/api/email.ts
+++ b/pages/api/email.ts
@@ -4,6 +4,7 @@ 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");
@@ -213,9 +214,10 @@ export default async function handler(req, res) {
//get from POST data: shiftId, assignmentId, date
//let shiftId = req.body.shiftId;
let assignmentId = req.body.assignmentId;
- let date = req.body.date;
- console.log("User: " + user.email + " sent a 'CoverMe' request for his assignment " + assignmentId + " " + date);
+ let toSubscribed = req.body.toSubscribed;
+ let toAvailable = req.body.toAvailable;
+
let assignment = await prisma.assignment.findUnique({
where: {
@@ -233,6 +235,8 @@ export default async function handler(req, res) {
}
}
});
+ 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();
@@ -246,29 +250,43 @@ export default async function handler(req, res) {
}
});
- //get all subscribed publisers
- const subscribedPublishers = await prisma.publisher.findMany({
- where: {
- isSubscribedToCoverMe: true
- }
- });
+ 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
+ ))
+ );
+
//send email to all subscribed publishers
- for (let i = 0; i < subscribedPublishers.length; i++) {
- if (subscribedPublishers[i].id == user.id) {
- continue;
- }
+ 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=" + subscribedPublishers[i].id + "&shiftId=" + assignment.shiftId + "&assignmentPID=" + newPublicGuid;
+ 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: subscribedPublishers[i].firstName,
- lastName: subscribedPublishers[i].lastName,
- email: subscribedPublishers[i].email,
+ 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),
@@ -276,8 +294,8 @@ export default async function handler(req, res) {
};
let results = emailHelper.SendEmailHandlebars(
{
- name: subscribedPublishers[i].firstName + " " + subscribedPublishers[i].lastName,
- email: subscribedPublishers[i].email
+ name: pubsToSend[i].firstName + " " + pubsToSend[i].lastName,
+ email: pubsToSend[i].email
}, "coverMe", model);
// if (results) {
// console.log("Error sending email: " + error);
@@ -285,10 +303,12 @@ export default async function handler(req, res) {
//}
if (results) {
- console.log("Email sent to: " + subscribedPublishers[i].email);
+ 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" });
diff --git a/pages/api/index.ts b/pages/api/index.ts
index 6ce6997..538891d 100644
--- a/pages/api/index.ts
+++ b/pages/api/index.ts
@@ -347,6 +347,43 @@ export default async function handler(req, res) {
res.status(200).json({ "message": "ok" });
break;
+ case "getPossibleShiftPublisherEmails":
+ const subscribedPublishers = await prisma.publisher.findMany({
+ where: {
+ isSubscribedToCoverMe: true
+ },
+ select: {
+ id: true,
+ firstName: true,
+ lastName: true,
+ email: true
+ }
+ }).then(pubs => {
+ return pubs.map(pub => {
+ return {
+ id: pub.id,
+ name: pub.firstName + " " + pub.lastName,
+ email: pub.email
+ }
+ });
+ });
+
+ let shift = await prisma.shift.findUnique({
+ where: {
+ id: parseInt(req.query.shiftId)
+ }
+ });
+ let availablePublishers = await filterPublishersNew_Available("id,firstName,lastName,email", new Date(shift.startTime), true, false);
+ //return names and email info only
+ availablePublishers = availablePublishers.map(pub => {
+ return {
+ id: pub.id,
+ name: pub.firstName + " " + pub.lastName,
+ email: pub.email
+ }
+ });
+ res.status(200).json({ shift, availablePublishers: availablePublishers, subscribedPublishers });
+ break;
default:
res.status(200).json({
@@ -425,254 +462,7 @@ export async function getMonthlyStatistics(selectFields, filterDate) {
export async function filterPublishersNew_Available(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true) {
-
- // Only attempt to split if selectFields is a string; otherwise, use it as it is.
- selectFields = typeof selectFields === 'string' ? selectFields.split(",") : selectFields;
-
- let selectBase = selectFields.reduce((acc, curr) => {
- acc[curr] = true;
- return acc;
- }, {});
-
- selectBase.assignments = {
- select: {
- id: true,
- shift: {
- select: {
- id: true,
- startTime: true,
- endTime: true
- }
- }
- },
- where: {
- shift: {
- startTime: {
- gte: filterDate,
- }
- }
- }
- };
-
- var monthInfo = common.getMonthDatesInfo(filterDate);
- var weekNr = common.getWeekOfMonth(filterDate); //getWeekNumber
- let dayOfWeekEnum = common.getDayOfWeekNameEnEnumForDate(filterDate);
- if (!isExactTime) {
- filterDate.setHours(0, 0, 0, 0); // Set to midnight
- }
- const filterDateEnd = new Date(filterDate);
- filterDateEnd.setHours(23, 59, 59, 999);
-
-
- let whereClause = {};
- //if full day, match by date only
- if (!isExactTime) { // Check only by date without considering time ( Assignments on specific days without time)
- whereClause["availabilities"] = {
- some: {
- OR: [
- {
- startTime: { gte: filterDate },
- endTime: { lte: filterDateEnd },
- }
- ,
- // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
- // This includes availabilities from previous assignments but not with preference
- {
- dayOfMonth: null, // includes monthly and weekly repeats
- dayofweek: dayOfWeekEnum,
- // ToDo: and weekOfMonth
- startTime: { lte: filterDate },
- AND: [
- {
- OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
- { endDate: { gte: filterDate } },
- { endDate: null }
- ]
- }
- ]
- }
- ]
- }
- };
- }
- //if not full day, match by date and time
- else {
- //match exact time (should be same as data.findPublisherAvailability())
- whereClause["availabilities"] = {
- some: {
- OR: [
- // Check if dayOfMonth is set and filterDate is between start and end dates (Assignments on specific days AND time)
- {
- // dayOfMonth: filterDate.getDate(),
- startTime: { lte: filterDate },
- endTime: { gte: filterDate }
- },
- // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
- {
- dayOfMonth: null,
- dayofweek: dayOfWeekEnum,
- startTime: { gte: filterDate },
- AND: [
- {
- OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
- { endDate: { gte: filterDate } },
- { endDate: null }
- ]
- }
- ]
- }
- ]
- }
- };
- }
- if (isForTheMonth) {
- // If no filter date, return all publishers's availabilities for currentMonthStart
- whereClause["availabilities"] = {
- some: {
- OR: [
- // Check if dayOfMonth is not null and startTime is after currentMonthStart (Assignments on specific days AND time)
- {
- dayOfMonth: { not: null },
- startTime: { gte: currentMonthStart },
- endTime: { lte: currentMonthEnd }
- },
- // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
- {
- dayOfMonth: null,
- AND: [
- {
- OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
- { endDate: { gte: filterDate } },
- { endDate: null }
- ]
- }
- ]
- }
- ]
- }
- };
- }
-
- console.log(`getting publishers for date: ${filterDate}, isExactTime: ${isExactTime}, isForTheMonth: ${isForTheMonth}`);
- //include availabilities if flag is true
- const prisma = common.getPrismaClient(); //why we need to get it again?
- let publishers = await prisma.publisher.findMany({
- where: whereClause,
- select: {
- ...selectBase,
- availabilities: true
- }
- });
-
- console.log(`publishers: ${publishers.length}, WhereClause: ${JSON.stringify(whereClause)}`);
-
- // convert matching weekly availabilities to availabilities for the day to make furter processing easier on the client.
- // we trust that the filtering was OK, so we use the dateFilter as date.
- publishers.forEach(pub => {
- pub.availabilities = pub.availabilities.map(avail => {
- if (avail.dayOfMonth == null) {
- let newStart = new Date(filterDate);
- newStart.setHours(avail.startTime.getHours(), avail.startTime.getMinutes(), 0, 0);
- let newEnd = new Date(filterDate);
- newEnd.setHours(avail.endTime.getHours(), avail.endTime.getMinutes(), 0, 0);
- return {
- ...avail,
- startTime: newStart,
- endTime: newEnd
- }
- }
- return avail;
- });
- });
-
-
- let currentWeekStart: Date, currentWeekEnd: Date,
- currentMonthStart: Date, currentMonthEnd: Date,
- previousMonthStart: Date, previousMonthEnd: Date;
-
- if (isWithStats) {
- currentWeekStart = common.getStartOfWeek(filterDate);
- currentWeekEnd = common.getEndOfWeek(filterDate);
- currentMonthStart = monthInfo.firstMonday;
- currentMonthEnd = monthInfo.lastSunday;
- let prevMnt = new Date(filterDate)
- prevMnt.setMonth(prevMnt.getMonth() - 1);
- monthInfo = common.getMonthDatesInfo(prevMnt);
- previousMonthStart = monthInfo.firstMonday;
- previousMonthEnd = monthInfo.lastSunday;
-
- //get if publisher has assignments for current weekday, week, current month, previous month
- publishers.forEach(pub => {
- // Filter assignments for current day
- pub.currentDayAssignments = pub.assignments?.filter(assignment => {
- return assignment.shift.startTime >= filterDate && assignment.shift.startTime <= filterDateEnd;
- }).length;
-
- // Filter assignments for current week
- pub.currentWeekAssignments = pub.assignments?.filter(assignment => {
- return assignment.shift.startTime >= currentWeekStart && assignment.shift.startTime <= currentWeekEnd;
- }).length;
-
- // Filter assignments for current month
- pub.currentMonthAssignments = pub.assignments?.filter(assignment => {
- return assignment.shift.startTime >= currentMonthStart && assignment.shift.startTime <= currentMonthEnd;
- }).length;
-
- // Filter assignments for previous month
- pub.previousMonthAssignments = pub.assignments?.filter(assignment => {
- return assignment.shift.startTime >= previousMonthStart && assignment.shift.startTime <= previousMonthEnd;
- }).length;
- });
-
- }
-
- //get the availabilities for the day. Calcullate:
- //1. how many days the publisher is available for the current month - only with dayOfMonth
- //2. how many days the publisher is available without dayOfMonth (previous months count)
- //3. how many hours in total the publisher is available for the current month
- publishers.forEach(pub => {
- if (isWithStats) {
- pub.currentMonthAvailability = pub.availabilities?.filter(avail => {
- // return avail.dayOfMonth != null && avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd;
- return avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd;
- })
- pub.currentMonthAvailabilityDaysCount = pub.currentMonthAvailability.length || 0;
- // pub.currentMonthAvailabilityDaysCount += pub.availabilities.filter(avail => {
- // return avail.dayOfMonth == null;
- // }).length;
- pub.currentMonthAvailabilityHoursCount = pub.currentMonthAvailability.reduce((acc, curr) => {
- return acc + (curr.endTime.getTime() - curr.startTime.getTime()) / (1000 * 60 * 60);
- }, 0);
- //if pub has up-to-date availabilities (with dayOfMonth) for the current month
- pub.hasUpToDateAvailabilities = pub.availabilities?.some(avail => {
- return avail.dayOfMonth != null && avail.startTime >= currentMonthStart; // && avail.startTime <= currentMonthEnd;
- });
-
- }
-
- //if pub has ever filled the form - if has availabilities which are not from previous assignments
- pub.hasEverFilledForm = pub.availabilities?.some(avail => {
- return avail.isFromPreviousAssignments == false;
- });
-
- //if pub has availabilities for the current day
- pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => {
- return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
- });
-
- });
-
-
-
- if (isExactTime) {
- // Post filter for time if dayOfMonth is null as we can't only by time for multiple dates in SQL
- // Modify the availabilities array of the filtered publishers
- publishers.forEach(pub => {
- pub.availabilities = pub.availabilities?.filter(avail => matchesAvailability(avail, filterDate));
- });
- }
-
- return publishers;
+ return data.filterPublishersNew(selectFields, filterDate, isExactTime, isForTheMonth, isWithStats);
}
// availabilites filter:
diff --git a/pages/cart/publishers/myschedule.tsx b/pages/cart/publishers/myschedule.tsx
index bf8a2d5..017b21c 100644
--- a/pages/cart/publishers/myschedule.tsx
+++ b/pages/cart/publishers/myschedule.tsx
@@ -7,6 +7,7 @@ import common from '../../../src/helpers/common';
import Modal from 'components/Modal';
import ConfirmationModal from 'components/ConfirmationModal';
import PublisherSearchBox from '../../../components/publisher/PublisherSearchBox'; // Update the path
+import SearchReplacement from '../../../components/publisher/SearchReplacement'; // Update the path
import { monthNamesBG, GetTimeFormat, GetDateFormat } from "../../../src/helpers/const"
import { useSession, getSession } from 'next-auth/react';
@@ -52,21 +53,6 @@ export default function MySchedulePage({ assignments }) {
});
};
- const searchReplacement = (assignmentId) => {
- axiosInstance.post('/api/email?action=sendCoverMeRequestByEmail', {
- assignmentId: assignmentId,
- }).then(response => {
- console.log("response", response);
- //toast success and confirm the change
- toast.success("Заявката за заместник е изпратена!", {
- onClose: () => {
- window.location.reload();
- }
- });
- }).catch(error => {
- console.log("error", error);
- });
- }
return (
@@ -121,12 +107,8 @@ export default function MySchedulePage({ assignments }) {
>
Избери Заместник
-
+
+
diff --git a/src/helpers/data.js b/src/helpers/data.js
index dc39ff2..1cc459b 100644
--- a/src/helpers/data.js
+++ b/src/helpers/data.js
@@ -226,6 +226,268 @@ async function getAvailabilities(userId) {
return serializableItems;
}
+
+async function filterPublishersNew(selectFields, filterDate, isExactTime = false, isForTheMonth = false, isWithStats = true) {
+
+ // Only attempt to split if selectFields is a string; otherwise, use it as it is.
+ selectFields = typeof selectFields === 'string' ? selectFields.split(",") : selectFields;
+
+ let selectBase = selectFields.reduce((acc, curr) => {
+ acc[curr] = true;
+ return acc;
+ }, {});
+
+ selectBase.assignments = {
+ select: {
+ id: true,
+ shift: {
+ select: {
+ id: true,
+ startTime: true,
+ endTime: true
+ }
+ }
+ },
+ where: {
+ shift: {
+ startTime: {
+ gte: filterDate,
+ }
+ }
+ }
+ };
+
+ var monthInfo = common.getMonthDatesInfo(filterDate);
+ var weekNr = common.getWeekOfMonth(filterDate); //getWeekNumber
+ let dayOfWeekEnum = common.getDayOfWeekNameEnEnumForDate(filterDate);
+ if (!isExactTime) {
+ filterDate.setHours(0, 0, 0, 0); // Set to midnight
+ }
+ const filterDateEnd = new Date(filterDate);
+ filterDateEnd.setHours(23, 59, 59, 999);
+
+
+ let whereClause = {};
+ //if full day, match by date only
+ if (!isExactTime) { // Check only by date without considering time ( Assignments on specific days without time)
+ whereClause["availabilities"] = {
+ some: {
+ OR: [
+ {
+ startTime: { gte: filterDate },
+ endTime: { lte: filterDateEnd },
+ }
+ ,
+ // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
+ // This includes availabilities from previous assignments but not with preference
+ {
+ dayOfMonth: null, // includes monthly and weekly repeats
+ dayofweek: dayOfWeekEnum,
+ // ToDo: and weekOfMonth
+ startTime: { lte: filterDate },
+ AND: [
+ {
+ OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
+ { endDate: { gte: filterDate } },
+ { endDate: null }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ };
+ }
+ //if not full day, match by date and time
+ else {
+ //match exact time (should be same as data.findPublisherAvailability())
+ whereClause["availabilities"] = {
+ some: {
+ OR: [
+ // Check if dayOfMonth is set and filterDate is between start and end dates (Assignments on specific days AND time)
+ {
+ // dayOfMonth: filterDate.getDate(),
+ startTime: { lte: filterDate },
+ endTime: { gte: filterDate }
+ },
+ // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
+ {
+ dayOfMonth: null,
+ dayofweek: dayOfWeekEnum,
+ startTime: { gte: filterDate },
+ AND: [
+ {
+ OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
+ { endDate: { gte: filterDate } },
+ { endDate: null }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ };
+ }
+ if (isForTheMonth) {
+ // If no filter date, return all publishers's availabilities for currentMonthStart
+ whereClause["availabilities"] = {
+ some: {
+ OR: [
+ // Check if dayOfMonth is not null and startTime is after currentMonthStart (Assignments on specific days AND time)
+ {
+ dayOfMonth: { not: null },
+ startTime: { gte: currentMonthStart },
+ endTime: { lte: currentMonthEnd }
+ },
+ // Check if dayOfMonth is null and match by day of week using the enum (Assigments every week)
+ {
+ dayOfMonth: null,
+ AND: [
+ {
+ OR: [ // OR condition for repeatUntil to handle events that either end after filterDate or repeat forever
+ { endDate: { gte: filterDate } },
+ { endDate: null }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ };
+ }
+
+ console.log(`getting publishers for date: ${filterDate}, isExactTime: ${isExactTime}, isForTheMonth: ${isForTheMonth}`);
+ //include availabilities if flag is true
+ const prisma = common.getPrismaClient(); //why we need to get it again?
+ let publishers = await prisma.publisher.findMany({
+ where: whereClause,
+ select: {
+ ...selectBase,
+ availabilities: true
+ }
+ });
+
+ console.log(`publishers: ${publishers.length}, WhereClause: ${JSON.stringify(whereClause)}`);
+
+ // convert matching weekly availabilities to availabilities for the day to make furter processing easier on the client.
+ // we trust that the filtering was OK, so we use the dateFilter as date.
+ publishers.forEach(pub => {
+ pub.availabilities = pub.availabilities.map(avail => {
+ if (avail.dayOfMonth == null) {
+ let newStart = new Date(filterDate);
+ newStart.setHours(avail.startTime.getHours(), avail.startTime.getMinutes(), 0, 0);
+ let newEnd = new Date(filterDate);
+ newEnd.setHours(avail.endTime.getHours(), avail.endTime.getMinutes(), 0, 0);
+ return {
+ ...avail,
+ startTime: newStart,
+ endTime: newEnd
+ }
+ }
+ return avail;
+ });
+ });
+
+
+ let currentWeekStart, currentWeekEnd,
+ currentMonthStart, currentMonthEnd,
+ previousMonthStart, previousMonthEnd;
+
+ if (isWithStats) {
+ currentWeekStart = common.getStartOfWeek(filterDate);
+ currentWeekEnd = common.getEndOfWeek(filterDate);
+ currentMonthStart = monthInfo.firstMonday;
+ currentMonthEnd = monthInfo.lastSunday;
+ let prevMnt = new Date(filterDate)
+ prevMnt.setMonth(prevMnt.getMonth() - 1);
+ monthInfo = common.getMonthDatesInfo(prevMnt);
+ previousMonthStart = monthInfo.firstMonday;
+ previousMonthEnd = monthInfo.lastSunday;
+
+ //get if publisher has assignments for current weekday, week, current month, previous month
+ publishers.forEach(pub => {
+ // Filter assignments for current day
+ pub.currentDayAssignments = pub.assignments?.filter(assignment => {
+ return assignment.shift.startTime >= filterDate && assignment.shift.startTime <= filterDateEnd;
+ }).length;
+
+ // Filter assignments for current week
+ pub.currentWeekAssignments = pub.assignments?.filter(assignment => {
+ return assignment.shift.startTime >= currentWeekStart && assignment.shift.startTime <= currentWeekEnd;
+ }).length;
+
+ // Filter assignments for current month
+ pub.currentMonthAssignments = pub.assignments?.filter(assignment => {
+ return assignment.shift.startTime >= currentMonthStart && assignment.shift.startTime <= currentMonthEnd;
+ }).length;
+
+ // Filter assignments for previous month
+ pub.previousMonthAssignments = pub.assignments?.filter(assignment => {
+ return assignment.shift.startTime >= previousMonthStart && assignment.shift.startTime <= previousMonthEnd;
+ }).length;
+ });
+
+ }
+
+ //get the availabilities for the day. Calcullate:
+ //1. how many days the publisher is available for the current month - only with dayOfMonth
+ //2. how many days the publisher is available without dayOfMonth (previous months count)
+ //3. how many hours in total the publisher is available for the current month
+ publishers.forEach(pub => {
+ if (isWithStats) {
+ pub.currentMonthAvailability = pub.availabilities?.filter(avail => {
+ // return avail.dayOfMonth != null && avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd;
+ return avail.startTime >= currentMonthStart && avail.startTime <= currentMonthEnd;
+ })
+ pub.currentMonthAvailabilityDaysCount = pub.currentMonthAvailability.length || 0;
+ // pub.currentMonthAvailabilityDaysCount += pub.availabilities.filter(avail => {
+ // return avail.dayOfMonth == null;
+ // }).length;
+ pub.currentMonthAvailabilityHoursCount = pub.currentMonthAvailability.reduce((acc, curr) => {
+ return acc + (curr.endTime.getTime() - curr.startTime.getTime()) / (1000 * 60 * 60);
+ }, 0);
+ //if pub has up-to-date availabilities (with dayOfMonth) for the current month
+ pub.hasUpToDateAvailabilities = pub.availabilities?.some(avail => {
+ return avail.dayOfMonth != null && avail.startTime >= currentMonthStart; // && avail.startTime <= currentMonthEnd;
+ });
+
+ }
+
+ //if pub has ever filled the form - if has availabilities which are not from previous assignments
+ pub.hasEverFilledForm = pub.availabilities?.some(avail => {
+ return avail.isFromPreviousAssignments == false;
+ });
+
+ //if pub has availabilities for the current day
+ pub.hasAvailabilityForCurrentDay = pub.availabilities?.some(avail => {
+ return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
+ });
+
+ });
+
+
+
+ if (isExactTime) {
+ // Post filter for time if dayOfMonth is null as we can't only by time for multiple dates in SQL
+ // Modify the availabilities array of the filtered publishers
+ publishers.forEach(pub => {
+ pub.availabilities = pub.availabilities?.filter(avail => matchesAvailability(avail, filterDate));
+ });
+ }
+ return publishers;
+
+}
+
+function matchesAvailability(avail, filterDate) {
+ // Setting the start and end time of the filterDate
+ filterDate.setHours(0, 0, 0, 0);
+ const filterDateEnd = new Date(filterDate);
+ filterDateEnd.setHours(23, 59, 59, 999);
+
+ // Return true if avail.startTime is between filterDate and filterDateEnd
+ return avail.startTime >= filterDate && avail.startTime <= filterDateEnd;
+}
+
const fs = require('fs');
const path = require('path');
@@ -255,5 +517,6 @@ module.exports = {
findPublisher,
findPublisherAvailability,
runSqlFile,
- getAvailabilities
+ getAvailabilities,
+ filterPublishersNew
};
\ No newline at end of file
diff --git a/src/helpers/email.js b/src/helpers/email.js
index 1e0f2a1..2e8c9de 100644
--- a/src/helpers/email.js
+++ b/src/helpers/email.js
@@ -25,22 +25,23 @@ let mailtrapTestClient = null;
// password: 'c7bc05f171c96c'
// });
-//test
+//PROD MAILTRAP
var transporter = nodemailer.createTransport({
- host: process.env.MAILERSEND_SERVER,
- port: process.env.MAILERSEND_PORT,
+ host: process.env.MAILTRAP_HOST || "sandbox.smtp.mailtrap.io",
+ port: 2525,
auth: {
- user: process.env.MAILERSEND_USER,
- pass: process.env.MAILERSEND_PASS
+ user: process.env.MAILTRAP_USER,
+ pass: process.env.MAILTRAP_PASS
}
});
-// production
+
+//PROD MAILERSEND
// var transporter = nodemailer.createTransport({
-// host: "live.smtp.mailtrap.io",
-// port: 587,
+// host: process.env.MAILERSEND_SERVER,
+// port: process.env.MAILERSEND_PORT,
// auth: {
-// user: "api",
-// pass: "1cfe82e747b8dc3390ed08bb16e0f48d"
+// user: process.env.MAILERSEND_USER,
+// pass: process.env.MAILERSEND_PASS
// }
// });