Untitled

 avatar
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