fix: infinity loop cause by change layout, adjust style

This commit is contained in:
lenhanphung
2025-09-24 14:22:36 +07:00
parent 48ca3fb834
commit 5a9a34d0d3
7 changed files with 105 additions and 84 deletions
+8 -2
View File
@@ -128,7 +128,10 @@ describe("CalendarSelection", () => {
}; };
it("renders calendars", async () => { it("renders calendars", async () => {
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument(); expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument(); expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
expect(screen.getByText("Other Calendars")).toBeInTheDocument(); expect(screen.getByText("Other Calendars")).toBeInTheDocument();
@@ -139,7 +142,10 @@ describe("CalendarSelection", () => {
}); });
it("open accordeon when clicking on button only", () => { it("open accordeon when clicking on button only", () => {
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
expect(screen.getByText("Personnal Calendars")).toBeInTheDocument(); expect(screen.getByText("Personnal Calendars")).toBeInTheDocument();
expect(screen.getByText("Delegated Calendars")).toBeInTheDocument(); expect(screen.getByText("Delegated Calendars")).toBeInTheDocument();
expect(screen.getByText("Other Calendars")).toBeInTheDocument(); expect(screen.getByText("Other Calendars")).toBeInTheDocument();
@@ -70,7 +70,10 @@ describe("CalendarApp integration", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
}; };
it("renders the event on the calendar and calendarRef works", async () => { it("renders the event on the calendar and calendarRef works", async () => {
@@ -159,7 +162,10 @@ describe("CalendarApp integration", () => {
title: "Private Event", title: "Private Event",
}); });
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
const eventEls = screen.getAllByText("Private Event"); const eventEls = screen.getAllByText("Private Event");
const found = eventEls.some((eventEl) => const found = eventEls.some((eventEl) =>
@@ -174,7 +180,10 @@ describe("CalendarApp integration", () => {
title: "Confidential Event", title: "Confidential Event",
}); });
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
const eventEls = screen.getAllByText("Confidential Event"); const eventEls = screen.getAllByText("Confidential Event");
const found = eventEls.some((eventEl) => const found = eventEls.some((eventEl) =>
@@ -189,7 +198,10 @@ describe("CalendarApp integration", () => {
title: "Public Event", title: "Public Event",
}); });
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
const eventEls = screen.getAllByText("Public Event"); const eventEls = screen.getAllByText("Public Event");
const found = eventEls.some((eventEl) => const found = eventEls.some((eventEl) =>
+56 -56
View File
@@ -23,14 +23,14 @@ describe("Calendar App Component Display Tests", () => {
]; ];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
const navbarElement = screen.getByText("Twake"); const navbarElement = screen.getByText("Twake");
@@ -40,14 +40,14 @@ describe("Calendar App Component Display Tests", () => {
(window as any).appList = [{ name: "test", icon: "test", link: "test" }]; (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText(/Twake/i)).toBeInTheDocument(); expect(screen.getByText(/Twake/i)).toBeInTheDocument();
@@ -58,14 +58,14 @@ describe("Calendar App Component Display Tests", () => {
(window as any).appList = [{ name: "test", icon: "test", link: "test" }]; (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("JD")).toBeInTheDocument(); expect(screen.getByText("JD")).toBeInTheDocument();
@@ -86,14 +86,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("t")).toBeInTheDocument(); expect(screen.getByText("t")).toBeInTheDocument();
@@ -116,14 +116,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("t")).toBeInTheDocument(); expect(screen.getByText("t")).toBeInTheDocument();
@@ -145,14 +145,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("t")).toBeInTheDocument(); expect(screen.getByText("t")).toBeInTheDocument();
@@ -174,14 +174,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("JD")).toBeInTheDocument(); expect(screen.getByText("JD")).toBeInTheDocument();
@@ -203,14 +203,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByText("t")).toBeInTheDocument(); expect(screen.getByText("t")).toBeInTheDocument();
@@ -232,14 +232,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
// Should not crash and show empty string // Should not crash and show empty string
@@ -263,14 +263,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
// Should not crash and show empty string // Should not crash and show empty string
@@ -294,14 +294,14 @@ describe("Calendar App Component Display Tests", () => {
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
// Should not crash and show empty string // Should not crash and show empty string
@@ -313,14 +313,14 @@ describe("Calendar App Component Display Tests", () => {
(window as any).appList = [{ name: "test", icon: "test", link: "test" }]; (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
expect(screen.getByTestId("AppsIcon")).toBeInTheDocument(); expect(screen.getByTestId("AppsIcon")).toBeInTheDocument();
@@ -330,14 +330,14 @@ describe("Calendar App Component Display Tests", () => {
(window as any).appList = [{ name: "test", icon: "test", link: "test" }]; (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
const appsButton = screen.getByTestId("AppsIcon"); const appsButton = screen.getByTestId("AppsIcon");
@@ -350,14 +350,14 @@ describe("Calendar App Component Display Tests", () => {
(window as any).appList = [{ name: "test", icon: "test", link: "test" }]; (window as any).appList = [{ name: "test", icon: "test", link: "test" }];
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
const mockOnRefresh = jest.fn(); const mockOnRefresh = jest.fn();
const mockCurrentDate = new Date('2024-04-15'); const mockCurrentDate = new Date("2024-04-15");
renderWithProviders( renderWithProviders(
<Menubar <Menubar
calendarRef={mockCalendarRef} calendarRef={mockCalendarRef}
onRefresh={mockOnRefresh} onRefresh={mockOnRefresh}
currentDate={mockCurrentDate} currentDate={mockCurrentDate}
/>, />,
preloadedState preloadedState
); );
const appsButton = screen.getByTestId("AppsIcon"); const appsButton = screen.getByTestId("AppsIcon");
@@ -45,7 +45,10 @@ describe("MiniCalendar", () => {
}, },
}; };
const mockCalendarRef = { current: null }; const mockCalendarRef = { current: null };
renderWithProviders(<CalendarApp calendarRef={mockCalendarRef} />, preloadedState); renderWithProviders(
<CalendarApp calendarRef={mockCalendarRef} />,
preloadedState
);
}; };
it("renders mini calendar with today in orange", async () => { it("renders mini calendar with today in orange", async () => {
@@ -56,9 +59,4 @@ describe("MiniCalendar", () => {
const todayTile = screen.getByTestId(dateTestId); const todayTile = screen.getByTestId(dateTestId);
expect(todayTile?.parentElement).toHaveClass("today"); expect(todayTile?.parentElement).toHaveClass("today");
}); });
}); });
+14 -13
View File
@@ -7,7 +7,7 @@ import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
import ReactCalendar from "react-calendar"; import ReactCalendar from "react-calendar";
import "./Calendar.css"; import "./Calendar.css";
import "./CustomCalendar.css"; import "./CustomCalendar.css";
import { useEffect, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useAppDispatch, useAppSelector } from "../../app/hooks"; import { useAppDispatch, useAppSelector } from "../../app/hooks";
import EventPopover from "../../features/Events/EventModal"; import EventPopover from "../../features/Events/EventModal";
import { CalendarEvent } from "../../features/Events/EventsTypes"; import { CalendarEvent } from "../../features/Events/EventsTypes";
@@ -86,6 +86,7 @@ export default function CalendarApp({
} }
}); });
const [selectedCalendars, setSelectedCalendars] = useState<string[]>([]); const [selectedCalendars, setSelectedCalendars] = useState<string[]>([]);
const fetchedRangesRef = useRef<Record<string, string>>({});
// Auto-select personal calendars when first loaded // Auto-select personal calendars when first loaded
useEffect(() => { useEffect(() => {
@@ -119,23 +120,23 @@ export default function CalendarApp({
); );
useEffect(() => { useEffect(() => {
if (!rangeKey) return;
selectedCalendars.forEach((id) => { selectedCalendars.forEach((id) => {
if (!pending && rangeKey) { if (fetchedRangesRef.current[id] === rangeKey) return;
dispatch( fetchedRangesRef.current[id] = rangeKey;
getCalendarDetailAsync({ dispatch(
calId: id, getCalendarDetailAsync({
match: { calId: id,
start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), match: {
end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start),
}, end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end),
}) },
); })
} );
}); });
}, [ }, [
rangeKey, rangeKey,
selectedCalendars, selectedCalendars,
pending,
dispatch, dispatch,
calendarRange.start, calendarRange.start,
calendarRange.end, calendarRange.end,
+5 -1
View File
@@ -224,6 +224,10 @@ th.fc-col-header-cell.fc-day:hover
.fc-timegrid-slot-label { .fc-timegrid-slot-label {
background-color: #fff !important; background-color: #fff !important;
} }
thead .fc-scroller, tbody > tr.fc-scrollgrid-section:first-of-type .fc-scroller { thead .fc-scroller,
tbody > tr.fc-scrollgrid-section:first-of-type .fc-scroller {
overflow: hidden !important; overflow: hidden !important;
}
.navigation-controls {
margin-right: 40px;
} }
+2 -2
View File
@@ -49,7 +49,7 @@
.menubar-item { .menubar-item {
display: flex; display: flex;
align-items: center; align-items: center;
width: calc(330px - .5rem); width: calc(330px - 0.5rem);
} }
.logo { .logo {
@@ -104,4 +104,4 @@
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
} }