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.
295 lines (276 loc) • 9.6 kB
JavaScript
import React, { useState, useRef, useContext, useEffect } from "react";
import styles from "./WeekView.module.css";
import { EventsContext } from "./Scheduler";
import EventForm from "./EventForm";
import EventDescrption from "./EventDescrption";
function WeekView({
selectedDate,
onEventsSubmit,
setUpdateData,
setStartTime,
setEndTime,
onEventDelete,
descriptionStyle,
timeRange,
formOpen,
setFormOpen,
}) {
const localEvents = useContext(EventsContext);
const mouseDown = useRef(false);
const initialDateTimeRef = useRef({
date: new Date(selectedDate),
timeIndex: null,
});
const [weekStart, setWeekStart] = useState(new Date(selectedDate));
const [startEvent, setStartEvent] = useState(null);
const [endEvent, setEndEvent] = useState(null);
const [selectedCells, setSelectedCells] = useState([]);
const [updateEvents, setUpdateEvents] = useState();
const [eventDescription, setEventDescrption] = useState(false);
const [eventDescriptionPosition, setEventDescriptionPosition] = useState({
top: 0,
left: 0,
});
const generateDates = () => {
const dates = [];
for (let i = 0; i < 7; i++) {
const currentDate = new Date(weekStart);
currentDate.setDate(weekStart.getDate() + i);
const formattedDate = `${currentDate.getDate()} ${currentDate.toLocaleString(
"default",
{ month: "short" }
)}`;
dates.push(formattedDate);
}
return dates;
};
const mouseDownHandler = (timeIndex, date) => {
mouseDown.current = true;
if (startEvent === undefined && endEvent === undefined) {
const startTime = new Date();
startTime.setHours(timeIndex + 7, 0, 0, 0);
const endTime = new Date();
endTime.setHours(timeIndex + 7 + 1, 0, 0, 0);
setStartEvent(startTime);
setEndEvent(endTime);
setStartTime(startTime);
setEndTime(endTime);
} else {
const startTime = new Date();
startTime.setHours(timeIndex + 7, 0, 0, 0);
setStartEvent(undefined);
setEndEvent(undefined);
}
initialDateTimeRef.current = { date: new Date(date), timeIndex };
setSelectedCells([{ timeIndex, date }]);
};
const cancelEventFormModal = () => {
setFormOpen(false);
setStartEvent(undefined);
setEndEvent(undefined);
};
const submitEventForm = () => {
setFormOpen(false);
setStartEvent(undefined);
setEndEvent(undefined);
onEventsSubmit();
};
const mouseMoveHandler = (timeIndex, date) => {
if (mouseDown.current) {
const startRow = initialDateTimeRef.current.timeIndex;
const endRow = timeIndex;
const min = Math.min(startRow, endRow);
const max = Math.max(startRow, endRow);
const range = Array.from({ length: max - min + 1 }, (_, i) => min + i);
const newSelectedCells = range.map((index) => ({
timeIndex: index,
date,
}));
setSelectedCells(newSelectedCells);
const time1 = range[0] + 7;
const time2 = range[range.length - 1] + 7;
const startDate = new Date(initialDateTimeRef.current.date);
startDate.setHours(time1, 0, 0, 0);
const endDate = new Date(date);
endDate.setHours(time2 + 1, 0, 0, 0);
setStartEvent(startDate);
setEndEvent(endDate);
setStartTime(startDate);
setEndTime(endDate);
}
};
const mouseUpHandler = () => {
mouseDown.current = false;
if (selectedCells.length > 0 && startEvent && endEvent) {
openEventFormHandler();
}
};
const openEventFormHandler = () => {
setFormOpen(true);
};
const renderDateColumns = () => {
const dates = generateDates();
return dates.map((date, index) => (
<th style={{ border: "1px solid #DDD" }} key={index}>
{date}
</th>
));
};
const openDescription = (data, event) => {
setFormOpen(false);
setUpdateEvents(data);
const cell = event.currentTarget.getBoundingClientRect();
setEventDescriptionPosition({
top: cell.top + window.scrollY,
left: cell.left + window.scrollX,
});
setEventDescrption(!eventDescription);
};
const closeDescrption = () => {
setEventDescrption(false);
};
const deleteEvent = () => {
onEventDelete();
setEventDescrption(false);
};
useEffect(() => {
const startDate = selectedDate[0];
setWeekStart(new Date(startDate));
}, [selectedDate]);
const formatTime = (startDate, endDate) => {
const options = { hour: "numeric", minute: "numeric" };
return `${startDate?.toLocaleTimeString(
[],
options
)} - ${endDate?.toLocaleTimeString([], options)}`;
};
const renderTimeRows = () => {
return Array.from(
{ length: timeRange ? timeRange : 16 },
(_, timeIndex) => {
const time = (timeIndex + 7).toFixed(2).replace(".", ":");
return (
<tr key={timeIndex}>
<td className="tableData" style={{ border: "1px solid #DDD" }}>
<div style={{ textAlign: "center" }}>{time}</div>
</td>
{generateDates().map((date, dateIndex) => {
const cellDate = new Date(weekStart);
cellDate.setDate(weekStart.getDate() + dateIndex);
const eventsForCell = localEvents.filter(
(event) =>
event.startDate.getDate() === cellDate.getDate() &&
event.startDate.getMonth() === cellDate.getMonth() + 1 &&
event.startDate.getFullYear() === cellDate.getFullYear() &&
event.startDate.getHours() === timeIndex + 7
);
const eventsForCells = localEvents.filter(
(event) =>
event.startDate.getDate() === cellDate.getDate() &&
event.startDate.getMonth() === cellDate.getMonth() + 1 &&
event.startDate.getFullYear() === cellDate.getFullYear() &&
event.startDate.getHours() <= timeIndex + 7 - 1 &&
event.endDate.getHours() >= timeIndex + 7 + 1
);
const isSelectedCell = selectedCells.some(
(selectedCell) =>
selectedCell.timeIndex === timeIndex &&
selectedCell.date.getDate() === cellDate.getDate()
);
const hasEvents =
eventsForCell.length > 0 || eventsForCells.length > 0;
return (
<td
style={{
maxWidth: "50px",
position: "relative",
border: hasEvents ? "none" : "1px solid #ddd",
}}
key={dateIndex}
onMouseUp={mouseUpHandler}
onMouseMove={() => mouseMoveHandler(timeIndex, cellDate)}
onMouseDown={() => mouseDownHandler(timeIndex, cellDate)}
className={`tableData ${
isSelectedCell ? styles.eventCellSelected : ""
}`}>
{eventsForCell.map((event, index) => (
<div
style={{
backgroundColor: event?.backgroundColor
? event?.backgroundColor
: "#0a5b99",
color: "white",
}}
className={styles.eventsList}
onClick={(events) => {
openDescription(event, events);
}}>
<div className={styles.eventName}> {event.eventName}</div>
<div> {formatTime(event?.startDate, event?.endDate)}</div>
</div>
))}
{eventsForCells.map((event) => (
<div
key={event.id}
style={{
borderRadius: "5px",
}}
onClick={(events) => {
openDescription(event, events);
}}>
<div
style={{
backgroundColor: event?.backgroundColor
? event?.backgroundColor
: "#0a5b99",
height: "60px",
paddingBottom: "1px",
cursor: "pointer",
}}></div>
</div>
))}
</td>
);
})}
</tr>
);
}
);
};
return (
<div>
<div className={styles.eventsContainers}>
<table border="0">
<thead>
<tr>
<th style={{ border: "1px solid #DDD" }}>Time</th>
{renderDateColumns()}
</tr>
</thead>
<tbody>{renderTimeRows()}</tbody>
</table>
</div>
{formOpen && (
<EventForm
cancelModal={cancelEventFormModal}
setUpdateData={setUpdateData}
submitForm={submitEventForm}
/>
)}
{eventDescription && (
<EventDescrption
closeDescrption={closeDescrption}
datas={updateEvents}
position={eventDescriptionPosition}
submitForm={submitEventForm}
setUpdateData={setUpdateData}
onEventDelete={deleteEvent}
descriptionStyle={descriptionStyle}
setFormOpen={setFormOpen}
formOpen={formOpen}
/>
)}
</div>
);
}
export default WeekView;