Untitled
unknown
plain_text
2 years ago
17 kB
14
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