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
JavaScript
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;