801 lines
27 KiB
JavaScript
801 lines
27 KiB
JavaScript
// import { format, startOfMonth, endOfMonth, eachDayOfInterval, startOfWeek, endOfWeek, isSameMonth } from 'date-fns';
|
||
|
||
|
||
|
||
const levenshtein = require('fastest-levenshtein');
|
||
|
||
const fs = typeof window === 'undefined' ? require('fs') : undefined;
|
||
const path = typeof window === 'undefined' ? require('path') : undefined;
|
||
const { PrismaClient, UserRole } = require('@prisma/client');
|
||
const DayOfWeek = require("@prisma/client").DayOfWeek;
|
||
const winston = require('winston');
|
||
const { getSession } = require("next-auth/react");
|
||
|
||
|
||
const logger = winston.createLogger({
|
||
level: 'info', // Set the default log level
|
||
format: winston.format.json(), // Choose a log format
|
||
transports: [
|
||
// Define where logs should be output (e.g., to a file or the console)
|
||
new winston.transports.Console(),
|
||
],
|
||
});
|
||
|
||
exports.logger = logger;
|
||
|
||
// import { DayOfWeek } from "@prisma/client";
|
||
|
||
//const UserRole = require("@prisma/client").UserRole; - does not allow usage of UserRole in code
|
||
// import { UserRole } from '@prisma/client';
|
||
|
||
// const getConfig = require("next/config");
|
||
// exports.nextconfig = getConfig();
|
||
// //const { serverRuntimeConfig } = getConfig();
|
||
|
||
// const dotenv = require("dotenv");
|
||
// dotenv.config();
|
||
// // dotenv.config({ path: ".env.local" });
|
||
|
||
exports.isValidPhoneNumber = function (phone) {
|
||
if (typeof phone !== 'string') {
|
||
return false; // or handle as you see fit
|
||
}
|
||
// Remove spaces and dashes for validation
|
||
const cleanedPhone = phone.replace(/\s|-/g, '');
|
||
|
||
// Check if the phone starts with '08' and has 10 digits
|
||
if ((cleanedPhone.startsWith('08') || cleanedPhone.startsWith('07')) && cleanedPhone.length === 10) {
|
||
return true;
|
||
}
|
||
|
||
// Check if the phone starts with '+359' and has the correct length
|
||
if (cleanedPhone.startsWith('+359') && cleanedPhone.length === 13) {
|
||
return true;
|
||
}
|
||
|
||
// If neither condition is met, the phone number is invalid
|
||
return false;
|
||
}
|
||
|
||
exports.getBaseUrl = function (relative = "", req = null) {
|
||
return process.env.NEXT_PUBLIC_PUBLIC_URL + relative;
|
||
};
|
||
|
||
|
||
let prisma;
|
||
exports.getPrismaClient = function getPrismaClient() {
|
||
if (!prisma) {
|
||
logger.debug("getPrismaClient: process.env.DATABASE = ", process.env.DATABASE);
|
||
prisma = new PrismaClient({
|
||
// Optional: Enable Prisma logging
|
||
//log: ['query', 'info', 'warn', 'error'],
|
||
datasources: { db: { url: process.env.DATABASE } },
|
||
});
|
||
}
|
||
logger.debug("getPrismaClient: process.env.DATABASE = ", process.env.DATABASE);
|
||
|
||
return prisma;
|
||
}
|
||
|
||
|
||
exports.removeAccentsAndSpecialCharacters = function (str) {
|
||
return str.normalize("NFD") // split an accented letter in the base letter and the accent
|
||
.replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
|
||
.replace(/[^a-zA-Z0-9]/g, ""); // remove all chars not letters and not digits
|
||
}
|
||
|
||
Date.prototype.getDayEuropean = function () {
|
||
const day = this.getDay();
|
||
return (day === 0) ? 6 : day - 1; // Convert 0 (Sunday) to 6, and decrement other days by 1
|
||
};
|
||
|
||
// Helper function to convert month name to 0-based index
|
||
exports.getMonthNames = function () {
|
||
return ["януари", "февруари", "март", "април", "май", "юни", "юли", "август", "септември", "октомври", "ноември", "декември"];
|
||
}
|
||
exports.getMonthIndex = function (monthName) {
|
||
return exports.getMonthNames().indexOf(monthName.toLowerCase());
|
||
};
|
||
|
||
exports.getMonthName = function (monthIndex) {
|
||
return exports.getMonthNames()[monthIndex];
|
||
};
|
||
|
||
|
||
exports.getMonthNameEn = function (monthIndex) {
|
||
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||
return monthNames[monthIndex];
|
||
};
|
||
|
||
exports.dayOfWeekNames = ["понеделник", "вторник", "сряда", "четвъртък", "петък", "събота", "неделя"];
|
||
exports.DaysOfWeekArray = [DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday];
|
||
|
||
// Helper function to convert day of week name to 0-based index (Sunday = 0)
|
||
exports.getDayOfWeekIndex = function (dayOfWeekName) {
|
||
dayOfWeekName = dayOfWeekName.toLowerCase().trim();
|
||
const abbreviatedDayOfWeekNames = ["пон", "вт", "ср", "четв", "пет", "съб", "нед"];
|
||
const enDayOfWeekNames = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"].map((d) => d.toLowerCase());
|
||
|
||
let index = exports.dayOfWeekNames.indexOf(dayOfWeekName);
|
||
|
||
// If not found in the full names, look in the abbreviated names
|
||
if (index === -1) {
|
||
index = abbreviatedDayOfWeekNames.indexOf(dayOfWeekName);
|
||
}
|
||
if (index === -1) {
|
||
index = enDayOfWeekNames.indexOf(dayOfWeekName);
|
||
}
|
||
logger.debug("getDayOfWeekIndex: dayOfWeekName = ", dayOfWeekName, "index = ", index);
|
||
return index;
|
||
};
|
||
|
||
|
||
exports.getDayOfWeekName = function (date) {
|
||
const dayOfWeekIndex = date.getDayEuropean();
|
||
return exports.dayOfWeekNames[dayOfWeekIndex];
|
||
};
|
||
|
||
exports.getDayOfWeekNameEnEnumForDate = function (date) {
|
||
date = new Date(date);
|
||
const dayOfWeekIndex = date.getDayEuropean();
|
||
return exports.DaysOfWeekArray[dayOfWeekIndex];
|
||
}
|
||
|
||
//obsolete: we want to ensure getDayEuropean() is used, hense we will not use this function
|
||
// exports.getDayOfWeekNameEnEnum = function (dayOfWeekIndex) {
|
||
// //return enum instead of string
|
||
// // const dayOfWeekNames: Record<number, DayOfWeek> = {
|
||
// // 0: DayOfWeek.Monday,
|
||
// // 1: DayOfWeek.Tuesday,
|
||
// // 2: DayOfWeek.Wednesday,
|
||
// // 3: DayOfWeek.Thursday,
|
||
// // 4: DayOfWeek.Friday,
|
||
// // 5: DayOfWeek.Saturday,
|
||
// // 6: DayOfWeek.Sunday
|
||
// // };
|
||
// return exports.DaysOfWeekArray[dayOfWeekIndex];
|
||
|
||
// }
|
||
exports.getPubTypeEnum = function (text) {
|
||
const input = text.trim();
|
||
const mapping = {
|
||
'Вестител': 'Publisher',
|
||
'Бетелит': 'Bethelite',
|
||
'Редовен Пионер': 'RegularPioneer',
|
||
'Специален Пионер/Мисионер': 'SpecialPioneer_Missionary',
|
||
};
|
||
|
||
// Default to 'Publisher' if the input does not match any key
|
||
return mapping[input] || 'Publisher';
|
||
}
|
||
|
||
|
||
/*
|
||
sets the date portion of the date object to the correct day of week, keeping the time portion
|
||
*/
|
||
exports.getDayOfWeekDate = function (dayOfWeekName, date = new Date()) {
|
||
const targetDay = exports.DaysOfWeekArray.indexOf(dayOfWeekName); // 0 = Sunday, 1 = Monday, etc.
|
||
if (targetDay === -1) {
|
||
throw new Error('Invalid day of week name provided');
|
||
}
|
||
// Adjust currentDay to match our custom mapping
|
||
let currentDay = date.getDayEuropean();
|
||
const daysDifference = targetDay - currentDay;
|
||
date.setDate(date.getDate() + daysDifference);
|
||
return date;
|
||
};
|
||
//common.getWeekOfMonth(date)
|
||
exports.getWeekOfMonth = function (inputDate) { //getWeekOfMonth?
|
||
let date = new Date(inputDate);
|
||
let firstDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1);
|
||
let firstMonday = new Date(firstDayOfMonth);
|
||
|
||
// Adjust firstDayOfMonth to the first Monday of the month
|
||
if (firstDayOfMonth.getDay() === 0) { // Sunday
|
||
firstMonday.setDate(2);
|
||
} else if (firstDayOfMonth.getDay() !== 1) { // Not Monday
|
||
firstMonday.setDate(9 - firstDayOfMonth.getDay());
|
||
}
|
||
|
||
// Calculate the difference in days
|
||
let diff = (date - firstMonday) / (1000 * 60 * 60 * 24);
|
||
// Calculate week number
|
||
let weekNumber = Math.ceil((diff + 1) / 7);
|
||
|
||
return weekNumber;
|
||
};
|
||
|
||
exports.getDateFromWeekNrAndDayOfWeek = function (firstMonday, weekNr, dayOfWeekEnum, startTime) {
|
||
firstMonday = new Date(firstMonday);
|
||
startTime = new Date(startTime);
|
||
if (!weekNr || weekNr < 1 || weekNr > 5) {
|
||
weekNr = this.getWeekOfMonth(startTime);
|
||
}
|
||
//get int from dayOfWeekEnum
|
||
let dayOfWeekNr = this.getDayOfWeekIndex(dayOfWeekEnum);
|
||
if (dayOfWeekNr < 0 || dayOfWeekNr > 6) {
|
||
dayOfWeekNr = 0;
|
||
}
|
||
|
||
// Calculate the day offset from the first Monday of the month
|
||
// Note: Assuming dayOfWeekEnum starts from 0 (Monday) to 6 (Sunday)
|
||
const daysFromFirstMonday = (weekNr - 1) * 7 + dayOfWeekNr;
|
||
|
||
// Calculate the new date
|
||
let newStart = new Date(firstMonday);
|
||
newStart.setDate(firstMonday.getDate() + daysFromFirstMonday);
|
||
|
||
// Extract time from startTime and apply it to newStart
|
||
const time = new Date(startTime);
|
||
newStart.setHours(time.getHours(), time.getMinutes(), time.getSeconds());
|
||
|
||
return newStart;
|
||
}
|
||
|
||
exports.getMonthDatesInfo = function (date) {
|
||
// cast to date if not daate
|
||
date = new Date(date);
|
||
// get first day of the month
|
||
var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
|
||
// get first day of next month
|
||
var lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 1);
|
||
// lastDay = new Date(lastDay.getTime() - 1);
|
||
lastDay = new Date(lastDay.getTime() - 86400000); // 86400000 ms = 1 day
|
||
|
||
// // get the day of the week of the first day
|
||
var firstDayOfWeek = firstDay.getDay(); // 0 = Sunday, 1 = Monday, etc.
|
||
// calculate the date of the first Monday
|
||
var firstMonday = new Date(firstDay);
|
||
if (firstDayOfWeek !== 1) { // Check if the first day is not already a Monday
|
||
firstMonday.setDate(firstDay.getDate() + ((7 - firstDayOfWeek) % 7) + 1);
|
||
}
|
||
|
||
// get last Monday
|
||
var lastMonday = new Date(lastDay);
|
||
if (lastDay.getDay() !== 0) { // Check if the last day is not already a Sunday
|
||
lastMonday.setDate(lastDay.getDate() - ((lastDay.getDay() + 6) % 7));
|
||
} else {
|
||
lastMonday.setDate(lastDay.getDate() - 6);
|
||
}
|
||
|
||
// get Sunday of the last week
|
||
var lastSunday = new Date(lastMonday);
|
||
lastSunday.setDate(lastMonday.getDate() + 6);
|
||
var monthName = exports.getMonthName(date.getMonth());
|
||
|
||
|
||
// var firstDayNextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1);
|
||
// // Calculate the last Sunday of the current month
|
||
// // .getDay() returns 0 for Sunday, 1 for Monday, ..., 6 for Saturday
|
||
// var lastSunday = new Date(firstDayNextMonth);
|
||
// lastSunday.setDate(firstDayNextMonth.getDate() - firstDayNextMonth.getDay());
|
||
|
||
//logger.debug("Last Sunday: ", lastSunday);
|
||
const diffInDays = (lastSunday - firstMonday) / (1000 * 60 * 60 * 24);
|
||
// Calculate number of weeks, rounding up for partial weeks
|
||
const nrOfWeeks = Math.ceil((diffInDays + 1) / 7);
|
||
|
||
return {
|
||
firstDay: firstDay,
|
||
lastDay: lastDay,
|
||
firstMonday: firstMonday,
|
||
lastMonday: lastMonday,
|
||
lastSunday: lastSunday,
|
||
date: date,
|
||
monthName: monthName,
|
||
year: date.getFullYear(),
|
||
nrOfWeeks: nrOfWeeks
|
||
};
|
||
};
|
||
exports.getMonthInfo = exports.getMonthDatesInfo;
|
||
|
||
exports.getMonthlyScheduleRange = function (date) {
|
||
let info = exports.getMonthDatesInfo(date);
|
||
// get first day of the month
|
||
var firstDay = info.firstDay;
|
||
// get last sunday of the month
|
||
var lastSunday = info.lastSunday;
|
||
return {
|
||
firstDay: firstDay,
|
||
lastSunday: lastSunday
|
||
};
|
||
};
|
||
|
||
exports.getWeekNumber = function (date) {
|
||
let info = exports.getMonthDatesInfo(date);
|
||
|
||
// If the date is before the first full week, return 0
|
||
if (date < info.firstMonday) {
|
||
return 0;
|
||
}
|
||
|
||
// Calculate the week number based on the first full week
|
||
return Math.ceil((date.getDate() - info.firstMonday.getDate() + 1) / 7);
|
||
};
|
||
|
||
exports.compareTimes = function (time1, time2) {
|
||
const time1String = `${getHours(time1)}:${getMinutes(time1)}`;
|
||
const time2String = `${getHours(time2)}:${getMinutes(time2)}`;
|
||
return time1String.localeCompare(time2String);
|
||
};
|
||
exports.normalizeTime = function (date, baseDate) {
|
||
// return set(baseDate, {
|
||
// hours: getHours(date),
|
||
// minutes: getMinutes(date),
|
||
// seconds: getSeconds(date),
|
||
// milliseconds: 0
|
||
// });
|
||
//don't use date-fns
|
||
let newDate = new Date(baseDate);
|
||
newDate.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), 0);
|
||
return newDate;
|
||
}
|
||
|
||
exports.getTimeRange = function (start, end) {
|
||
start = new Date(start);
|
||
end = new Date(end);
|
||
const startTime = start.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Sofia' });
|
||
const endTime = end.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Sofia' });
|
||
return `${startTime}-${endTime}`;
|
||
}
|
||
|
||
//get date in format сряда 1 юли 2020 г.
|
||
exports.getDateFormated = function (date) {
|
||
const dayOfWeekName = exports.getDayOfWeekName(date);
|
||
const day = date.getDate();
|
||
const monthName = exports.getMonthName(date.getMonth());
|
||
const year = date.getFullYear();
|
||
return `${dayOfWeekName} ${day} ${monthName} ${year} г.`;
|
||
}
|
||
|
||
exports.getDateFormatedShort = function (date) {
|
||
const day = date.getDate();
|
||
const monthName = exports.getMonthName(date.getMonth());
|
||
return `${day} ${monthName}`;
|
||
}
|
||
|
||
|
||
exports.getTimeFomatted = function (date) {
|
||
return date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', timeZone: 'Europe/Sofia' });//timeZone: 'local'
|
||
|
||
}
|
||
|
||
/*Todo: remove:
|
||
toISOString
|
||
slice(0, 10)
|
||
|
||
getISODateFromDateTime > getISODateOnly
|
||
|
||
*/
|
||
exports.toLocalISO = function (date) {
|
||
// Adjust for timezone and get ISO string without 'Z'
|
||
const offset = date.getTimezoneOffset() * 60000; // offset in milliseconds
|
||
return new Date(date.getTime() - offset).toISOString().slice(0, -1);
|
||
};
|
||
|
||
exports.getISODateOnly = function (date) {
|
||
// Use toLocalISO and get the date part only
|
||
return this.toLocalISO(date).split('T')[0];
|
||
};
|
||
|
||
exports.getDateFromDateTime = function (day) {
|
||
// Adjust for timezone and reset time to midnight
|
||
var date = new Date(day);
|
||
date.setHours(0, 0, 0, 0);
|
||
const offset = date.getTimezoneOffset() * 60000;
|
||
return new Date(date.getTime() - offset);
|
||
};
|
||
|
||
|
||
// ###########################################
|
||
// remove empty nodes from json
|
||
|
||
// Function to check if an object is empty or contains only empty nodes
|
||
exports.isEmpty = function (obj) {
|
||
for (const key in obj) {
|
||
if (typeof obj[key] === 'object') {
|
||
if (!exports.isEmpty(obj[key])) {
|
||
return false;
|
||
}
|
||
} else if (obj[key] !== '') {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// Function to remove empty nodes from a JSON object
|
||
exports.jsonRemoveEmptyNodes = function (obj) {
|
||
const newObj = {};
|
||
|
||
for (const key in obj) {
|
||
if (typeof obj[key] === 'object') {
|
||
const cleanedObj = exports.jsonRemoveEmptyNodes(obj[key]);
|
||
if (!exports.isEmpty(cleanedObj)) {
|
||
newObj[key] = cleanedObj;
|
||
}
|
||
} else if (obj[key] !== '') {
|
||
newObj[key] = obj[key];
|
||
}
|
||
}
|
||
|
||
return newObj;
|
||
}
|
||
|
||
|
||
|
||
|
||
// #region string functions
|
||
|
||
//input:Светослав и Сириел Георгиеви
|
||
//output: Светослав Георгиев, Сириел Георгиев
|
||
//input: Игор и Галина Москвини
|
||
//output: Игор Москвин, Галина Москвин
|
||
exports.separateFamilyMemberNames = function (namesArray) {
|
||
logger.debug("separateFamilyMemberNames: " + namesArray);
|
||
const result = [];
|
||
// itteraate over all names
|
||
for (let i = 0; i < namesArray.trim().split(' '); i++) {
|
||
const name = namesArray[i];
|
||
|
||
// if name contains " и " then split it into two names
|
||
// else just add it to the result
|
||
if (name.includes(" и ")) {
|
||
const namePairs = name.split(" и ");
|
||
const firstNames = namePairs.map((pair) => pair.split(" ")[0]);
|
||
// last name is only one. and it is shared for both firstnames
|
||
const lastName = namePairs[1].split(" ")[1];
|
||
|
||
for (let i = 0; i < namePairs.length; i++) {
|
||
let firstName = firstNames[i];
|
||
|
||
if (i === namePairs.length - 1 && namePairs.length % 2 !== 0) {
|
||
result.push(`${firstName} ${lastName}`);
|
||
} else {
|
||
result.push(`${firstName} ${lastName}`);
|
||
}
|
||
}
|
||
} else {
|
||
result.push(name);
|
||
}
|
||
}
|
||
|
||
//normalize names
|
||
for (var i = 0; i < result.length; i++) {
|
||
var name = result[i].trim();
|
||
//cut last letter of name if it is "a" or "и" (bulgarian feminine ending)
|
||
if (name.endsWith("a") || name.endsWith("и")) {
|
||
name = name.substring(0, name.length - 1);
|
||
}
|
||
result[i] = name;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
exports.separateFamilyMemberNames2 = function (input) {
|
||
const nameParts = input.trim().split(' ');
|
||
let familyName = nameParts.pop();
|
||
|
||
const firstNames = nameParts.join(' ').split(' и ');
|
||
const result = firstNames.map(firstName => `${firstName} ${familyName}`);
|
||
return result;
|
||
|
||
}
|
||
|
||
exports.fuzzySearch = function (publishers, searchQuery, distanceThreshold = 0.9) {
|
||
const lowerCaseSearchQuery = searchQuery?.toLowerCase();
|
||
|
||
let results = publishers
|
||
.filter((p) => {
|
||
try {
|
||
const fullName = p.firstName.toLowerCase() + " " + p.lastName.toLowerCase();
|
||
const reversedFullName = p.lastName.toLowerCase() + " " + p.firstName.toLowerCase();
|
||
|
||
const distanceFullName = levenshtein.distance(fullName, lowerCaseSearchQuery);
|
||
const distanceReversedFullName = levenshtein.distance(reversedFullName, lowerCaseSearchQuery);
|
||
|
||
const similarityFullName = 1 - distanceFullName / Math.max(fullName.length, lowerCaseSearchQuery.length);
|
||
const similarityReversedFullName = 1 - distanceReversedFullName / Math.max(reversedFullName.length, lowerCaseSearchQuery.length);
|
||
|
||
// If total fullname length is less than 10 symbols, allow results that are 1 symbol difference
|
||
if ((fullName.length < 10 || reversedFullName.length < 10) && (distanceFullName <= 1 || distanceReversedFullName <= 1)) {
|
||
return true;
|
||
}
|
||
|
||
return similarityFullName >= distanceThreshold || similarityReversedFullName >= distanceThreshold
|
||
} catch (e) {
|
||
logger.error(e);
|
||
console.log(e);
|
||
return false;
|
||
}
|
||
})
|
||
.sort((a, b) => (a.similarity > b.similarity ? -1 : 1));
|
||
|
||
return (results && results.length > 0) ? results[0] : null;
|
||
|
||
}
|
||
|
||
|
||
exports.getCurrentNonthFormatted = function () {
|
||
const getCurrentYearMonth = () => {
|
||
const currentDate = new Date();
|
||
const year = currentDate.getFullYear();
|
||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
|
||
return `${year}-${month}`;
|
||
}
|
||
return getCurrentYearMonth();
|
||
}
|
||
|
||
exports.getCurrentYearMonth = () => {
|
||
const currentDate = new Date();
|
||
const year = currentDate.getFullYear();
|
||
const month = String(currentDate.getMonth() + 1).padStart(2, '0'); // Month is 0-indexed
|
||
return `${year}-${month}`;
|
||
}
|
||
exports.getTimeFormated = function (date) {
|
||
return this.formatTimeHHmm(date);
|
||
}
|
||
// format date to 'HH:mm' time string required by the time picker
|
||
exports.formatTimeHHmm = function (input) {
|
||
// Check if the input is a string or a Date object
|
||
const date = (typeof input === 'string') ? new Date(input) : input;
|
||
|
||
return date.toLocaleTimeString('en-US', {
|
||
hour12: false,
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
timeZone: 'Europe/Sofia'
|
||
}).substring(0, 5);
|
||
}
|
||
|
||
|
||
//parse 'HH:mm' time string to date object
|
||
exports.parseTimeHHmm = (timeString) => {
|
||
// If timeString is already a date, return it as is
|
||
if (timeString instanceof Date) {
|
||
return timeString;
|
||
}
|
||
|
||
const [hours, minutes] = timeString.split(':');
|
||
const date = new Date();
|
||
date.setHours(hours);
|
||
date.setMinutes(minutes);
|
||
return date;
|
||
}
|
||
|
||
exports.setTimeHHmm = (date, timeStringOrHours) => {
|
||
const newDate = new Date(date);
|
||
|
||
if (typeof timeStringOrHours === 'string' && timeStringOrHours.includes(':')) {
|
||
// If hours is a string in "HH:mm" format
|
||
const [h, m] = timeStringOrHours.split(':');
|
||
newDate.setHours(parseInt(h, 10), parseInt(m, 10), 0, 0);
|
||
} else {
|
||
// If hours and minutes are provided separately
|
||
newDate.setHours(parseInt(timeStringOrHours, 10), 0, 0, 0);
|
||
}
|
||
|
||
return newDate;
|
||
};
|
||
|
||
exports.getTimeInMinutes = (dateOrTimestamp) => {
|
||
const date = new Date(dateOrTimestamp);
|
||
logger.debug("getTimeInMinutes: date = ", date);
|
||
return date.getHours() * 60 + date.getMinutes();
|
||
};
|
||
|
||
exports.parseBool = function (value) {
|
||
if (value === undefined) {
|
||
return false;
|
||
}
|
||
value = value || "false";
|
||
const truthyValues = ['1', 'y', 'yes', 'true', 't'];
|
||
return truthyValues.includes(String(value).toLowerCase());
|
||
}
|
||
|
||
|
||
exports.getStartOfWeek = function (date) {
|
||
const result = new Date(date); // create a copy of the input date
|
||
// If the day is Sunday (0), we set it to -6, otherwise, subtract the current day of the week from 1 (for Monday)
|
||
let daysToSubtract = result.getDay() === 0 ? 6 : result.getDay() - 1;
|
||
result.setDate(result.getDate() - daysToSubtract);
|
||
result.setHours(0, 0, 0, 0); // set time to midnight
|
||
return result;
|
||
}
|
||
exports.getEndOfWeek = function (date) {
|
||
const result = new Date(date);
|
||
// If the day is Sunday (0 in `getDay()`), no addition is needed. Otherwise, add 7 minus the current day of the week.
|
||
let daysToAdd = result.getDay() === 0 ? 0 : 7 - result.getDay();
|
||
result.setDate(result.getDate() + daysToAdd);
|
||
result.setHours(23, 59, 59, 999); // set time to the last millisecond of the day
|
||
return result;
|
||
}
|
||
exports.getStartOfMonth = function (date) {
|
||
date = new Date(date);
|
||
return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
|
||
}
|
||
exports.getEndOfMonth = function (date) {
|
||
date = new Date(date);
|
||
const result = new Date(date.getFullYear(), date.getMonth() + 1, 0); // 0th day of the next month
|
||
result.setHours(23, 59, 59, 999); // set time to the last millisecond of the day
|
||
return result;
|
||
}
|
||
|
||
exports.excelSerialDateToDate = function (serial) {
|
||
// Set base date as 1899-12-31 (Excel's zero date, ignoring leap year bug)
|
||
let baseDate = new Date(1899, 11, 31);
|
||
|
||
// Extract date and time fractions
|
||
let datePart = Math.floor(serial);
|
||
let timePart = serial - datePart;
|
||
|
||
// Compute the complete date
|
||
let dateInMs = baseDate.getTime() + datePart * 24 * 60 * 60 * 1000;
|
||
let timeInMs = timePart * 24 * 60 * 60 * 1000;
|
||
|
||
// Construct and return the final date
|
||
return new Date(dateInMs + timeInMs);
|
||
}
|
||
// Function to get a value from the session
|
||
exports.getSessionValue = function (session, fieldName, defaultValue = null) {
|
||
return session[fieldName] || defaultValue;
|
||
};
|
||
|
||
// Function to update a value in the session
|
||
exports.updateSessionValue = function (session, fieldName, value) {
|
||
session[fieldName] = value;
|
||
session.save(); // Save the session after updating
|
||
};
|
||
|
||
|
||
exports.copyToClipboard = function (event, text) {
|
||
let contentToCopy;
|
||
|
||
if (event) {
|
||
const spanElement = event.currentTarget;
|
||
contentToCopy = spanElement.textContent;
|
||
|
||
// Animation logic
|
||
const originalText = spanElement.textContent;
|
||
const originalColor = spanElement.style.backgroundColor; // Store the original color
|
||
|
||
spanElement.textContent = "имейла копиран";
|
||
spanElement.style.backgroundColor = "blue"; // Change color to "info" (blue in this case)
|
||
|
||
setTimeout(() => {
|
||
spanElement.textContent = originalText;
|
||
spanElement.style.backgroundColor = originalColor; // Reset the color back to original
|
||
}, 3000); // Reset the text and color back to original after 3 seconds
|
||
} else {
|
||
// If event is null, use the provided text parameter
|
||
if (!text) {
|
||
console.error("No text provided to copy to clipboard");
|
||
return; // Exit the function if no text is provided
|
||
}
|
||
contentToCopy = text;
|
||
}
|
||
|
||
// Copy contentToCopy to clipboard
|
||
const tempTextarea = document.createElement('textarea');
|
||
tempTextarea.value = contentToCopy;
|
||
document.body.appendChild(tempTextarea);
|
||
tempTextarea.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(tempTextarea);
|
||
}
|
||
|
||
|
||
|
||
|
||
// exports.getUser = async function (req) {
|
||
// // Use req if provided (server-side), otherwise call getSession without args (client-side)
|
||
// const session = req ? await getSession({ req }) : await getSession();
|
||
// return session?.user;
|
||
// }
|
||
|
||
// exports.isUserInRole = function (req, allowedRoles = []) {
|
||
// const user = exports.getUser(req);
|
||
|
||
// // Check if the user is authenticated
|
||
// if (!user) {
|
||
// return false;
|
||
// }
|
||
|
||
// // If no specific roles are required, return true as the user is authenticated
|
||
// if (allowedRoles.length === 0) {
|
||
// return true;
|
||
// }
|
||
|
||
// // Check if the user's role is among the allowed roles
|
||
// // Ensure role exists and is a valid UserRole
|
||
// const userRole = user.role;
|
||
// return allowedRoles.includes(userRole);
|
||
// }
|
||
|
||
|
||
|
||
// Utility functions for localStorage operations
|
||
exports.setLocalStorage = function (key, value) {
|
||
if (typeof window !== 'undefined') {
|
||
window.localStorage.setItem(key, JSON.stringify(value));
|
||
}
|
||
};
|
||
|
||
exports.getLocalStorage = function (key, defaultValue) {
|
||
if (typeof window !== 'undefined') {
|
||
const stored = window.localStorage.getItem(key);
|
||
if (stored) {
|
||
try {
|
||
// Attempt to parse the stored JSON data
|
||
return JSON.parse(stored);
|
||
} catch (error) {
|
||
// Handle parsing error
|
||
console.error(`Error parsing JSON from localStorage for key '${key}':`, error);
|
||
// Return defaultValue or perform other error handling as needed
|
||
return defaultValue;
|
||
}
|
||
}
|
||
}
|
||
return defaultValue;
|
||
};
|
||
|
||
exports.root = function (req) {
|
||
return process.env.NEXT_PUBLIC_PUBLIC_URL;
|
||
}
|
||
|
||
exports.getInitials = function (names) {
|
||
const parts = names.split(' ');
|
||
return parts.map(part => part[0] + ".").join('');
|
||
}
|
||
|
||
// ? import { addMinutes } from 'date-fns';
|
||
exports.addMinutes = function (date, minutes) {
|
||
return new Date(date.getTime() + minutes * 60000); // 60000 milliseconds in a minute
|
||
}
|
||
|
||
/**
|
||
* Recursively converts all Date objects in an object to ISO strings.
|
||
* @param {Object} obj - The object to convert.
|
||
* @returns {Object} - The new object with all Date objects converted to ISO strings.
|
||
*/
|
||
exports.convertDatesToISOStrings = function (obj) {
|
||
if (obj === null || obj === undefined) {
|
||
return obj;
|
||
}
|
||
|
||
if (obj instanceof Date) {
|
||
return obj.toISOString();
|
||
}
|
||
|
||
if (Array.isArray(obj)) {
|
||
return obj.map(exports.convertDatesToISOStrings);
|
||
}
|
||
|
||
if (typeof obj === 'object') {
|
||
const keys = Object.keys(obj);
|
||
return keys.reduce((acc, key) => {
|
||
acc[key] = exports.convertDatesToISOStrings(obj[key]);
|
||
return acc;
|
||
}, {});
|
||
}
|
||
|
||
return obj;
|
||
}
|
||
|
||
|
||
// exports.getInitials = function (names) {
|
||
// const parts = names.split(' '); // Split the full name into parts
|
||
// if (parts.length === 0) {
|
||
// return '';
|
||
// }
|
||
// // Extract the first two letters of the first name
|
||
// let initials = parts[0].substring(0, 2) + ".";
|
||
|
||
// // If there is a last name, add the first letter of the last name
|
||
// if (parts.length > 1) {
|
||
// initials += parts[parts.length - 1][0] + ".";
|
||
// }
|
||
|
||
// return initials;
|
||
// }
|