Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions src/components/Dropdown/Calendar/Calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useTranslation } from 'react-i18next';
import { useDebounce } from '../../../hooks/debounce';
import { SEARCH_DELAY } from '../../../constants/search';
import { useLazyGetAllCalendarsQuery } from '../../../services/calendar';
import { setRecentCalendarForUser } from '../../../utils/recentCalendarStorage';
import LoadingIndicator from '../../LoadingIndicator';

const hashString = (value = '') => {
Expand Down Expand Up @@ -58,6 +59,7 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
const [open, setOpen] = useState(false);
const [searchInput, setSearchInput] = useState('');
const [searchQuery, setSearchQuery] = useState('');
const [activeSearchTerm, setActiveSearchTerm] = useState('');
const [calendars, setCalendars] = useState([]);
const [totalCount, setTotalCount] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
Expand Down Expand Up @@ -191,6 +193,21 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
[cacheKey, getAllCalendars],
);

useEffect(() => {
if (!open) return;
if (activeSearchTerm === searchQuery) return;

inFlightPageKeysRef.current.clear();
loadedPageKeysRef.current.clear();
loadingMoreRef.current = false;
setCalendars([]);
setTotalCount(0);
setCurrentPage(1);
setActiveSearchTerm(searchQuery);

loadPage(1, searchQuery, false);
}, [activeSearchTerm, loadPage, open, searchQuery]);

useEffect(() => {
return () => {
if (activeRequestRef.current?.abort) {
Expand All @@ -207,13 +224,6 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
[],
);

useEffect(() => {
if (!open || !searchQuery || isFetching || !hasMore || loadingMoreRef.current) return;
if (!filteredCalendars.length) {
loadPage(currentPage + 1, searchQuery, true);
}
}, [open, searchQuery, isFetching, hasMore, filteredCalendars.length, loadPage, currentPage]);

useEffect(() => {
const cachedData = cacheRef.current.get(cacheKey);

Expand All @@ -222,17 +232,20 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
setCalendars(cachedData.data);
setTotalCount(cachedData.totalCount);
setCurrentPage(cachedData.currentPage);
setActiveSearchTerm('');
} else if (allCalendarsData?.data) {
setCalendars(allCalendarsData.data);
setTotalCount(allCalendarsData.count ?? allCalendarsData.data.length);
setCurrentPage(1);
setActiveSearchTerm('');
cacheRef.current.set(cacheKey, {
data: allCalendarsData.data,
totalCount: allCalendarsData.count ?? allCalendarsData.data.length,
currentPage: 1,
timestamp: Date.now(),
});
} else {
setActiveSearchTerm('');
loadPage(1, '', false);
}
} else {
Expand All @@ -252,9 +265,10 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
}
setSearchInput('');
setSearchQuery('');
setActiveSearchTerm('');
loadingMoreRef.current = false;
inFlightPageKeysRef.current.clear();
loadedPageKeysRef.current.clear();
setCalendars([]);
setTotalCount(0);
setCurrentPage(1);
}
Expand All @@ -268,9 +282,10 @@ function Calendar({ children, setPageNumber, allCalendarsData }) {
const handleItemClick = (key) => {
if (calendarIdInCookies !== key) {
dispatch(setSelectedCalendar(String(key)));
sessionStorage.setItem('calendarId', key);
setRecentCalendarForUser({ user, calendarId: key });
setPageNumber(1);
sessionStorage.clear();
sessionStorage.setItem('calendarId', key);
setOpen(false);
const origin = window.location.origin;
const newUrl = `${origin}${PathName.Dashboard}/${key}${PathName.Events}`;
Expand Down
70 changes: 55 additions & 15 deletions src/pages/Dashboard/Dashboard.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import './dashboard.css';
import { Grid, Layout, Row, Col } from 'antd';
import { Outlet, useLocation, useSearchParams } from 'react-router-dom';
Expand All @@ -25,6 +25,7 @@ import { calendarModes } from '../../constants/calendarModes';
import { useAuth } from '../../hooks/useAuth';
import { clearErrors, getErrorDetails } from '../../redux/reducer/ErrorSlice';
import LoadingIndicator from '../../components/LoadingIndicator/LoadingIndicator';
import { getRecentCalendarForUser, setRecentCalendarForUser } from '../../utils/recentCalendarStorage';

const { Header, Content } = Layout;
const { useBreakpoint } = Grid;
Expand All @@ -49,7 +50,6 @@ function Dashboard() {

const {
currentData: allCalendarsData,
isLoading,
isSuccess,
refetch,
} = useGetAllCalendarsQuery(
Expand All @@ -69,6 +69,16 @@ function Dashboard() {
const [isReadOnly, setIsReadOnly] = useState(false);
const [isModalVisible, setIsModalVisible] = useState(false);

const persistActiveCalendar = useCallback(
(id) => {
if (!id) return;
sessionStorage.setItem('calendarId', id);
dispatch(setSelectedCalendar(id));
setRecentCalendarForUser({ user, calendarId: id });
},
[dispatch, user],
);

useEffect(() => {
if (location?.state?.previousPath?.toLowerCase() === 'login') {
dispatch(setInterfaceLanguage(user?.interfaceLanguage?.toLowerCase()));
Expand All @@ -79,9 +89,9 @@ function Dashboard() {
useEffect(() => {
const accessTokenFromCookie = Cookies.get('accessToken');
const refreshTokenFromCookie = Cookies.get('refreshToken');
const calendarIdFromCookie = sessionStorage.getItem('calendarId');
const calendarIdFromSessionStorage = sessionStorage.getItem('calendarId');

const calId = calendarId || calendarIdFromCookie;
const calId = calendarId || calendarIdFromSessionStorage;
if (calendarId) sessionStorage.setItem('calendarId', calId);

if (!checkToken(accessToken, accessTokenFromCookie)) navigate(PathName.Login);
Expand Down Expand Up @@ -113,8 +123,7 @@ function Dashboard() {
getCalendar({ id: calendarId, sessionId: timestampRef })
.unwrap()
.then((response) => {
sessionStorage.setItem('calendarId', calendarId);
dispatch(setSelectedCalendar(String(calendarId)));
persistActiveCalendar(calendarId);
if (response?.mode === calendarModes.READ_ONLY) {
setIsReadOnly(true);
setIsModalVisible(true);
Expand All @@ -126,16 +135,47 @@ function Dashboard() {
}
});
} else {
let activeCalendarId = sessionStorage.getItem('calendarId');
if (activeCalendarId && accessToken) {
navigate(`${PathName.Dashboard}/${activeCalendarId}${PathName.Events}`);
} else if (!isLoading && allCalendarsData?.data) {
activeCalendarId = allCalendarsData?.data[0]?.id;
sessionStorage.setItem('calendarId', activeCalendarId);
navigate(`${PathName.Dashboard}/${activeCalendarId}${PathName.Events}`);
}
const resolveAndNavigateToCalendar = async () => {
const recentCalendarId = getRecentCalendarForUser(user);
if (recentCalendarId) {
try {
await getCalendar({ id: recentCalendarId, sessionId: timestampRef }).unwrap();
persistActiveCalendar(recentCalendarId);
navigate(`${PathName.Dashboard}/${recentCalendarId}${PathName.Events}`);
return;
} catch {
// Ignore stale/inaccessible stored recent ID and continue with legacy fallback.
}
}

let activeCalendarId = sessionStorage.getItem('calendarId');

if (activeCalendarId && accessToken) {
persistActiveCalendar(activeCalendarId);
navigate(`${PathName.Dashboard}/${activeCalendarId}${PathName.Events}`);
return;
}

const firstCalendarId = allCalendarsData?.data?.[0]?.id;
if (!firstCalendarId) return;

persistActiveCalendar(firstCalendarId);
navigate(`${PathName.Dashboard}/${firstCalendarId}${PathName.Events}`);
};

resolveAndNavigateToCalendar();
}
}, [calendarId, isLoading, allCalendarsData, isSuccess]);
}, [
accessToken,
allCalendarsData,
calendarId,
getCalendar,
isSuccess,
navigate,
persistActiveCalendar,
timestampRef,
user,
]);

useEffect(() => {
if (reloadStatus) {
Expand Down
10 changes: 2 additions & 8 deletions src/pages/Login/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,16 @@ const Login = () => {
}

const savedAccessToken = Cookies.get('accessToken');
const calenderId = sessionStorage.getItem('calendarId');
if (location?.state?.previousPath === 'logout') {
dispatch(clearUser());
}
if (
((accessToken && accessToken != '') || (savedAccessToken && savedAccessToken != '')) &&
calenderId &&
calenderId != ''
) {
if ((accessToken && accessToken != '') || (savedAccessToken && savedAccessToken != '')) {
navigate(PathName.Dashboard, { state: { previousPath: 'login' } });
}
}, []);

useEffect(() => {
const calenderId = sessionStorage.getItem('calendarId');
if (accessToken && accessToken != '' && calenderId && calenderId != '') {
if (accessToken && accessToken != '') {
navigate(PathName.Dashboard, { state: { previousPath: 'login' } });
}
}, [accessToken]);
Expand Down
68 changes: 68 additions & 0 deletions src/utils/recentCalendarStorage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const RECENT_CALENDAR_STORAGE_PREFIX = 'recentCalendar';

const getSafeLocalStorage = () => {
if (typeof window === 'undefined' || !window.localStorage) {
return null;
}

return window.localStorage;
};

const getUserIdentity = (user) => {
if (!user) return '';

return user?.id ? String(user.id).trim() : '';
};

const getRecentCalendarStorageKey = (user) => {
const identity = getUserIdentity(user);
if (!identity) return '';

return `${RECENT_CALENDAR_STORAGE_PREFIX}:${identity}`;
};

export const getRecentCalendarForUser = (user) => {
const storage = getSafeLocalStorage();
if (!storage) return '';

const storageKey = getRecentCalendarStorageKey(user);
if (!storageKey) return '';

try {
const value = storage.getItem(storageKey);
if (!value) return '';
return String(value);
} catch {
return '';
}
};

export const setRecentCalendarForUser = ({ user, calendarId }) => {
if (!calendarId) return;

const storage = getSafeLocalStorage();
if (!storage) return;

const storageKey = getRecentCalendarStorageKey(user);
if (!storageKey) return;

try {
storage.setItem(storageKey, String(calendarId));
} catch {
// Ignore storage failures (private mode/quota) and keep runtime behavior unchanged.
}
};

export const clearRecentCalendarForUser = (user) => {
const storage = getSafeLocalStorage();
if (!storage) return;

const storageKey = getRecentCalendarStorageKey(user);
if (!storageKey) return;

try {
storage.removeItem(storageKey);
} catch {
// Ignore storage failures.
}
};
Loading