Untitled
unknown
plain_text
2 years ago
17 kB
11
Indexable
import { useState, useEffect } from "react"; import axios from "axios"; import FullCalendar, { formatDate } from "@fullcalendar/react"; import dayGridPlugin from "@fullcalendar/daygrid"; import PlusIcon from "@heroicons/react/24/solid/PlusIcon"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; import resourceTimelinePlugin from '@fullcalendar/resource-timeline'; import { useNavigate, useParams } from "react-router-dom"; import { Button, Container, Stack, SvgIcon, duration } from "@mui/material"; import listPlugin from "@fullcalendar/list"; import { ToastContainer, toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import { startOfMonth, set, formatISO, addHours } from "date-fns"; import { utcToZonedTime } from "date-fns-tz"; import { parse, format } from "date-fns"; import Timeline from 'react-calendar-timeline' // make sure you include the timeline stylesheet or the timeline will not be styled import 'react-calendar-timeline/lib/Timeline.css' import moment from 'moment' import { Box, List, ListItem, ListItemText, Typography, useTheme, } from "@mui/material"; import Header from "../../components/Header"; import { tokens } from "../../theme"; import { number } from "yup"; const Calendar = () => { const theme = useTheme(); const navigate = useNavigate(); const colors = tokens(theme.palette.mode); const [currentEvents, setCurrentEvents] = useState([]); const [data, setData] = useState([]); const [leaves, setLeaves] = useState([]); const [shifts, setShifts] = useState([]); const [names, setNames] = useState([]); const [heads, setHead] = useState([]); const updatedMonitorArray = []; const [userMonitorData, setUserMonitorData] = useState([]); let ids = new Set(); const array = [3]; useState(""); const notify = () => toast("Wow so easy!"); const [usershift, setuserShift] = useState([]); useEffect(() => { axios .get("http://localhost:5000/getheads") .then((res) => { if (res.status === 200) { setHead(res.data); console.log(res.data); } else { alert("Error"); } }) .catch((err) => console.log(err)); }, []); const fetchDataAndSetState = () => { axios .get("http://localhost:5000/userstiming") .then((res) => { if (res.status === 200) { setData(res.data); // console.log("Hitest", res.data); } else { alert("Error"); } }) .catch((err) => console.log(err)); }; const fetchUserShift = () => { axios .get("http://localhost:5000/usershift") .then((res) => { if (res.status === 200) { setuserShift(res.data); } else { alert("Error"); } }) .catch((err) => console.log(err)); }; useEffect(() => { const namesArray = data.map((item) => { // Extract the 'start' and 'end' values from each 'usershifts' item const shifts = item.usershifts.map((shift) => ({ id: shift.id, name: item.name, start: shift.start.replace("T", " ").replace("Z", ""), end: shift.end.replace("T", " ").replace("Z", ""), })); // Return the shifts for this item return shifts; }); // Flatten the array of arrays into a single array const flattenedArray = namesArray.flat(); setNames(flattenedArray); }, [data]); useEffect(() => { // Create the initial events using 'names' once it's available const initialEvents = names.map((item) => ({ id: item.id, title: item.name, start: item.start, end: item.end, // You can set the date as needed })); // Set the initial events in state setCurrentEvents(initialEvents); }, [names]); useEffect(() => { fetchDataAndSetState(); fetchUserShift(); }, []); const handleDateClick = (selected) => { const title = prompt("Please enter a new title for your event"); const calendarApi = selected.view.calendar; calendarApi.unselect(); if (title) { calendarApi.addEvent({ id: `${selected.dateStr}-${title}`, title, start: selected.startStr, end: selected.endStr, allDay: selected.allDay, }); } }; const handleEventClick = (selected) => { if ( window.confirm( `Are you sure you want to delete the event '${selected.event.title}'` ) ) { selected.event.remove(); } }; var date = new Date(); //Shift Api useEffect(() => { axios .get("http://localhost:5000/getshifts/") .then((res) => { if (res.status === 200) { setShifts(res.data); } else { alert("Error"); } }) .catch((err) => console.log(err)); }, []); //Leave Api useEffect(() => { axios .get("http://localhost:5000/getleave") .then((res) => { if (res.status === 200) { setLeaves(res.data); } else { alert("Error"); } }) .catch((err) => console.log(err)); }, []); //Leave const userHasLeaveOnDate = (userId, checkDate) => { const leaveOnDate = leaves.find((leave) => { // Parse the original date string const parsedDate = parse(leave.start, "EEEE do MMMM yyyy h:mma", new Date()); // Format the parsed date to only include the date part const formattedDate = format(parsedDate, "yyyy-MM-dd"); // Format checkDate to only include the date part // const formattedCheckDate = format(checkDate, "yyyy-MM-dd"); const formattedCheckDate = checkDate.substring(0, 10); if(leave.userId == userId && formattedDate == formattedCheckDate){ } return ( leave.userId === userId && formattedDate === formattedCheckDate ); }); return leaveOnDate !== undefined; }; //Random function getRandomDate(date, start) { date.setUTCHours(start, 0, 0, 0); return date; } //SCHEDULES function schedule(date, duration) { var initialDate = new Date(date); initialDate.setHours(initialDate.getHours() + duration); var newDateString = initialDate.toString(); return newDateString; } //end function convertDateFormat(inputDate) { const date = new Date(inputDate); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, "0"); // Month is zero-based const day = String(date.getDate()).padStart(2, "0"); const hours = String(date.getHours()).padStart(2, "0"); // Set the minutes to 0 const minutes = "00"; // Return the formatted date string return `${year}-${month}-${day} ${hours}:${minutes}:00`; } function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; } const getUserHoursWorked = (userId, duration) => { const userMonitorIndex = updatedMonitorArray.findIndex( (entry) => entry.userId === userId ); // If the user is in the array, update the worked hours and return if (userMonitorIndex !== -1) { const userMonitorEntry = updatedMonitorArray[userMonitorIndex]; // Subtract the worked hours from the initial total hours const remainingHours = userMonitorEntry.hoursworked - duration; // Update the hoursworked for the existing entry in updatedMonitorArray updatedMonitorArray[userMonitorIndex].hoursworked = remainingHours < 0 ? 0 : remainingHours; return remainingHours < 0 ? 0 : remainingHours; } // If the user is not in the array, calculate the initial total hours const userTotalHours = 160; // Subtract the worked hours from the initial total hours const remainingHours = userTotalHours - duration; // Create a new entry for the user and add it to the updatedMonitorArray updatedMonitorArray.push({ userId: userId, hoursworked: remainingHours < 0 ? 0 : remainingHours, }); // Return the remaining hours return remainingHours < 0 ? 0 : remainingHours; }; var hours; const assignedShiftsForDay = new Set(); // //USERMONITOR // const updatedmonitor = { // userId: id, // name: shiftname, // start: start, // hoursworked: duration, // }; const handleSubmits = (datas, start, duration, maxcust, date, shiftname, roleId, maxrole ) => {//pass in 2ic id here also, if not then value would be null let count = 0; const randomDate = getRandomDate(date, start); const shuffledIds = shuffleArray(data.map((item) => item.id)); const before = convertDateFormat(randomDate); shuffledIds.forEach((id) => { if ( count < maxcust && !assignedShiftsForDay.has(id) && !userHasLeaveOnDate(id, before) //if cc_id exists --> generate for that day ) { if(getUserHoursWorked(id, duration) > 0){ assignedShiftsForDay.add(id); const schedules = schedule(randomDate, duration); const before = convertDateFormat(randomDate); const after = convertDateFormat(schedules); //USERSHIFT const updatedDate = { start: before, end: after, shiftId: datas, userId: id, }; axios .post("http://localhost:5000/userposttiming/" + datas, updatedDate) .then( (response) => { if (response.status === 200) { fetchDataAndSetState(); // navigate("/calendar"); } } ) .catch((err) => console.log(err)); count++; if (count >= maxcust) { return; } } } }); // if(roleId !== null){ // console.log("YASSSSSS for", roleId); // heads.forEach((head) => { // // if (head.roleId === roleId) { // // console.log("Matching head found! Head ID:", head.roleId); // // const schedules = schedule(randomDate, duration); // // const before = convertDateFormat(randomDate); // // const after = convertDateFormat(schedules); // // console.log("HEAD TIME", before, after, datas, head.roleId); // // //USERSHIFT // // // const updatedRoleDate = { // // // start: before, // // // end: after, // // // shiftId: datas, // // // userId: head.id, // // // }; // // // axios // // // .post("http://localhost:5000/userposttiming/" + datas, updatedRoleDate) // // // .then( // // // (response) => { // // // if (response.status === 200) { // // // fetchDataAndSetState(); // // // // navigate("/calendar"); // // // } // // // } // // // ) // // // .catch((err) => console.log(err)); // // } // }); // } //if statement , 2ic exists takes that id and name and pass in updated monitor 2IC (if not then 2ic NULL) //if roles exists then data.map with the role one and choose the name. //and one of the 2ic to put there random... //take the users data and check where the id falls //runs shuffleids on that // // //2ic ... //add extra 2ic there // }; const showConfirmation = () => { if (window.confirm("Confirm generating new schedule for employees?")) { // User pressed OK, call handleSubmits const totalShifts = shifts.length; const date = new Date(); // Get the current date and time const year = date.getFullYear(); const month = date.getMonth(); const totalDays = new Date(year, month + 1, 0).getDate(); const addedDates = new Set(); let i = 1; while (i <= totalDays) { //I <= TOTAL DAYS IN THE MONTHS assignedShiftsForDay.clear(); date.setDate( Math.floor(Math.random() * new Date(year, month + 1, 0).getDate()) + 1 ); if (!addedDates.has(date.toDateString())) { addedDates.add(date.toDateString()); shifts.map((item) => handleSubmits( item.id, item.start, item.duration, item.maxcust, date, item.name, item.roleId, item.maxrole, ) ); i++; } } //While i < alltotalshifts // } else { // User canceled, you can handle this case if needed // For example, show a different message or take other actions } }; const showConfirmationReset = () => { if (window.confirm("Confirm Deletion of Shifts?")) { // User pressed OK, call handleSubmits deleteShift(); fetchDataAndSetState(); // fetchUserShift(); } else { // User canceled, you can handle this case if needed // For example, show a different message or take other actions } }; const deleteShift = () => { // Get the current date const currentDate = new Date(); // Get the first day of the current month const firstDayOfMonth = startOfMonth(currentDate); // Set the time to 7 AM const startTime = set(firstDayOfMonth, { hours: 7, minutes: 0, seconds: 0, milliseconds: 0, }); // Adjust for daylight saving time const adjustedTime = addHours( startTime, new Date().getTimezoneOffset() / 60 ); // Format the date in the required format (2023-11-01T07:00:00.000Z) const formattedDate = formatISO(adjustedTime); // Make the DELETE request with the formatted date as a parameter axios .delete(`http://localhost:5000/deleteshifts/${formattedDate}`) .then((response) => { if (response.status === 200) { // Assuming fetchDataAndSetState is a function that updates your React component's state fetchDataAndSetState(); // Assuming navigate is a function for navigation // navigate("/calendar"); } }) .catch((err) => console.log(err)); }; return ( <Box m="20px"> <Header title="Calendar" subtitle="Generate and View Schedules" /> <div style={{ marginBottom: 10 }}> <Button onClick={showConfirmation} startIcon={ <SvgIcon fontSize="small"> <PlusIcon /> </SvgIcon> } variant="contained" color="secondary" > Generate </Button> <Button style={{ marginLeft: 5 }} onClick={showConfirmationReset} startIcon={ <SvgIcon fontSize="small"> <PlusIcon /> </SvgIcon> } variant="contained" color="error" > Reset </Button> </div> <Box display="flex" justifyContent="space-between"> {/* CALENDAR SIDEBAR */} <Box flex="1 1 20%" backgroundColor={colors.primary[400]} p="15px" borderRadius="4px" > <Typography variant="h5">Events</Typography> <List> {currentEvents.map((event) => ( <ListItem key={event.id} sx={{ backgroundColor: colors.greenAccent[500], margin: "10px 0", borderRadius: "2px", }} > <ListItemText primary={event.title} secondary={ <Typography> {formatDate(event.start, { year: "numeric", month: "short", day: "numeric", })} </Typography> } /> </ListItem> ))} </List> </Box> {/* CALENDAR */} <Box flex="1 1 100%" ml="15px"> <FullCalendar height="75vh" plugins={[ dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin, ]} headerToolbar={{ left: "prev,next today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay,listMonth", }} initialView="dayGridWeek" editable={true} selectable={true} selectMirror={true} dayMaxEvents={true} select={handleDateClick} eventClick={handleEventClick} events={currentEvents} /> </Box> </Box> </Box> ); }; export default Calendar;
Editor is loading...
Leave a Comment