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.

295 lines (276 loc) 9.6 kB
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;