I use a React calendar system to create new events for scheduling appointments. However, the user can also drag an existing event to a new position if desired. The problem is that when the event is larger than the calendar view, it starts to stutter back and forth. I have some code that shows what it does now.
import React, { useState, useEffect, useRef } from 'react';
import { Calendar, momentLocalizer, Views } from 'react-big-calendar';
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop';
import 'react-big-calendar/lib/addons/dragAndDrop/styles.css';
import 'react-big-calendar/lib/css/react-big-calendar.css';
import moment from 'moment';
import PlanningStats from './PlanningStats';
import DebugCalendar from './DebugCalendar';
import EventOptionScreen from './EventOptionScreen';
import CustomDeleteEvent from './CustomDeleteEvent';
import { retrieveReservations } from './ReservationHttpHandler';
import { ReservationProvider } from './ReservationProvider';
import { useReservation } from './ReservationProvider';
import { consoleLog, debugMode } from './General';
import './SystemCalendar.css';
const localizer = momentLocalizer(moment);
const DragAndDropCalendar = withDragAndDrop(Calendar);
const SysCalendar = ({ user, system, systemName }) => {
const {
handleMouseDown,
handleMouseMove,
handleMouseUp,
setVisibleRange,
handleRangeChange,
deleteEvent,
eventStyleGetter,
setEvents,
events,
tempEvent,
debugDateRef,
createHandleEventDrop,
} = useReservation();
const [view, setView] = useState(Views.WEEK);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [isSelectionLocked, setIsSelectionLocked] = useState(false);
const [selectedEvent, setSelectedEvent] = useState(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const calendarRef = useRef(null);
useEffect(() => {
setLoading(true);
const now = new Date();
setVisibleRange({
start: moment(now).startOf('week').toDate(),
end: moment(now).endOf('week').toDate(),
});
retrieveReservations(system.id, user.userId, setEvents)
.catch((err) => {
console.error('Error fetching reservations:', err);
setError('Could not fetch reservations. Please try again.');
})
.finally(() => setLoading(false));
}, [system.id, user.userId]);
//handel dubble click event for opening a new modal screen for the event options
const handleDoubleClickEvent = (event) => {
if( user.userId===event.userId)
{
console.log("Open new Overlay")
setSelectedEvent(event); // Set the clicked event
setIsModalOpen(true); // Open the modal
}
};
// when the mouse is pressed down
// event: event is for checking and passing on for the handelmouse down.
const handleMouseDownWrapper = (event) => {
if (!isSelectionLocked && !isModalOpen && !event.target.closest('button')) {
event.currentTarget.style.cursor = 'crosshair';
handleMouseDown(event);
// Add the global listener
document.addEventListener('mouseup', handleGlobalMouseUp);
}
};
// handleGlobalMouseUp when the mouse is outside the boundery of the calendar
// event: pass on the event that has been selected.
const handleGlobalMouseUp=(event)=>{
handleMouseUp(event, calendarRef, user, system);
document.removeEventListener('mouseup', handleGlobalMouseUp);
}
const handleEventDrop = createHandleEventDrop({ setEvents, user, system, setIsSelectionLocked });
if (loading) return <div>Loading...</div>;
if (error) return <div>{error}</div>;
return (
<div
style={{
height: '50vh',
cursor: isSelectionLocked ? 'default' : 'pointer',
}}
ref={calendarRef}
onMouseDown={handleMouseDownWrapper}
onMouseMove={!isSelectionLocked && !isModalOpen ? (event) => handleMouseMove(event, calendarRef, user) : undefined}
// mouse up is responsible that the delete event is not working.
onMouseUp={(event) => {
console.log("-------------MOUSE BUTTON UP----------------")
if ((!isSelectionLocked && !isModalOpen) ) {
event.currentTarget.style.cursor = 'pointer';
handleMouseUp(event, calendarRef, user, system);
}
}}
>
{debugMode() &&
<DebugCalendar
isSelectionLocked={isSelectionLocked}
view={view}
tempEvent={tempEvent}
debugDateRef={debugDateRef}
/>
}
<PlanningStats sysId={system.id} sysName={systemName} sysEvents={events} />
<DragAndDropCalendar
localizer={localizer}
events={tempEvent ? [...events, tempEvent] : events}
startAccessor="start"
endAccessor="end"
style={{ height: '100%' }}
defaultView={view}
views={{ month: true, week: true, day: true, agenda: true }}
selectable
onEventDrop={handleEventDrop}
onDoubleClickEvent={handleDoubleClickEvent} // Use your double-click handler here
onView={setView}
step={30}
timeslots={1}
showMultiDayTimes
onEventResize={handleEventDrop}
resizable={true}
onRangeChange={handleRangeChange}
draggableAccessor={(event) => user.userRoll === 'Planner' || event.userId === user.userId}
onEventResizeStart={(type, { start, end }) => {
console.log(`Resize started: start=${start}, end=${end}`);
}}
onEventResizeStop={(type, { start, end }) => {
console.log(`Resize stopped: start=${start}, end=${end}`);
}}
eventPropGetter={(event) => eventStyleGetter(event, user)}
components={{
event: (props) => <CustomDeleteEvent {...props} deleteEvent={deleteEvent} user={user} setIsSelectionLocked={setIsSelectionLocked} />,
}}
/>
{isModalOpen && (
<EventOptionScreen event={selectedEvent} onClose={() => setIsModalOpen(false)} />
)}
</div>
);
};
const SystemCalendar = ({ system, user, systemName }) => {
return (
<ReservationProvider>
<h2 style={{ color: '#ff0000' }}>Availability</h2>
<SysCalendar user={user} system={system} systemName={systemName} />
</ReservationProvider>
);
};
export default SystemCalendar;
Css
/* Change the background color of the event rows */
.rbc-agenda-content .rbc-agenda-event-cell {
background-color: #e0f7fa; /* Light blue background */
color: #105a7c; /* Dark teal text */
}
/* Change the color of the date headers */
.rbc-agenda-content .rbc-agenda-date-cell {
background-color: #006179; /* Dark teal background */
color: #ffffff; /* White text */
font-weight: bold; /* Bold text */
}
/* Style the time columns */
.rbc-agenda-content .rbc-agenda-time-cell {
color: #0871a1; /* Teal color for the time */
font-style: italic; /* Italic text */
}
.rbc-event {
background-color: rgba(248, 255, 147, 0.89); /* Light yellow background */
color: rgb(0, 0, 0) !important; /* Black text color */
border-width: 2px;
max-height: 100px;
overflow: hidden;
}
/* change the color to yellow for requested */
.user-event {
background-color: rgba(248, 255, 147, 0.89) !important; /* Light yellow background */
color: rgb(0, 0, 0) !important; /* Black text color */
border: 2px solid black !important; /* Black border */
cursor: pointer !important; /* Pointer cursor to indicate interaction allowed */
}
/* Non-user event styles */
.non-user-event {
background-color: rgba(192, 192, 192, 0.5) !important; /* Light gray background */
color: gray !important; /* Gray text color */
border: 2px solid lightgray !important; /* Light gray border */
cursor: not-allowed !important; /* 'Not-allowed' cursor to indicate restricted access */
}
/* change the color to green for accepted */
.user-event-approved{
background-color: rgba(147, 255, 170, 0.89) !important; /* Light yellow background */
color: rgb(0, 0, 0) !important; /* Black text color */
border: 2px solid black !important; /* Black border */
cursor: pointer !important; /* Pointer cursor to indicate interaction allowed */
}
/* change the color to red for rejected */
.user-event-reject{
background-color: rgba(255, 36, 36, 0.89) !important; /* Light yellow background */
color: rgb(255, 255, 255) !important; /* Black text color */
border: 2px solid black !important; /* Black border */
cursor: pointer !important; /* Pointer cursor to indicate interaction allowed */
}
/* change the color to orange for planned */
.user-event-planned{
background-color: rgba(214, 162, 20, 0.89) !important; /* Light yellow background */
color: rgb(255, 255, 255) !important; /* Black text color */
border: 2px solid black !important; /* Black border */
cursor: pointer !important; /* Pointer cursor to indicate interaction allowed */
}
/* Add custom styles for drag selection indication */
.rbc-selected-cell {
background-color: rgba(0, 128, 255, 0.3); /* Light blue background */
border: 1px solid #007bff; /* Blue border */
}
/* Hide the default selection box of react-big-calendar */
.rbc-slot-selection {
display: none; /* Completely hides the selection box */
}
/* Optional: Hide the borders of the selected cells */
.rbc-selected-cell {
background-color: transparent; /* Removes the background color */
border: none; /* Removes the border */
}
/* Temporary event styling */
.temp-event {
background-color: rgba(61, 61, 61, 0.7) !important;
border: 1px solid rgba(133, 133, 133, 0.8) !important;
color: white !important;
border-radius: 5px;
opacity: 0.8;
}
I ask different people at the office and google but no answer has been founded. I don’t know if it is a re-rendering problem or wrong way of logic thinking of myself.
I tried to see if it needed some autoscroll handling, but that didn’t work. I also tried making changes in the CSS, including overflow and handlers, but the same problem still occurs.
Latest edit Css file added.