UNPKG

glide-design-system

Version:

Glide design system is an open-source React component library. It offers numerous benefits that make them essential tools for design and development teams.

449 lines (402 loc) 16 kB
import React, { useState, useRef, useContext, useEffect } from "react"; import dayjs from "dayjs"; import styles from "./DayView.module.css"; import EventForm from "./EventForm"; import EventDescrption from "./EventDescrption"; import { EventsContext } from "./Scheduler"; function DayView({ selectedDate, timeRange, setStartTime, setEndTime, formOpen, setFormOpen, descriptionStyle, tableCellStyle, setUpdateData, edit, eventDescription, setEventDescrption, events, width, }) { const tableContainerRef = useRef(null); const localEvents = useContext(EventsContext); const [selectedRows, setSelectedRows] = useState([]); const isMouseDown = useRef(false); const [startEvent, setStartEvent] = useState(); const [endEvent, setEndEvent] = useState(); const [updateEvents, setUpdateEvents] = useState(); const [eventDescriptionPosition, setEventDescriptionPosition] = useState({ top: 0, left: 0, }); const startDate = new Date(2023, 10, 16, 10, 0); const handleMouseDown = (startRow) => { localEvents?.map((data) => { if (startEvent === undefined && endEvent === undefined) { const endHour = data?.endDate.getHours(); const startTime = new Date(); if (startRow === endHour) { startTime.setHours(startRow, 0 + 1, 0, 0); } else { startTime.setHours(startRow - 1, 0, 0, 0); } const endTime = new Date(); endTime.setHours(startRow, 0, 0, 0); if (endTime.getHours() === 0) { endTime.setHours(startRow, 0 - 1, 0, 0); } else { endTime.setHours(startRow, 0, 0, 0); } setStartEvent(startTime); setEndEvent(endTime); setStartTime(startTime); setEndTime(endTime); } }); isMouseDown.current = true; setSelectedRows([startRow]); }; const handleMouseMove = (currentRow) => { if (isMouseDown.current && edit !== false) { const startRow = selectedRows[0]; const endRow = currentRow; const min = Math.min(startRow, endRow); const max = Math.max(startRow, endRow); const isOverlapping = localEvents.some((event) => { const eventStartRow = event.startDate.getHours(); const eventEndRow = event.endDate.getHours(); return ( (min <= eventEndRow && max >= eventStartRow) || (startRow <= eventEndRow && endRow >= eventStartRow) ); }); if (!isOverlapping) { const range = Array.from({ length: max - min + 1 }, (_, i) => min + i); setSelectedRows(range); const time1 = range[0]; const time2 = range[range.length - 1]; const startTime = new Date(); startTime.setHours(time1 - 1, 0, 0, 0); const endTime = new Date(); endTime.setHours(time2 - 1 + 1, 0, 0, 0); setUpdateData(""); setStartEvent(startTime); setEndEvent(endTime); setStartTime(startTime); setEndTime(endTime); } } }; const handleMouseUp = () => { isMouseDown.current = false; if (selectedRows.length > 0 && startEvent && endEvent) { openEventForm(); } }; const renderTime = (hour, minute) => { const amPm = hour < 12 ? "AM" : "PM"; // Change formattedHour calculation to handle 12 AM as 11 PM and other hours accordingly const formattedHour = hour % 12 === 0 ? 11 : (hour % 12) - 1; const formattedMinute = minute < 10 ? `0${minute}` : minute; return `${ formattedHour === 0 ? 12 : formattedHour }:${formattedMinute} ${amPm}`; }; const openEventForm = () => { setFormOpen(edit !== false ? true : false); }; const cancelHandler = () => { setFormOpen(false); setStartEvent(undefined); setEndEvent(undefined); }; const hours = Array.from({ length: 24 }, (_, index) => index + 1); const formatTime = (startDate, endDate) => { const hours = startDate.getHours(); const minutes = startDate.getMinutes(); const ampm = hours >= 12 ? "PM" : "AM"; const formattedHours = hours % 12 || 12; // Convert 0 to 12 const hours2 = endDate.getHours(); const minutes2 = endDate.getMinutes(); const ampm2 = hours2 >= 12 ? "PM" : "AM"; const formattedHours2 = hours2 % 12 || 12; // Convert 0 to 12 return `${formattedHours}:${minutes .toString() .padStart(2, "0")} ${ampm}-${formattedHours2}:${minutes2 .toString() .padStart(2, "0")} ${ampm2}`; }; const openDescription = (data, event) => { setFormOpen(false); setUpdateEvents(data); setUpdateData(data); const cell = event.currentTarget.getBoundingClientRect(); setEventDescriptionPosition({ top: cell.top + window.scrollY, left: cell.left + window.scrollX, }); setEventDescrption(!eventDescription); }; const closeDescrption = () => { setEventDescrption(false); }; useEffect(() => { const handleOutsideClick = (event) => { if ( tableContainerRef.current && !tableContainerRef.current.contains(event.target) ) { setSelectedRows([]); setStartEvent(undefined); setEndEvent(undefined); } }; document.addEventListener("mousedown", handleOutsideClick); return () => { document.removeEventListener("mousedown", handleOutsideClick); }; }, []); return ( <div className={styles.tableVviewContainer} style={{ minWidth: "400px", marginTop: "20px" }} ref={tableContainerRef} > {hours?.map((hour) => { const isEventRowStart = localEvents.some( (event) => hour === startDate?.getHours() + 1 ); return ( <div key={hour} style={{ height: "60px" }} className={`${styles.tableRow} ${ selectedRows.includes(hour) ? "selected" : "" }`} onMouseDown={() => handleMouseDown(hour)} onMouseMove={() => handleMouseMove(hour)} onMouseUp={handleMouseUp} > <div style={{ width: "80px", height: "60px", borderRight: "1px solid #DDD", }} > {renderTime(hour, 0)} </div> <div className={`${styles.eventCell} ${ isEventRowStart ? "has-event" : "" } ${selectedRows.includes(hour) ? styles.eventCellSelected : ""}`} style={{ width: "100%", height: "100%" }} > {localEvents?.map((event) => { const eventStartTime = event?.startDate; const eventEndTime = event?.endDate; const eventStartHour = eventStartTime?.getHours() + 1; const eventStartMinutes = eventStartTime?.getMinutes(); const eventEndHour = eventEndTime?.getHours() + 1; const eventEndMinutes = eventEndTime?.getMinutes(); const eventStartDate = event.startDate; const eventEndDate = event.endDate; var startDateString = eventStartDate; var startingDate = new Date(startDateString); startingDate.setMonth(startingDate.getMonth()); var endDateString = eventEndDate; var endingDate = new Date(endDateString); endingDate.setMonth(endingDate.getMonth()); const eventDateMatches = dayjs(startingDate).isSame(selectedDate, "day") && dayjs(endingDate).isSame(selectedDate, "day"); const eventYearMonthMatches = dayjs(startingDate).isSame(selectedDate, "year") && dayjs(startingDate).isSame(selectedDate, "month"); const eventStartRow = eventStartTime; const eventEndTimes = eventEndDate?.getHours() - 7; const eventEndRow = eventEndTimes; if (eventDateMatches && eventYearMonthMatches) { const start = eventStartDate?.getHours(); const end = eventEndDate.getHours(); const startMinutes = eventStartDate.getMinutes(); const endMinutes = eventEndDate.getMinutes(); const topPercent = (startMinutes / 60) * 100; const differenceHr = end - start; let eventStartTimes = start === 0 && end === 0 ? eventStartDate?.getHours() + 1 : eventStartDate?.getHours() + 1; let eventEndTime = start === 0 && end === 0 ? eventEndDate?.getHours() - 1 - 7 : eventEndDate?.getHours() - 7; const startTime = new Date(eventStartDate); // End time const endTime = new Date(eventEndDate); // Calculate the difference in milliseconds const timeDifference = endTime - startTime; // Convert the difference to minutes const totalMinutes = timeDifference / (1000 * 60); const hours = Math.floor(totalMinutes / 60); const minutes = Math.floor(totalMinutes % 60); const formattedTimeDiifrence = `${hours}h ${minutes}m`; if (hour === eventStartTimes && differenceHr < 1) { const heightPercentage = (((eventEndHour - eventStartHour) * 60 + eventEndMinutes - eventStartMinutes) / 60) * 100; return ( <div style={{ width: "99.5%", position: "relative" }}> <div style={{ width: "100%", height: "60px", overflow: "hidden", color: event?.color ? event?.color : "white", borderRadius: "5px", position: "absolute", }} > {differenceHr < 1 && ( <div onClick={(events) => { openDescription(event, events); }} style={{ width: "99.2%", display: "flex", alignItems: "center", borderRadius: "5px", height: `${heightPercentage}%`, top: `${topPercent}%`, marginLeft: "5px", position: "absolute", backgroundColor: event?.backgroundColor ? event?.backgroundColor : "#0a5b99", color: event?.color ? event?.color : "white", }} > <div style={{ marginLeft: "5px" }}> {" "} {`${event.eventName} - `} </div> <div style={{ marginLeft: "3px" }}> {`${formatTime( eventStartDate, eventEndDate )} - `} </div> <div style={{ marginLeft: "3px" }}> {`(${formattedTimeDiifrence})`} </div> </div> )} </div> </div> ); } if ( (eventStartHour < hour || (eventStartHour === hour && eventStartMinutes < 0)) && (eventEndHour > hour || eventEndHour === hour) ) { const eventTop = (((eventStartHour - hour) * 60 + eventStartMinutes) / 60) * 100; const eventHeight = (((eventEndHour - eventStartHour) * 60 + eventEndMinutes - eventStartMinutes) / 60) * 100; return ( <div style={{ width: "99.5%", position: "relative" }}> <div key={event.eventName} style={{ height: "60px", width: "100%", position: "absolute", borderRadius: "5px", }} > <div style={{ position: "absolute", top: `${eventTop}%`, height: `${eventHeight}%`, width: "99.2%", marginLeft: "5px", display: totalMinutes < 60 ? "flex" : "", alignItems: totalMinutes < 60 && "center", backgroundColor: event?.backgroundColor ? event?.backgroundColor : "#0a5b99", color: event?.color ? event?.color : "white", borderRadius: "5px", }} onClick={(events) => { openDescription(event, events); }} > {totalMinutes > 59 ? ( <div style={{ marginLeft: "5px" }}> {`${event.eventName}`} </div> ) : ( <div style={{ marginLeft: "5px" }}> {`${event.eventName} - `} </div> )} <div style={{ display: "flex", marginLeft: "5px" }}> <div> {`${formatTime( eventStartDate, eventEndDate )} - `} </div> <div style={{ marginLeft: "3px" }}> {`(${formattedTimeDiifrence})`} </div> </div> </div> </div> </div> ); } else { return null; } } })} </div> </div> ); })} {eventDescription && ( <EventDescrption closeDescrption={closeDescrption} datas={updateEvents} descriptionStyle={descriptionStyle} position={eventDescriptionPosition} setFormOpen={setFormOpen} formOpen={formOpen} /> )} {formOpen && ( <EventForm cancelModal={cancelHandler} setSelectedRows={setSelectedRows} datas={updateEvents} /> )} </div> ); } export default DayView;