feat: move headerToolbar functionality to Menubar component
- Remove headerToolbar from FullCalendar and set to false - Create CalendarLayout component to manage state between Menubar and Calendar - Add navigation controls (prev/today/next) to Menubar left-menu using MUI ButtonGroup - Add current date/time display (April 2024 format) to Menubar left-menu - Add view selector (Month/Week/Day) to Menubar right-menu using MUI Select - Implement real-time date synchronization between Calendar and Menubar
This commit is contained in:
@@ -7,15 +7,13 @@ import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
|
||||
import ReactCalendar from "react-calendar";
|
||||
import "./Calendar.css";
|
||||
import "./CustomCalendar.css";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import EventPopover from "../../features/Events/EventModal";
|
||||
import CalendarPopover from "../../features/Calendars/CalendarModal";
|
||||
import { CalendarEvent } from "../../features/Events/EventsTypes";
|
||||
import CalendarSelection from "./CalendarSelection";
|
||||
import {
|
||||
getCalendarDetailAsync,
|
||||
getCalendarsListAsync,
|
||||
getEventAsync,
|
||||
putEventAsync,
|
||||
updateEventLocal,
|
||||
@@ -40,12 +38,15 @@ import { userAttendee } from "../../features/User/userDataTypes";
|
||||
import { TempCalendarsInput } from "./TempCalendarsInput";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
export default function CalendarApp() {
|
||||
const calendarRef = useRef<CalendarApi | null>(null);
|
||||
interface CalendarAppProps {
|
||||
calendarRef: React.RefObject<CalendarApi | null>;
|
||||
onDateChange?: (date: Date) => void;
|
||||
}
|
||||
|
||||
export default function CalendarApp({ calendarRef, onDateChange }: CalendarAppProps) {
|
||||
const [selectedDate, setSelectedDate] = useState(new Date());
|
||||
const [selectedMiniDate, setSelectedMiniDate] = useState(new Date());
|
||||
const tokens = useAppSelector((state) => state.user.tokens);
|
||||
const user = useAppSelector((state) => state.user.userData);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
if (!tokens) {
|
||||
@@ -115,15 +116,20 @@ export default function CalendarApp() {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
updateCalsDetails(
|
||||
selectedCalendars,
|
||||
pending,
|
||||
calendars,
|
||||
rangeKey,
|
||||
dispatch,
|
||||
calendarRange
|
||||
);
|
||||
}, [rangeKey, selectedCalendars]);
|
||||
selectedCalendars.forEach((id) => {
|
||||
if (!pending && rangeKey) {
|
||||
dispatch(
|
||||
getCalendarDetailAsync({
|
||||
calId: id,
|
||||
match: {
|
||||
start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start),
|
||||
end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}, [rangeKey, selectedCalendars, pending, dispatch, calendarRange.start, calendarRange.end]);
|
||||
|
||||
useEffect(() => {
|
||||
updateCalsDetails(
|
||||
@@ -327,29 +333,7 @@ export default function CalendarApp() {
|
||||
height={"100%"}
|
||||
select={handleDateSelect}
|
||||
nowIndicator
|
||||
customButtons={{
|
||||
refresh: {
|
||||
text: "↻",
|
||||
click: async () => {
|
||||
await dispatch(getCalendarsListAsync());
|
||||
selectedCalendars.forEach((id) => {
|
||||
if (!pending && rangeKey) {
|
||||
dispatch(
|
||||
getCalendarDetailAsync({
|
||||
calId: id,
|
||||
match: {
|
||||
start: formatDateToYYYYMMDDTHHMMSS(
|
||||
calendarRange.start
|
||||
),
|
||||
end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}}
|
||||
headerToolbar={false}
|
||||
views={{
|
||||
timeGridWeek: { titleFormat: { month: "long", year: "numeric" } },
|
||||
}}
|
||||
@@ -372,15 +356,21 @@ export default function CalendarApp() {
|
||||
hour12: false,
|
||||
}}
|
||||
datesSet={(arg) => {
|
||||
// Get the current date from calendar API to ensure consistency
|
||||
const calendarCurrentDate = calendarRef.current?.getDate() || new Date(arg.start);
|
||||
|
||||
if (arg.view.type === "dayGridMonth") {
|
||||
setSelectedDate(new Date(arg.start));
|
||||
const midTimestamp =
|
||||
(arg.start.getTime() + arg.end.getTime()) / 2;
|
||||
setSelectedMiniDate(new Date(midTimestamp));
|
||||
setSelectedMiniDate(calendarCurrentDate);
|
||||
} else {
|
||||
setSelectedDate(new Date(arg.start));
|
||||
setSelectedMiniDate(new Date(arg.start));
|
||||
}
|
||||
|
||||
// Always use the calendar's current date for consistency
|
||||
if (onDateChange) {
|
||||
onDateChange(calendarCurrentDate);
|
||||
}
|
||||
}}
|
||||
dayHeaderContent={(arg) => {
|
||||
const date = arg.date.getDate();
|
||||
@@ -695,11 +685,6 @@ export default function CalendarApp() {
|
||||
putEventAsync({ cal: calendars[newEvent.calId], newEvent })
|
||||
);
|
||||
}}
|
||||
headerToolbar={{
|
||||
left: "title",
|
||||
center: "prev,today,next",
|
||||
right: "refresh,dayGridMonth,timeGridWeek,timeGridDay",
|
||||
}}
|
||||
eventContent={(arg) => {
|
||||
const event = arg.event;
|
||||
if (
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Menubar, MenubarProps } from "../Menubar/Menubar";
|
||||
import CalendarApp from "./Calendar";
|
||||
import { useAppDispatch } from "../../app/hooks";
|
||||
import {
|
||||
getCalendarDetailAsync,
|
||||
getCalendarsListAsync,
|
||||
} from "../../features/Calendars/CalendarSlice";
|
||||
import {
|
||||
formatDateToYYYYMMDDTHHMMSS,
|
||||
getCalendarRange,
|
||||
} from "../../utils/dateUtils";
|
||||
import { useAppSelector } from "../../app/hooks";
|
||||
|
||||
export default function CalendarLayout() {
|
||||
const calendarRef = useRef<any>(null);
|
||||
const dispatch = useAppDispatch();
|
||||
const selectedCalendars = useAppSelector((state) => state.calendars.list);
|
||||
const userId = useAppSelector((state) => state.user.userData?.openpaasId) ?? "";
|
||||
const [currentDate, setCurrentDate] = useState<Date>(new Date());
|
||||
|
||||
const handleRefresh = async () => {
|
||||
await dispatch(getCalendarsListAsync());
|
||||
|
||||
// Get current calendar range
|
||||
if (calendarRef.current) {
|
||||
const view = calendarRef.current.getApi().view;
|
||||
const calendarRange = getCalendarRange(view.activeStart);
|
||||
|
||||
// Refresh events for selected calendars
|
||||
Object.keys(selectedCalendars).forEach((id) => {
|
||||
if (id.split("/")[0] === userId) {
|
||||
dispatch(
|
||||
getCalendarDetailAsync({
|
||||
calId: id,
|
||||
match: {
|
||||
start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start),
|
||||
end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleDateChange = (date: Date) => {
|
||||
setCurrentDate(date);
|
||||
};
|
||||
|
||||
const menubarProps: MenubarProps = {
|
||||
calendarRef,
|
||||
onRefresh: handleRefresh,
|
||||
currentDate,
|
||||
onDateChange: handleDateChange,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Menubar {...menubarProps} />
|
||||
<CalendarApp calendarRef={calendarRef} onDateChange={handleDateChange} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user