import React, { useState, useEffect, use } from 'react'; import { useSession } from "next-auth/react" import Link from 'next/link'; import Calendar from 'react-calendar'; import 'react-calendar/dist/Calendar.css'; import axiosInstance from '../../../src/axiosSecure'; import Layout from "../../../components/layout" import Shift from '../../../components/calendar/ShiftComponent'; import { DayOfWeek, UserRole } from '@prisma/client'; import { env } from 'process' import ShiftComponent from '../../../components/calendar/ShiftComponent'; //import { set } from 'date-fns'; const common = require('src/helpers/common'); import { toast } from 'react-toastify'; import ProtectedRoute from '../../../components/protectedRoute'; import ConfirmationModal from '../../../components/ConfirmationModal'; import LocalShippingIcon from '@mui/icons-material/LocalShipping'; // import { FaPlus, FaCogs, FaTrashAlt, FaSpinner } from 'react-icons/fa'; // Import FontAwesome icons // import { useSession,} from 'next-auth/react'; // import { getToken } from "next-auth/jwt" //define Shift type interface Shift { id: number; startTime: Date; endTime: Date; cartEventId: number; assignments: Assignment[]; } interface Assignment { id: number; publisherId: number; shiftId: number; isConfirmed: boolean; publisher: Publisher; } interface Publisher { id: number; firstName: string; lastName: string; isImported: boolean; } // https://www.npmjs.com/package/react-calendar export default function CalendarPage({ initialEvents, initialShifts }) { const { data: session } = useSession() //if logged in, get the user's email // var email = ""; // const [events, setEvents] = useState(initialEvents); const events = initialEvents; const [allShifts, setAllShifts] = useState(initialShifts); const [isPublished, setIsPublished] = useState(() => initialShifts.some(shift => shift.isPublished)); const [value, onChange] = useState(new Date()); const [shifts, setShifts] = React.useState([]); const [error, setError] = React.useState(null); const [availablePubs, setAvailablePubs] = React.useState([]); const [selectedShiftId, setSelectedShiftId] = useState(null); const [isOperationInProgress, setIsOperationInProgress] = useState(false); const [progress, setProgress] = useState(0); const [activeButton, setActiveButton] = useState(null); const isLoading = (buttonId) => activeButton === buttonId; // ------------------ MODAL ------------------ const [isModalOpen, setIsModalOpen] = useState(false); const [modalPub, setModalPub] = useState(null); // ------------------ no assignments checkbox ------------------ const [filterShowWithoutAssignments, setFilterShowWithoutAssignments] = useState(false); const handleCheckboxChange = (event) => { setFilterShowWithoutAssignments(!filterShowWithoutAssignments); // Toggle the checkbox state }; useEffect(() => { console.log("checkbox checked: " + filterShowWithoutAssignments); handleCalDateChange(value); // Call handleCalDateChange whenever isCheckboxChecked changes }, [filterShowWithoutAssignments]); // Dependency array const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth()); useEffect(() => { const newMonth = value.getMonth(); if (newMonth !== selectedMonth) { setSelectedMonth(newMonth); } }, [value, selectedMonth]); const handleCalDateChange = async (selectedDate) => { var date = new Date(common.getDateFromDateTime(selectedDate));//ToDo: check if seting the timezone affects the selectedDate?! var dateStr = common.getISODateOnly(date); console.log("Setting date to '" + date.toLocaleDateString() + "' from '" + selectedDate.toLocaleDateString() + "'. ISO: " + date.toISOString(), "locale ISO:", common.getISODateOnly(date)); if (filterShowWithoutAssignments) { console.log(`getting unassigned publishers for ${common.getMonthName(date.getMonth())} ${date.getFullYear()}`); const { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=getUnassignedPublishers&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`); setAvailablePubs(availablePubsForDate); } else { console.log(`getting shifts for ${common.getISODateOnly(date)}`) try { const { data: shiftsForDate } = await axiosInstance.get(`/api/?action=getShiftsForDay&date=${dateStr}`); setShifts(shiftsForDate); setIsPublished(shiftsForDate.some(shift => shift.isPublished)); let { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=filterPublishersNew&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth&includeOldAvailabilities=${filterShowWithoutAssignments}`); availablePubsForDate.forEach(pub => { pub.canTransport = pub.availabilities.some(av => av.isWithTransportIn || av.isWithTransportOut ); }); //remove availabilities that are isFromPreviousAssignment or from previous month for each publisher // availablePubsForDate = availablePubsForDate.map(pub => { // pub.availabilities = pub.availabilities.filter(avail => avail.isFromPreviousAssignment == false); // return pub; // }); //commented for now: remove unavailable publishers // availablePubsForDate = availablePubsForDate.map(pub => { // pub.availabilities = pub.availabilities.filter(avail => avail.isFromPreviousAssignment == false); // return pub; // }); setAvailablePubs(availablePubsForDate); console.log(`found shifts for ${dateStr}: ${shiftsForDate.length}`); } catch (err) { console.error("Error fetching shifts:", err); setError(err); } onChange(selectedDate); } } const handleShiftSelection = (selectedShift) => { setSelectedShiftId(selectedShift.id); const updatedPubs = availablePubs.map(pub => { pub.isAvailableForShift = false; pub.canTransport = false; const av = pub.availabilities?.find(avail => avail.startTime <= selectedShift.startTime && avail.endTime >= selectedShift.endTime ); if (av) { pub.isAvailableForShift = true; pub.canTransport = av.isWithTransportIn || av.isWithTransportOut; } // const isAvailableForShift = pub.availabilities.some(avail => // avail.startTime <= selectedShift.startTime // && avail.endTime >= selectedShift.endTime // && avail.isFromPreviousAssignment == false // ); const isAvailableForShiftWithPrevious = pub.availabilities.some(avail => avail.startTime <= selectedShift.startTime && avail.endTime >= selectedShift.endTime ); // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} is available for shift ${selectedShift.id}: ${isAvailableForShift}`); // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + pub.availabilities.map(avail => avail.startTime + " - " + avail.endTime)); // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + stringify.join(', 'pub.availabilities.map(avail => avail.id))); // const availabilitiesIds = pub.availabilities.map(avail => avail.id).join(', '); // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities with IDs: ${availabilitiesIds}`); return { ...pub, isAvailableForShiftWithPrevious, isSelected: pub.id === selectedShift.selectedPublisher?.id }; }); // Sort publishers based on their availability state. use currentDayAssignments, currentWeekAssignments, // currentMonthAssignments and previousMonthAssignments properties // Sort publishers based on availability and then by assignment counts. const sortedPubs = updatedPubs.sort((a, b) => { if (a.isActive !== b.isActive) { return a.isActive ? -1 : 1; } // First, sort by isselected. if (a.isSelected !== b.isSelected) { return a.isSelected ? -1 : 1; } // Them, sort by availability. if (a.isAvailableForShift !== b.isAvailableForShift) { return a.isAvailableForShift ? -1 : 1; } // If both are available (or unavailable) for the shift, continue with the additional sorting logic. // Prioritize those without currentDayAssignments. if (!!a.currentDayAssignments !== !!b.currentDayAssignments) { return a.currentDayAssignments ? 1 : -1; } // Then prioritize those without currentWeekAssignments. if (!!a.currentWeekAssignments !== !!b.currentWeekAssignments) { return a.currentWeekAssignments ? 1 : -1; } // Prioritize those with fewer currentMonthAvailabilityHoursCount. if (a.currentMonthAvailabilityHoursCount !== b.currentMonthAvailabilityHoursCount) { return a.currentMonthAvailabilityHoursCount - b.currentMonthAvailabilityHoursCount; } // Finally, sort by (currentMonthAssignments - previousMonthAssignments). return (a.currentMonthAssignments - a.previousMonthAssignments) - (b.currentMonthAssignments - b.previousMonthAssignments); }); setAvailablePubs(sortedPubs); }; const handleSelectedPublisher = (publisher) => { // Do something with the selected publisher console.log("handle pub clicked:", publisher); } const handlePublisherModalOpen = async (publisher) => { // Do something with the selected publisher console.log("handle pub modal opened:", publisher.firstName + " " + publisher.lastName); let date = new Date(value); const { data: publisherInfo } = await axiosInstance.get(`/api/?action=getPublisherInfo&id=${publisher.id}&date=${common.getISODateOnly(date)}`); publisher.assignments = publisherInfo.assignments; publisher.availabilities = publisherInfo.availabilities; publisher.email = publisherInfo.email; setModalPub(publisher); setIsModalOpen(true); } // file uploads const [fileActionUrl, setFileActionUrl] = useState(''); const [file, setFile] = useState(null); const handleFileUpload = async (event) => { setIsOperationInProgress(true); console.log('handleFileUpload(): Selected file:', event.target.files[0], 'actionUrl:', fileActionUrl); setFile(event.target.files[0]); if (!event.target.files[0]) { toast.error('Моля, изберете файл!'); return; } uploadToServer(fileActionUrl, event.target.files[0]); }; const uploadToServer = async (actionUrl, file) => { const formData = new FormData(); formData.append('file', file); try { const response = await fetch('/' + actionUrl, { method: 'POST', body: formData, }); const result = await response.json(); if (result.fileId) { pollProgress(result.fileId); } console.log('Result from server-side API:', result); toast.info(result.message || "Файла е качен! Започна обработката на данните..."); } catch (error) { toast.error(error.message || "Възникна грешка при обработката на данните."); } finally { } }; const pollProgress = (fileId: any) => { fetch(`/api/upload?fileId=${fileId}`) .then(response => response.json()) .then(data => { updateProgressBar(data.progress); // Update the progress bar if (data.progress < 98 && data.progress > 0) { // Poll every second if progress is between 0 and 100 setTimeout(() => pollProgress(fileId), 1000); } else if (data.progress === 0) { // Handle error case toast.error("Възникна грешка при обработката на данните."); setIsOperationInProgress(false); } else { // Handle completion case toast.success("Файла беше обработен успешно!"); setIsOperationInProgress(false); } }) .catch(error => { console.error('Error polling for progress:', error); toast.error("Грешка при обновяването на напредъка"); setIsOperationInProgress(false) }) .finally(); }; const updateProgressBar = (progress: string) => { // Implement the logic to update your progress bar based on the 'progress' value // For example, updating the width of a progress bar element const progressBar = document.getElementById('progress-bar'); if (progressBar) { progressBar.style.width = progress + '%'; } }; function getEventClassname(event, allShifts, date) { if (event && allShifts) { const matchingShifts = allShifts.filter(shift => { const shiftDate = new Date(shift.startTime); return shift.cartEventId === event.id && shiftDate.getDate() === date.getDate() && shiftDate.getMonth() === date.getMonth(); }); //get matching shifts with assignments using nextcrud //const { data: withAss } = await axiosInstance.get(`/shifts?include=assignments&where={"id":{"$in":[${matchingShifts.map(shift => shift.id)}]}}`); const minCount = Math.min(...matchingShifts.map(shift => shift.assignedCount)) || 0; //const minCount = 4; //console.log("matchingShifts: " + matchingShifts) + " for date " + date; if (matchingShifts.length < 3) { return "text-gray"; } else { if (minCount === 0) return "text-red-700 font-bold "; if (minCount === 1) return "text-brown-900 font-bold "; if (minCount === 2) return "text-orange-500"; if (minCount === 3) return "text-yellow-500"; if (minCount >= 4) return "text-blue-500"; } } return "text-default"; // A default color in case none of the conditions are met. } const onTileContent = ({ date, view }) => { // Add your logic here var dayName = common.DaysOfWeekArray[date.getDayEuropean()]; var classname = ""; if (events == null) { return
{" "}
; } const event = events.find((event) => { return event.dayofweek == dayName; }); if (event != null) { const classname = getEventClassname(event, allShifts, date); return
{new Date(event.startTime).getHours() + "-" + new Date(event.endTime).getHours()}ч.
} return
{" "}
; }; const addAssignment = async (publisher, shiftId) => { try { console.log(`new assignment for publisher ${publisher.id} - ${publisher.firstName} ${publisher.lastName}`); const newAssignment = { publisher: { connect: { id: publisher.id } }, shift: { connect: { id: shiftId } }, isActive: true, isConfirmed: true }; const { data } = await axiosInstance.post("/api/data/assignments", newAssignment); // Update the 'publisher' property of the returned data with the full publisher object data.publisher = publisher; } catch (error) { console.error("Error adding assignment:", error); } }; const removeAssignment = async (publisher, shiftId) => { try { const assignment = publisher.assignments.find(ass => ass.shift.id === shiftId); console.log(`remove assignment for shift ${shiftId}`); const { data } = await axiosInstance.delete(`/api/data/assignments/${assignment.id}`); } catch (error) { console.error("Error removing assignment:", error); } } // ---------------------------------------------------------- // button handlers // ---------------------------------------------------------- const importShifts = async () => { try { setActiveButton("importShifts"); setIsOperationInProgress(true); let date = new Date(value); date.setDate(date.getDate() + 1); const dateString = common.getISODateOnly(date); const fileInput = document.getElementById('fileInput'); // setFileActionUrl(`readword/${dateString.slice(0, 4)}/${dateString.slice(5, 7)}/${dateString.slice(8, 10)}?action=import`); setFileActionUrl(`api/upload?action=readword&date=${dateString}`); console.log('fileaction set to ' + fileActionUrl); fileInput.click(); //handleFileUpload({ target: { files: [file] } }); fileInput.value = null; } catch (error) { toast.error(error); } finally { setIsOperationInProgress(false); setActiveButton(null); } } const fetchShifts = async () => { try { setActiveButton("fetchShifts"); // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}} const { data } = await axiosInstance.get(`/api/data/shifts?include=assignments.publisher&where={"startTime":{"$and":[{"$gte":"2022-12-04T15:09:47.768Z","$lt":"2022-12-10T15:09:47.768Z"}]}}`); setShifts(data); toast.success('Готово!', { autoClose: 1000 }); } catch (error) { console.log(error); } finally { setActiveButton(null); } } const generateShifts = async (buttonId, copyFromPrevious = false, autoFill = false, forDay?: Boolean | null) => { try { setActiveButton(buttonId); const endpoint = `/api/shiftgenerate?action=generate&date=${common.getISODateOnly(value)}©FromPreviousMonth=${copyFromPrevious}&autoFill=${autoFill}&forDay=${forDay}`; const { shifts } = await axiosInstance.get(endpoint); toast.success('Готово!', { autoClose: 1000 }); setIsMenuOpen(false); } catch (error) { console.log(error); } finally { setActiveButton(null); } } const deleteShifts = async (buttonId, forDay: Boolean) => { try { setActiveButton(buttonId); await axiosInstance.get(`/api/shiftgenerate?action=delete&date=${common.getISODateOnly(value)}&forDay=${forDay}`); toast.success('Готово!', { autoClose: 1000 }); setIsMenuOpen(false); } catch (error) { console.log(error); } finally { setActiveButton(null); } } const sendMails = async () => { try { var month = new Date(value).getMonth() + 1; // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}} const { data } = await axiosInstance.get(`/sendmails/${new Date(value).getFullYear()}/${month}`); } catch (error) { console.log(error); } } const generateXLS = async () => { try { var month = new Date(value).getMonth() + 1; // where:{"startTime":"$and":{{ "$gte": "2022-12-04T15:09:47.768Z", "$lt": "2022-12-10T15:09:47.768Z" }}} const { data } = await axiosInstance.get(`/generatexcel/${new Date(value).getFullYear()}/${month}/2`); } catch (error) { console.log(error); } } const generateDOCX = async () => { try { setActiveButton("generateDOCX"); var month = new Date(value).getMonth() + 1; const response = await axiosInstance.get(`/getDocxFile/${new Date(value).getFullYear()}/${month}`, { responseType: 'blob' }); const url = window.URL.createObjectURL(new Blob([response.data])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `График 2023.${month}.docx`); document.body.appendChild(link); link.click(); link.remove(); } catch (error) { console.log(error); } } //get all publishers and create txt file with their names, current and previous month assignments count (getPublisherInfo) // const generateMonthlyStatistics = async () => { try { var month = new Date(value).getMonth() + 1; let { data: allPublishersInfo } = await axiosInstance.get(`/api/?action=getMonthlyStatistics&date=${common.getISODateOnly(value)}`); //order by name and generate the list allPublishersInfo = allPublishersInfo.sort((a, b) => { if (a.firstName !== b.firstName) { return a.firstName < b.firstName ? -1 : 1; } if (a.lastName !== b.lastName) { return a.lastName < b.lastName ? -1 : 1; } return 0; }); var list = ""; allPublishersInfo.forEach(pub => { // list += `${pub.firstName} ${pub.lastName}\t ${pub.currentMonthAssignments} / ${pub.previousMonthAssignments}\n`; list += `${pub.firstName} ${pub.lastName}\t ${pub.currentMonthAssignments}\n`; }); //write to google sheets file //download the file const url = window.URL.createObjectURL(new Blob([list])); const link = document.createElement('a'); link.href = url; link.setAttribute('download', `Статистика 2023.${month}.txt`); document.body.appendChild(link); link.click(); link.remove(); } catch (error) { console.log(error); } } const togglePublished = async () => { try { const publishState = !isPublished; // Toggle the state const isPublishedParam = publishState ? 'true' : 'fasle'; await axiosInstance.get(`/api/?action=updateShifts&isPublished=${isPublishedParam}&date=${common.getISODateOnly(value)}`); setIsPublished(publishState); // Update state based on the action } catch (error) { console.log(error); } } const [isMenuOpen, setIsMenuOpen] = useState(false); const [isConfirmModalOpen, setConfirmModalOpen] = useState(false); async function copyOldAvailabilities(event: MouseEvent): Promise { await axiosInstance.get(`/api/?action=copyOldAvailabilities&date=${common.getISODateOnly(value)}`); } async function handleCreateNewShift(event: MouseEvent): Promise { //get last shift end time let lastShift = shifts.sort((a, b) => new Date(b.endTime).getTime() - new Date(a.endTime).getTime())[0]; //default to 9:00 if no shifts if (!lastShift) { //get cart event id var dayName = common.DaysOfWeekArray[value.getDayEuropean()]; const cartEvent = events.find(event => event.dayofweek == dayName); lastShift = { endTime: new Date(value.setHours(9, 0, 0, 0)), cartEventId: cartEvent.id }; } const lastShiftEndTime = new Date(lastShift.endTime); //add 90 minutes const newShiftEndTime = new Date(lastShiftEndTime.getTime() + 90 * 60000); await axiosInstance.post(`/api/data/shifts`, { name: "Нова смяна", startTime: lastShiftEndTime, endTime: newShiftEndTime, isPublished: false, cartEvent: { connect: { id: lastShift.cartEventId } } }).then((response) => { console.log("New shift created:", response.data); // setShifts([...shifts, response.data]); handleCalDateChange(value); } ).catch((error) => { console.error("Error creating new shift:", error); }); } return ( <> {/* Page Overlay */} {isOperationInProgress && (
)}
setConfirmModalOpen(false)} onConfirm={() => { toast.info("Потвърдено!", { autoClose: 2000 }); setConfirmModalOpen(false); sendMails() }} message="Това ще изпрати имейли до всички участници за смените им през избрания месец. Сигурни ли сте?" />
{isMenuOpen && (
{/* Group 1: Daily actions */}

)}
{/* progress bar holder */} {isOperationInProgress && (
)}
{/* Calendar section */}
{/* ------------------------------- PUBLISHERS LIST ---------------------------------- list of publishers for the selected date with availabilities ------------------AVAILABLE PUBLISHERS LIST FOR THE SELECTED DATE0 ------------------ */}

Достъпни за този ден: {availablePubs.length}

    {Array.isArray(availablePubs) && availablePubs?.map((pub, index) => { // Determine background and border classes based on conditions let bgAndBorderColorClass; if (pub.isAvailableForShift) { if (pub.currentDayAssignments === 0) { const comparisonResultClass = pub.currentMonthAvailabilityDaysCount < pub.previousMonthAssignments ? 'bg-green-100' : 'bg-green-50'; bgAndBorderColorClass = `${comparisonResultClass} border-l-4 border-green-400`; } else if (!pub.isSelected) { bgAndBorderColorClass = 'bg-orange-50 border-l-4 border-orange-400'; } } else { if (pub.isAvailableForShiftWithPrevious) // add left orange border { bgAndBorderColorClass = 'border-l-4 border-orange-400'; } else { bgAndBorderColorClass = 'bg-white'; } } //tOdO: CHECK WHY THIS IS NOT WORKING if (!pub.hasEverFilledForm) { //bgAndBorderColorClass = 'border-t-2 border-yellow-400'; } // Determine border class if selected const selectedBorderClass = pub.isSelected ? 'border-blue-400 border-b-4' : ''; // Determine opacity class const activeOpacityClass = pub.isActive ? '' : 'opacity-25'; return (
  • {pub.firstName} {pub.lastName} {pub.canTransport && ()}
    {pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0} {pub.currentWeekAssignments || 0} {pub.currentMonthAssignments || 0} {pub.previousMonthAssignments || 0}
  • ); })}
{/* Shift list section */}
{shifts.map((shift, index) => ( ))}
{/* */}
{isModalOpen && setIsModalOpen(false)} />}
); function PublisherShiftsModal({ publisher, shifts, onClose }) { const monthInfo = common.getMonthDatesInfo(new Date(value)); const monthShifts = shifts.filter(shift => { const shiftDate = new Date(shift.startTime); return shiftDate > monthInfo.firstDay && shiftDate < monthInfo.lastDay; }); const weekShifts = monthShifts.filter(shift => { const shiftDate = new Date(shift.startTime); return common.getStartOfWeek(value) <= shiftDate && shiftDate <= common.getEndOfWeek(value); }); const dayShifts = weekShifts.map(shift => { const isAvailable = publisher.availabilities.some(avail => avail.startTime <= shift.startTime && avail.endTime >= shift.endTime ); let color = isAvailable ? getColorForShift(shift) : 'bg-gray-300'; if (shift.isFromPreviousMonth) { color += ' border-l-4 border-orange-500 '; } if (shift.isFromPreviousAssignment) { color += ' border-l-4 border-red-500 '; } return { ...shift, isAvailable, color }; }).reduce((acc, shift) => { const dayIndex = new Date(shift.startTime).getDay(); acc[dayIndex] = acc[dayIndex] || []; acc[dayIndex].push(shift); return acc; }, {}); console.log("dayShifts:", dayShifts); const hasAssignment = (shiftId) => { // return publisher.assignments.some(ass => ass.shift.id == shiftId); return publisher.assignments.some(ass => { console.log(`Comparing: ${ass.shift.id} to ${shiftId}: ${ass.shift.id === shiftId}`); return ass.shift.id === shiftId; }); }; useEffect(() => { const handleKeyDown = (event) => { if (event.key === 'Escape') { console.log('ESC: closing modal.'); onClose(); // Call the onClose function when ESC key is pressed } }; // Add event listener window.addEventListener('keydown', handleKeyDown); // Remove event listener on cleanup return () => { window.removeEventListener('keydown', handleKeyDown); }; }, [onClose]); // Include onClose in the dependency array return (

График на {publisher.firstName} {publisher.lastName} {publisher.email} тази седмица:

{/* ... Display shifts in a calendar-like UI ... */}
{Object.entries(dayShifts).map(([dayIndex, shiftsForDay]) => (
{/* Day header */}
{new Date(shiftsForDay[0].startTime).getDate()}-ти
{shiftsForDay.map((shift, index) => { const assignmentExists = hasAssignment(shift.id); const availability = publisher.availabilities.find(avail => avail.startTime <= shift.startTime && avail.endTime >= shift.endTime ); const isFromPrevMonth = availability && availability.isFromPreviousMonth; return (
{common.getTimeRange(shift.startTime, shift.endTime)} {shift.id} {!assignmentExists && shift.isAvailable && ( )} {assignmentExists && ( )}
); } )}
))}
{/* Close button in the top right corner */} {/* */} {/* Edit button in the top right corner, next to the close button */}
); } function getColorForShift(shift) { const assignedCount = shift.assignedCount || 0; // Assuming each shift has an assignedCount property switch (assignedCount) { case 0: return 'bg-blue-300'; case 1: return 'bg-green-300'; case 2: return 'bg-yellow-300'; case 3: return 'bg-orange-300'; case 4: return 'bg-red-200'; default: return 'bg-gray-300'; } } } import axiosServer from '../../../src/axiosServer'; import { start } from 'repl'; import { filter } from 'jszip'; export const getServerSideProps = async (context) => { const axios = await axiosServer(context); // const baseUrl = common.getBaseUrl(); // console.log('runtime BaseUrl: ' + baseUrl); console.log('runtime NEXT_PUBLIC_PUBLIC_URL: ' + process.env.NEXT_PUBLIC_PUBLIC_URL); console.log('Runtime Axios Base URL:', axios.defaults.baseURL); const currentDate = new Date(); const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() - 3, 1); const lastDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0); // 0th day of the next month gives the last day of the current month const url = `/api/data/shifts?where={"startTime":{"$and":[{"$gte":"${common.getISODateOnly(firstDayOfMonth)}","$lt":"${common.getISODateOnly(lastDayOfMonth)}"}]}}`; const prismaClient = common.getPrismaClient(); const { data: events } = await axios.get(`/api/data/cartevents?where={"isActive":true}`); //const { data: shifts } = await axios.get(url); // get all shifts for the month, including assigments let shifts = await prismaClient.shift.findMany({ where: { isActive: true, startTime: { gte: firstDayOfMonth, //lt: lastDayOfMonth } }, include: { assignments: { include: { publisher: { select: { id: true, } } } } } }); //calculate assCount for each shift shifts = shifts.map(shift => ({ ...shift, assignedCount: shift.assignments.length, startTime: shift.startTime.toISOString(), endTime: shift.endTime.toISOString(), })); return { props: { initialEvents: events, initialShifts: shifts, }, }; }