fix calendar popup
This commit is contained in:
@ -10,6 +10,8 @@ import { bgBG } from '../x-date-pickers/locales/bgBG';
|
|||||||
import { ToastContainer } from 'react-toastify';
|
import { ToastContainer } from 'react-toastify';
|
||||||
const common = require('src/helpers/common');
|
const common = require('src/helpers/common');
|
||||||
//todo import Availability type from prisma schema
|
//todo import Availability type from prisma schema
|
||||||
|
import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const fetchConfig = async () => {
|
const fetchConfig = async () => {
|
||||||
@ -183,59 +185,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
return groupedIntervals;
|
return groupedIntervals;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // const firstSlotWithTransport = timeSlots[0].checked && timeSlots[0]?.isWithTransport;
|
|
||||||
// // const lastSlotWithTransport = timeSlots[timeSlots.length - 1].checked && timeSlots[timeSlots.length - 1]?.isWithTransport;
|
|
||||||
// function createAvailabilityFromGroup(group) {
|
|
||||||
// let startTime = new Date(day);
|
|
||||||
// startTime.setHours(group[0].startTime.getHours(), group[0].startTime.getMinutes(), group[0].startTime.getSeconds(), 0);
|
|
||||||
|
|
||||||
// let endTime = new Date(day);
|
|
||||||
// endTime.setHours(group[group.length - 1].endTime.getHours(), group[group.length - 1].endTime.getMinutes(), group[group.length - 1].endTime.getSeconds(), 0);
|
|
||||||
|
|
||||||
|
|
||||||
// return {
|
|
||||||
// name: common.getTimeFomatted(startTime) + "-" + common.getTimeFomatted(endTime),
|
|
||||||
// publisherId: publisher.id,
|
|
||||||
// startTime: startTime,
|
|
||||||
// endTime: endTime,
|
|
||||||
// isWithTransportIn: group[0].isFirst && timeSlots[0].isWithTransport,
|
|
||||||
// isWithTransportOut: group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport,
|
|
||||||
// dayofweek: common.getDayOfWeekNameEnEnumForDate(day.getDay()),
|
|
||||||
// repeatWeekly: doRepeat,
|
|
||||||
// dayOfMonth: doRepeat ? null : startTime.getDate(),
|
|
||||||
// endDate: doRepeat ? repeatUntil : null,
|
|
||||||
// dateOfEntry: new Date(),
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function updateAvailabilityFromGroup(availability, group) {
|
|
||||||
// availability.startTime.setTime(group[0].startTime);
|
|
||||||
// availability.endTime.setTime(group[group.length - 1].endTime);
|
|
||||||
// availability.name = common.getTimeFomatted(availability.startTime) + "-" + common.getTimeFomatted(availability.endTime);
|
|
||||||
|
|
||||||
// availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport;
|
|
||||||
// availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport;
|
|
||||||
|
|
||||||
// delete availability.weekOfMonth;
|
|
||||||
// if (doRepeat) {
|
|
||||||
// availability.repeatWeekly = true;
|
|
||||||
// availability.dayOfMonth = null;
|
|
||||||
// availability.weekOfMonth = 0;
|
|
||||||
// availability.endDate = repeatUntil;
|
|
||||||
// } else {
|
|
||||||
// availability.repeatWeekly = false;
|
|
||||||
// availability.dayOfMonth = availability.startTime.getDate();
|
|
||||||
// availability.endDate = null;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// availability.dateOfEntry = new Date();
|
|
||||||
// if (availability.parentAvailabilityId) {
|
|
||||||
// availability.parentAvailability = { connect: { id: parentAvailabilityId } };
|
|
||||||
// }
|
|
||||||
// delete availability.parentAvailabilityId;
|
|
||||||
|
|
||||||
// return availability;
|
|
||||||
// }
|
|
||||||
// Common function to set shared properties
|
// Common function to set shared properties
|
||||||
function setSharedAvailabilityProperties(availability, group, timeSlots) {
|
function setSharedAvailabilityProperties(availability, group, timeSlots) {
|
||||||
let startTime = new Date(availability.startTime || day);
|
let startTime = new Date(availability.startTime || day);
|
||||||
@ -332,22 +281,25 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
}
|
}
|
||||||
|
|
||||||
// console.log("AvailabilityForm: publisherId: " + publisher.id + ", id: " + availabilit .id, ", inline: " + isInline);
|
// console.log("AvailabilityForm: publisherId: " + publisher.id + ", id: " + availabilit .id, ", inline: " + isInline);
|
||||||
|
//ToDo: this is examplary function to be used in the future. replace all date/time related functions with this one
|
||||||
const generateTimeSlots = (start, end, increment, items) => {
|
const generateTimeSlots = (start, end, increment, items) => {
|
||||||
const slots = [];
|
const slots = [];
|
||||||
let currentTime = start.getTime();
|
let currentTime = start;
|
||||||
|
|
||||||
const endTime = end.getTime();
|
const baseDate = new Date(2000, 0, 1); // Use a constant date for all time comparisons
|
||||||
|
|
||||||
while (currentTime < endTime) {
|
while (isBefore(currentTime, end)) {
|
||||||
let slotStart = new Date(currentTime);
|
let slotStart = normalizeTime(currentTime, baseDate);
|
||||||
let slotEnd = new Date(currentTime + increment * 60000); // increment is in minutes
|
let slotEnd = normalizeTime(addMinutes(currentTime, increment), baseDate);
|
||||||
|
|
||||||
const isChecked = items.some(item =>
|
const isChecked = items.some(item => {
|
||||||
item.startTime && item.endTime &&
|
let itemStart = item.startTime ? normalizeTime(new Date(item.startTime), baseDate) : null;
|
||||||
(slotStart.getTime() < item.endTime.getTime()) &&
|
let itemEnd = item.endTime ? normalizeTime(new Date(item.endTime), baseDate) : null;
|
||||||
(slotEnd.getTime() > item.startTime.getTime())
|
|
||||||
);
|
return itemStart && itemEnd &&
|
||||||
|
(slotStart.getTime() <= itemEnd.getTime()) &&
|
||||||
|
(slotEnd.getTime() >= itemStart.getTime());
|
||||||
|
});
|
||||||
|
|
||||||
slots.push({
|
slots.push({
|
||||||
startTime: slotStart,
|
startTime: slotStart,
|
||||||
@ -355,10 +307,9 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
isChecked: isChecked,
|
isChecked: isChecked,
|
||||||
});
|
});
|
||||||
|
|
||||||
currentTime += increment * 60000; // Increment in milliseconds (minutes to milliseconds)
|
currentTime = addMinutes(currentTime, increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: Add isFirst, isLast, and isWithTransport properties
|
|
||||||
if (slots.length > 0 && items?.length > 0) {
|
if (slots.length > 0 && items?.length > 0) {
|
||||||
slots[0].isFirst = true;
|
slots[0].isFirst = true;
|
||||||
slots[slots.length - 1].isLast = true;
|
slots[slots.length - 1].isLast = true;
|
||||||
@ -369,6 +320,16 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
return slots;
|
return slots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Normalize the time part of a date by using a base date
|
||||||
|
function normalizeTime(date, baseDate) {
|
||||||
|
return set(baseDate, {
|
||||||
|
hours: getHours(date),
|
||||||
|
minutes: getMinutes(date),
|
||||||
|
seconds: getSeconds(date),
|
||||||
|
milliseconds: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
|
const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => {
|
||||||
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
|
const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked));
|
||||||
const handleAllDayChange = (e) => {
|
const handleAllDayChange = (e) => {
|
||||||
|
@ -16,7 +16,12 @@ import { MdToday } from 'react-icons/md';
|
|||||||
|
|
||||||
import { useSwipeable } from 'react-swipeable';
|
import { useSwipeable } from 'react-swipeable';
|
||||||
import axiosInstance from '../../src/axiosSecure';
|
import axiosInstance from '../../src/axiosSecure';
|
||||||
import { set } from 'date-fns';
|
// import { set, format, addDays } from 'date-fns';
|
||||||
|
import { isEqual, isSameDay, getHours, getMinutes } from 'date-fns';
|
||||||
|
import { filter } from 'jszip';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Set moment to use the Bulgarian locale
|
// Set moment to use the Bulgarian locale
|
||||||
moment.locale('bg');
|
moment.locale('bg');
|
||||||
@ -162,6 +167,31 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
occurrences.push(occurrence);
|
occurrences.push(occurrence);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const filterEvents = (evts, publisherId, startdate) => {
|
||||||
|
setDate(startdate); // Assuming setDate is a function that sets some state or context
|
||||||
|
|
||||||
|
// Filter events based on the publisher ID and the start date/time
|
||||||
|
const existingEvents = evts?.filter(event => {
|
||||||
|
// Ensure the event belongs to the specified publisher
|
||||||
|
const isPublisherMatch = (event.publisher?.id || event.publisherId) === publisherId;
|
||||||
|
|
||||||
|
let isDateMatch;
|
||||||
|
if (event.repeatWeekly && event.date) {
|
||||||
|
// Compare only the time part
|
||||||
|
const eventDate = new Date(event.startTime);
|
||||||
|
const isSameHour = getHours(eventDate) === getHours(startdate);
|
||||||
|
const isSameMinute = getMinutes(eventDate) === getMinutes(startdate);
|
||||||
|
isDateMatch = isSameHour && isSameMinute;
|
||||||
|
} else if (event.date) {
|
||||||
|
// Compare the full date
|
||||||
|
isDateMatch = isSameDay(new Date(event.date), startdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isPublisherMatch && isDateMatch;
|
||||||
|
});
|
||||||
|
|
||||||
|
return existingEvents;
|
||||||
|
};
|
||||||
|
|
||||||
// Define min and max times
|
// Define min and max times
|
||||||
const minHour = 8; // 8:00 AM
|
const minHour = 8; // 8:00 AM
|
||||||
@ -177,7 +207,8 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
const enddate = typeof end === 'string' ? new Date(end) : end;
|
const enddate = typeof end === 'string' ? new Date(end) : end;
|
||||||
|
|
||||||
if (!start || !end) return;
|
if (!start || !end) return;
|
||||||
if (startdate < new Date() || end < new Date() || startdate > end) return;
|
//readonly for past dates (ToDo: if not admin)
|
||||||
|
//if (startdate < new Date() || end < new Date() || startdate > end) return;
|
||||||
|
|
||||||
// Check if start and end are on the same day
|
// Check if start and end are on the same day
|
||||||
if (startdate.toDateString() !== enddate.toDateString()) {
|
if (startdate.toDateString() !== enddate.toDateString()) {
|
||||||
@ -198,52 +229,15 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
setDate(start);
|
setDate(start);
|
||||||
|
|
||||||
// get exising events for the selected date
|
// get exising events for the selected date
|
||||||
const existingEvents = evts?.filter(event => (event.publisher?.id || event.publisherId) === publisherId && new Date(event.date).toDateString() === startdate.toDateString());
|
const existingEvents = filterEvents(evts, publisherId, startdate);
|
||||||
// const existingEvents = evts?.filter(event => {
|
|
||||||
// return event.publisherId === publisherId &&
|
|
||||||
// new Date(event.startTime).getFullYear() === start.getFullYear() &&
|
|
||||||
// new Date(event.startTime).getMonth() === start.getMonth() &&
|
|
||||||
// new Date(event.startTime).getDate() === start.getDate();
|
|
||||||
// });
|
|
||||||
console.log("handleSelect: " + existingEvents);
|
console.log("handleSelect: " + existingEvents);
|
||||||
setSelectedEvents(existingEvents);
|
setSelectedEvents(existingEvents);
|
||||||
|
setIsModalOpen(true);
|
||||||
// setSelectedEvent({
|
|
||||||
// date: start,
|
|
||||||
// startTime: start,
|
|
||||||
// endTime: end,
|
|
||||||
// dayOfMonth: start.getDate(),
|
|
||||||
// isActive: true,
|
|
||||||
// publisherId: publisherId,
|
|
||||||
// // Add any other initial values needed
|
|
||||||
// //set dayOfMonth to null, so that we repeat the availability every week
|
|
||||||
// dayOfMonth: null,
|
|
||||||
|
|
||||||
// });
|
|
||||||
setIsModalOpen(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEventClick = (event) => {
|
const handleEventClick = (event) => {
|
||||||
if (event.type === "assignment") return;
|
if (event.type === "assignment") return;
|
||||||
handleSelect({ start: event.startTime, end: event.endTime });
|
handleSelect({ start: event.startTime, end: event.endTime });
|
||||||
// Handle event click
|
|
||||||
// const eventForEditing = {
|
|
||||||
// ...event,
|
|
||||||
// startTime: new Date(event.startTime),
|
|
||||||
// endTime: new Date(event.endTime),
|
|
||||||
// publisherId: event.publisherId || event.publisher?.connect?.id,
|
|
||||||
// repeatWeekly: event.repeatWeekly || false,
|
|
||||||
// };
|
|
||||||
// //strip title, start, end and allDay properties
|
|
||||||
// delete eventForEditing.title;
|
|
||||||
// delete eventForEditing.start;
|
|
||||||
// delete eventForEditing.end;
|
|
||||||
// delete eventForEditing.type;
|
|
||||||
// delete eventForEditing.publisher
|
|
||||||
// console.log("handleEventClick: " + eventForEditing);
|
|
||||||
// setSelectedEvents([eventForEditing]);
|
|
||||||
// setIsModalOpen(true);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDialogClose = async (dialogEvent) => {
|
const handleDialogClose = async (dialogEvent) => {
|
||||||
@ -256,10 +250,8 @@ const AvCalendar = ({ publisherId, events, selectedDate }) => {
|
|||||||
newEvents.forEach(event => {
|
newEvents.forEach(event => {
|
||||||
event.startTime = new Date(event.startTime);
|
event.startTime = new Date(event.startTime);
|
||||||
event.endTime = new Date(event.endTime);
|
event.endTime = new Date(event.endTime);
|
||||||
|
|
||||||
});
|
});
|
||||||
setEvents(newEvents);
|
setEvents(newEvents);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("handleSave: ", dialogEvent);
|
console.log("handleSave: ", dialogEvent);
|
||||||
|
@ -123,10 +123,10 @@ export default async function handler(req, res) {
|
|||||||
const availabilities = req.body;
|
const availabilities = req.body;
|
||||||
//! console.log("createAvailabilities: " + JSON.stringify(availabilities));
|
//! console.log("createAvailabilities: " + JSON.stringify(availabilities));
|
||||||
try {
|
try {
|
||||||
await prisma.availability.createMany({
|
let createResults = await prisma.availability.createMany({
|
||||||
data: availabilities
|
data: availabilities
|
||||||
});
|
});
|
||||||
res.status(200).json({ "message": "ok" });
|
res.status(200).json({ "message": "ok", "results": createResults });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error creating availabilities: " + error);
|
console.error("Error creating availabilities: " + error);
|
||||||
res.status(500).json({ error });
|
res.status(500).json({ error });
|
||||||
|
@ -24,7 +24,7 @@ function ContactsPage({ publishers, allPublishers }) {
|
|||||||
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
||||||
<div className="container mx-auto p-4">
|
<div className="container mx-auto p-4">
|
||||||
<h1 className="text-xl font-semibold mb-4">Статистика </h1>
|
<h1 className="text-xl font-semibold mb-4">Статистика </h1>
|
||||||
<h5 className="text-lg font-semibold mb-4">{publishers.length} участника с предпочитания (от {allPublishers.length} )</h5>
|
<h5 className="text-lg font-semibold mb-4">{publishers.length} участника с предпочитания за месеца (от {allPublishers.length} )</h5>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Търси по име, имейл или телефон..."
|
placeholder="Търси по име, имейл или телефон..."
|
||||||
|
@ -329,7 +329,11 @@ exports.getWeekNumber = function (date) {
|
|||||||
return Math.ceil((date.getDate() - info.firstMonday.getDate() + 1) / 7);
|
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.getTimeRange = function (start, end) {
|
exports.getTimeRange = function (start, end) {
|
||||||
start = new Date(start);
|
start = new Date(start);
|
||||||
|
Reference in New Issue
Block a user