Skip to content

Commit 5e8ee81

Browse files
deduplicated caching logic
1 parent b6f322a commit 5e8ee81

4 files changed

Lines changed: 274 additions & 199 deletions

File tree

src/components/Reports/TotalReport/TotalContributorsReport.jsx

Lines changed: 25 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import TotalReportBarGraph from './TotalReportBarGraph';
66
import Loading from '../../common/Loading';
77
import EditableInfoModal from '../../UserProfile/EditableModal/EditableInfoModal';
88
import { generateBarData as generateBarDataUtil } from './generateBarData';
9+
import {
10+
getCachedData,
11+
setCachedData,
12+
validateUserList,
13+
logApiRequest,
14+
logApiResponse,
15+
} from './cacheUtils';
916

1017
function TotalContributorsReport({ startDate, endDate, userProfiles, darkMode, userRole }) {
1118
const [contributors, setContributors] = useState([]);
@@ -30,88 +37,57 @@ function TotalContributorsReport({ startDate, endDate, userProfiles, darkMode, u
3037

3138
// Fetch time entries for the selected period
3239
const loadTimeEntriesForPeriod = useCallback(async (controller) => {
40+
const reportName = 'TotalContributorsReport';
3341
const url = ENDPOINTS.TIME_ENTRIES_REPORTS;
3442

3543
if (!url) {
3644
return;
3745
}
3846

39-
// Don't make API call if userList is empty
40-
if (!userList || userList.length === 0) {
41-
// eslint-disable-next-line no-console
42-
console.warn('TotalContributorsReport: Skipping API call - userList is empty', {
43-
userProfilesLength: userProfiles?.length,
44-
userListLength: userList?.length,
45-
});
47+
// Validate userList
48+
if (!validateUserList(userList, userProfiles, reportName)) {
4649
setTimeEntries([]);
4750
setLoading(false);
4851
return;
4952
}
5053

51-
// Check cache with date range key to ensure cache is valid for current date range
52-
const cacheKey = `TotalContributorsReport_${fromDate}_${toDate}`;
53-
const cachedData = localStorage.getItem(cacheKey);
54-
if (cachedData) {
55-
try {
56-
const parsedData = JSON.parse(cachedData);
57-
if (parsedData && Array.isArray(parsedData) && parsedData.length > 0) {
58-
// eslint-disable-next-line no-console
59-
console.log('TotalContributorsReport: Using cached data', {
60-
cacheKey,
61-
dataLength: parsedData.length,
62-
});
63-
setTimeEntries(parsedData);
64-
setLoading(false);
65-
return;
66-
}
67-
} catch (e) {
68-
// eslint-disable-next-line no-console
69-
console.warn('TotalContributorsReport: Failed to parse cached data', e);
70-
}
54+
// Check cache with date range key
55+
const cacheKey = `${reportName}_${fromDate}_${toDate}`;
56+
const cached = getCachedData(cacheKey, reportName);
57+
if (cached.data) {
58+
setTimeEntries(cached.data);
59+
setLoading(false);
60+
return;
7161
}
7262

7363
try {
74-
// eslint-disable-next-line no-console
75-
console.log('TotalContributorsReport API Request:', {
76-
url,
77-
payload: { users: userList, fromDate, toDate },
64+
logApiRequest(reportName, url, { users: userList, fromDate, toDate }, {
7865
usersCount: userList?.length,
79-
timestamp: new Date().toISOString(),
8066
});
67+
8168
const response = await axios.post(
8269
url,
8370
{ users: userList, fromDate, toDate },
8471
{ signal: controller.signal }
8572
);
86-
// eslint-disable-next-line no-console
87-
console.log('TotalContributorsReport API Response:', {
88-
dataLength: response.data?.length,
89-
timestamp: new Date().toISOString(),
90-
});
73+
74+
logApiResponse(reportName, response.data?.length);
75+
9176
const mappedTimeEntries = response.data.map(entry => ({
9277
userId: entry.personId,
9378
hours: entry.hours,
9479
minutes: entry.minutes,
9580
isTangible: entry.isTangible,
9681
date: entry.dateOfWork,
9782
}));
83+
9884
setTimeEntries(mappedTimeEntries);
99-
100-
// Cache the data with date range key
101-
if (mappedTimeEntries.length > 0) {
102-
localStorage.setItem(cacheKey, JSON.stringify(mappedTimeEntries));
103-
// eslint-disable-next-line no-console
104-
console.log('TotalContributorsReport: Data cached', { cacheKey, dataLength: mappedTimeEntries.length });
105-
} else {
106-
// eslint-disable-next-line no-console
107-
console.warn('TotalContributorsReport: Empty response - clearing cache', { cacheKey });
108-
localStorage.removeItem(cacheKey);
109-
}
85+
setCachedData(cacheKey, mappedTimeEntries, reportName);
11086
} catch (error) {
11187
// eslint-disable-next-line import/no-named-as-default-member
11288
if (!axios.isCancel(error)) {
11389
// eslint-disable-next-line no-console
114-
console.error('TotalContributorsReport API Error:', error);
90+
console.error(`${reportName} API Error:`, error);
11591
setTimeEntries([]);
11692
}
11793
}

src/components/Reports/TotalReport/TotalPeopleReport.jsx

Lines changed: 29 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ import ReactTooltip from 'react-tooltip';
88
import TotalReportBarGraph from './TotalReportBarGraph';
99
import Loading from '../../common/Loading';
1010
import { generateBarData as generateBarDataUtil } from './generateBarData';
11+
import {
12+
getCachedData,
13+
setCachedData,
14+
validateUserList,
15+
logApiRequest,
16+
logApiResponse,
17+
checkIncompleteResponse,
18+
} from './cacheUtils';
1119

1220
function TotalPeopleReport(props) {
1321
const { startDate, endDate, userProfiles, darkMode } = props;
@@ -39,104 +47,60 @@ function TotalPeopleReport(props) {
3947

4048
const loadTimeEntriesForPeriod = useCallback(
4149
async controller => {
50+
const reportName = 'TotalPeopleReport';
4251
const url = ENDPOINTS.TIME_ENTRIES_REPORTS;
4352

4453
if (!url) {
4554
setTotalPeopleReportDataLoading(false);
4655
return;
4756
}
4857

49-
// Don't make API call if userList is empty
50-
if (!userList || userList.length === 0) {
51-
// eslint-disable-next-line no-console
52-
console.warn('TotalPeopleReport: Skipping API call - userList is empty', {
53-
userProfilesLength: userProfiles?.length,
54-
userListLength: userList?.length,
55-
});
58+
// Validate userList
59+
if (!validateUserList(userList, userProfiles, reportName)) {
5660
setTotalPeopleReportDataLoading(false);
5761
setAllTimeEntries([]);
5862
return;
5963
}
6064

61-
// Check cache with date range key to ensure cache is valid for current date range
62-
const cacheKey = `TotalPeopleReport_${fromDate}_${toDate}`;
63-
const cachedData = localStorage.getItem(cacheKey);
64-
if (cachedData) {
65-
try {
66-
const parsedData = JSON.parse(cachedData);
67-
if (parsedData && Array.isArray(parsedData) && parsedData.length > 0) {
68-
// eslint-disable-next-line no-console
69-
console.log('TotalPeopleReport: Using cached data', {
70-
cacheKey,
71-
dataLength: parsedData.length,
72-
});
73-
setAllTimeEntries(parsedData);
74-
setTotalPeopleReportDataLoading(false);
75-
setTotalPeopleReportDataReady(true);
76-
return;
77-
}
78-
} catch (e) {
79-
// eslint-disable-next-line no-console
80-
console.warn('TotalPeopleReport: Failed to parse cached data', e);
81-
}
65+
// Check cache with date range key
66+
const cacheKey = `${reportName}_${fromDate}_${toDate}`;
67+
const cached = getCachedData(cacheKey, reportName);
68+
if (cached.data) {
69+
setAllTimeEntries(cached.data);
70+
setTotalPeopleReportDataLoading(false);
71+
setTotalPeopleReportDataReady(true);
72+
return;
8273
}
8374

8475
try {
85-
// eslint-disable-next-line no-console
86-
console.log('TotalPeopleReport API Request:', {
87-
url,
88-
payload: { users: userList, fromDate, toDate },
76+
logApiRequest(reportName, url, { users: userList, fromDate, toDate }, {
8977
usersCount: userList?.length,
9078
userProfilesCount: userProfiles?.length,
91-
timestamp: new Date().toISOString(),
9279
});
80+
9381
const res = await axios.post(
9482
url,
9583
{ users: userList, fromDate, toDate },
9684
{ signal: controller.signal },
9785
);
98-
// eslint-disable-next-line no-console
99-
console.log('TotalPeopleReport API Response:', {
100-
dataLength: res.data?.length,
101-
sampleData: res.data?.slice(0, 2),
102-
timestamp: new Date().toISOString(),
103-
responseTime: new Date().toISOString(),
104-
});
105-
86+
87+
logApiResponse(reportName, res.data?.length, res.data?.slice(0, 2));
88+
10689
const timeEntries = res.data.map(entry => ({
10790
userId: entry.personId,
10891
hours: entry.hours,
10992
minutes: entry.minutes,
11093
isTangible: entry.isTangible,
11194
date: entry.dateOfWork,
11295
}));
113-
114-
// Log if response seems incomplete (very few entries for many users)
115-
if (timeEntries.length > 0 && userList.length > 100 && timeEntries.length < 10) {
116-
// eslint-disable-next-line no-console
117-
console.warn('TotalPeopleReport: Response may be incomplete', {
118-
timeEntriesCount: timeEntries.length,
119-
usersCount: userList.length,
120-
ratio: (timeEntries.length / userList.length * 100).toFixed(2) + '%',
121-
message: 'If data seems incomplete, backend may still be processing. Try refreshing in a few minutes.',
122-
});
123-
}
124-
96+
97+
checkIncompleteResponse(reportName, timeEntries.length, userList.length);
98+
12599
setAllTimeEntries(timeEntries);
126-
127-
// Cache the data with date range key
128-
if (timeEntries.length > 0) {
129-
localStorage.setItem(cacheKey, JSON.stringify(timeEntries));
130-
// eslint-disable-next-line no-console
131-
console.log('TotalPeopleReport: Data cached', { cacheKey, dataLength: timeEntries.length });
132-
} else {
133-
// eslint-disable-next-line no-console
134-
console.warn('TotalPeopleReport: Empty response - clearing cache', { cacheKey });
135-
localStorage.removeItem(cacheKey);
136-
}
100+
setCachedData(cacheKey, timeEntries, reportName);
137101
} catch (error) {
138102
// eslint-disable-next-line no-console
139-
console.error('TotalPeopleReport API Error:', error);
103+
console.error(`${reportName} API Error:`, error);
140104
setTotalPeopleReportDataLoading(false);
141105
}
142106
},

0 commit comments

Comments
 (0)