import React from 'react'; import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; import timeGridPlugin from '@fullcalendar/timegrid'; import interaction from '@fullcalendar/interaction'; import scrollGrid from '@fullcalendar/scrollgrid'; import { DateTime } from 'luxon'; import { Icon, IconButton } from 'rsuite'; // FullCalendar props const dayMinWidth = 110; export default function IntervalSelector({ selectedDates, handleSelect, availability, setAvailability, slotMinTime, slotMaxTime, }) { /// DATES DISPLAY let startDate = selectedDates[0].start; // create a Datetime object from the last event date, // add one day, and change it to a date string let lastEventDate = selectedDates[selectedDates.length - 1].start; let endDate = DateTime.fromFormat(lastEventDate, 'yyyy-MM-dd') .plus({ days: 1 }) .toFormat('yyyy-MM-dd'); // Create an event dates list used to create the days columns const daysList = selectedDates.map((event) => event.start); const handleDayDidMount = (info) => { let currentDate = DateTime.fromJSDate(info.date).toFormat('yyyy-MM-dd'); if (!daysList.includes(currentDate)) { info.el.remove(); } }; const handleViewMount = ({ el }) => { // Adapt column width to number of dates present const timegridBody = el.querySelectorAll('div.fc-timegrid-body'); const timegridSlots = el.querySelectorAll( 'div.fc-timegrid-slots table', ); // Update width based on rendered dates number let newWidth = daysList.length * dayMinWidth; timegridBody[0].style['min-width'] = `${newWidth}px`; timegridSlots[0].style['min-width'] = `${newWidth}px`; }; /// AVAILABILITY INTERACTION const handleClick = (eventStart, eventEnd) => { let updatedAvailability = []; // Create an event object to compare let currentAvailability = { start: eventStart, end: eventEnd, }; // Make it to JSON let currentAvJson = JSON.stringify(currentAvailability); // Create an array of stringified availability let avListJson = availability.map((event) => { delete event['id']; return JSON.stringify(event); }); // Check if there's a similar event obj in the availability let index = avListJson.findIndex( (availability) => currentAvJson === availability, ); // Remove event from availability at index if (index > -1) { updatedAvailability = [...availability]; updatedAvailability.splice(index, 1); } setAvailability([...updatedAvailability]); }; const handleContent = ({ event }) => { let eventStart = event.start; let eventEnd = event.end; let evStartDT = DateTime.fromJSDate(eventStart); let evEndDT = DateTime.fromJSDate(eventEnd); return ( <>

{evStartDT.toFormat('HH:mm')} -{' '} {evEndDT.toFormat('HH:mm')}

} appearance='default' size='xs' circle onClick={() => handleClick(eventStart, eventEnd)} >
); }; return ( handleDayDidMount(arg)} dayHeaderDidMount={(arg) => handleDayDidMount(arg)} viewDidMount={(arg) => handleViewMount(arg)} // Interaction props selectable={true} unselectAuto={true} selectOverlap={false} select={(info) => handleSelect(info)} longPressDelay={150} eventContent={(arg) => handleContent(arg)} /> ); }