icleafreportui 0.2.11 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/App.js CHANGED
@@ -8,7 +8,8 @@ import ExamPackReport from './Reports/ExamPackReport';
8
8
  import { TenantProvider } from './context/TenantProvider'; // ADD THIS
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const App = () => {
11
- const userToken = localStorage.getItem("token");
11
+ // const userToken = localStorage.getItem("token")
12
+ const tenantToken = localStorage.getItem("tenantToken");
12
13
 
13
14
  // Configuration for API calls
14
15
  const config = {
@@ -23,10 +24,10 @@ const App = () => {
23
24
  children: /*#__PURE__*/_jsxs(Routes, {
24
25
  children: [/*#__PURE__*/_jsx(Route, {
25
26
  path: "/",
26
- element: userToken != null ? /*#__PURE__*/_jsx(Report, {}) : /*#__PURE__*/_jsx(Login, {})
27
+ element: tenantToken != null ? /*#__PURE__*/_jsx(Report, {}) : /*#__PURE__*/_jsx(Login, {})
27
28
  }), /*#__PURE__*/_jsx(Route, {
28
29
  path: "/login",
29
- element: userToken != null ? /*#__PURE__*/_jsx(Report, {}) : /*#__PURE__*/_jsx(Login, {})
30
+ element: tenantToken != null ? /*#__PURE__*/_jsx(Report, {}) : /*#__PURE__*/_jsx(Login, {})
30
31
  }), /*#__PURE__*/_jsx(Route, {
31
32
  path: "/report",
32
33
  element: /*#__PURE__*/_jsx(Report, {})
package/dist/Login.js CHANGED
@@ -41,29 +41,69 @@ const Login = () => {
41
41
  return "icleaf";
42
42
  };
43
43
  const baseURL = process.env.REACT_APP_BASE_URL;
44
+
45
+ // const handleLogin = async (e) => {
46
+ // e.preventDefault();
47
+
48
+ // const subdomain = getSubDomain();
49
+ // try {
50
+ // // const response = await axios.get(`${baseURL}` + "api/login?userName=" + username + "&password=" + password);
51
+ // const response = await axios.get(
52
+ // `${baseURL}api/login?userName=${username}&password=${password}&subdomain=${subdomain}`
53
+ // );
54
+ // console.log(response, "response")
55
+ // if (response.data) {
56
+ // var res = response.data;
57
+ // if (res == "User Not Found") {
58
+ // setError(res);
59
+ // setOpenAlert(true);
60
+ // } else if (res == "UserName or Password cannot be empty") {
61
+ // setError(res);
62
+ // setOpenAlert(true);
63
+ // } else {
64
+ // localStorage.setItem("token", response.data);
65
+ // localStorage.setItem("subdomain", subdomain);
66
+ // navigate('/Report');
67
+
68
+ // }
69
+ // }
70
+
71
+ // } catch (error) {
72
+ // setError('User Not Found');
73
+ // setOpenAlert(true);
74
+ // }
75
+ // };
76
+
44
77
  const handleLogin = async e => {
45
78
  e.preventDefault();
46
79
  const subdomain = getSubDomain();
47
80
  try {
48
- // const response = await axios.get(`${baseURL}` + "api/login?userName=" + username + "&password=" + password);
49
- const response = await axios.get(`${baseURL}api/login?userName=${username}&password=${password}&subdomain=${subdomain}`);
50
- console.log(response, "response");
51
- if (response.data) {
52
- var res = response.data;
53
- if (res == "User Not Found") {
54
- setError(res);
55
- setOpenAlert(true);
56
- } else if (res == "UserName or Password cannot be empty") {
81
+ const response = await axios.get(`${baseURL}/api/login?userName=${username}&password=${password}&subdomain=${subdomain}`);
82
+ console.log("Response data:", response.data);
83
+ console.log("Type of response:", typeof response.data);
84
+ const res = response.data;
85
+
86
+ // Check if response is an error message (string)
87
+ if (typeof res === 'string') {
88
+ if (res === "User Not Found" || res === "UserName or Password cannot be empty" || res === "Invalid Company" || res === "User not allowed") {
57
89
  setError(res);
58
90
  setOpenAlert(true);
59
- } else {
60
- localStorage.setItem("token", response.data);
61
- localStorage.setItem("subdomain", subdomain);
62
- navigate('/Report');
91
+ return;
63
92
  }
64
93
  }
94
+
95
+ // If we reach here, it's a success (tenant token)
96
+ if (res) {
97
+ localStorage.setItem("tenantToken", res);
98
+ localStorage.setItem("subdomain", subdomain);
99
+ navigate('/Report');
100
+ } else {
101
+ setError("Login failed");
102
+ setOpenAlert(true);
103
+ }
65
104
  } catch (error) {
66
- setError('User Not Found');
105
+ console.error("Login error:", error);
106
+ setError(error.response?.data || "User Not Found");
67
107
  setOpenAlert(true);
68
108
  }
69
109
  };
@@ -8,7 +8,8 @@ import '../App.css';
8
8
  import { useTenant } from '../context/TenantProvider';
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  function CourseReport() {
11
- const [token, setToken] = useState(localStorage.getItem("token"));
11
+ // const [token, setToken] = useState(localStorage.getItem("token"));
12
+ const tenantToken = localStorage.getItem("tenantToken");
12
13
  const navigate = useNavigate();
13
14
  const [subjects, setSubjects] = useState([]);
14
15
  const [courses, setCourses] = useState([]);
@@ -24,7 +25,7 @@ function CourseReport() {
24
25
  apiClient
25
26
  } = useTenant();
26
27
  useEffect(() => {
27
- if (token == null) {
28
+ if (tenantToken == null) {
28
29
  navigate("/login");
29
30
  } else {
30
31
  fetchAllSubjects();
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect, useRef } from 'react';
2
- import axios from 'axios';
2
+ // import axios from 'axios'; // ❌ OLD - Commented
3
3
  import { Autocomplete, FormControl, Button, Grid, Box, Typography, Paper, Snackbar, Alert, CircularProgress, TextField, Checkbox, InputAdornment } from '@mui/material';
4
4
  import { useNavigate } from 'react-router-dom';
5
5
  import Header from '../components/Header';
@@ -9,10 +9,16 @@ import Backdrop from '@mui/material/Backdrop';
9
9
  import { DataGrid } from '@mui/x-data-grid';
10
10
  import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
11
11
  import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined';
12
+ import { useTenant } from '../context/TenantProvider'; // ✅ NEW - Add this
12
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
14
  function ExamPackReport() {
14
- const [token] = useState(localStorage.getItem("token"));
15
+ // const [token] = useState(localStorage.getItem("token")); // ❌ OLD - Commented
16
+ const tenantToken = localStorage.getItem("tenantToken"); // ✅ NEW
15
17
  const navigate = useNavigate();
18
+ const {
19
+ apiClient
20
+ } = useTenant(); // ✅ NEW - Add this
21
+
16
22
  const [subjects, setSubjects] = useState([]);
17
23
  const [courses, setCourses] = useState([]);
18
24
  const [selectedSubject, setSelectedSubject] = useState(null);
@@ -44,10 +50,8 @@ function ExamPackReport() {
44
50
  const localPart = email.split('@')[0];
45
51
  return searchTerms.some(term => {
46
52
  if (term.includes('@')) {
47
- // Exact full email match
48
53
  return email === term;
49
54
  } else {
50
- // Match with the part before @
51
55
  return localPart.includes(term);
52
56
  }
53
57
  });
@@ -67,7 +71,7 @@ function ExamPackReport() {
67
71
  headerName: 'Status',
68
72
  width: 170,
69
73
  renderCell: params => {
70
- const isActive = params.value; // Assuming it's a boolean (true/false)
74
+ const isActive = params.value;
71
75
  return /*#__PURE__*/_jsx("span", {
72
76
  style: {
73
77
  color: isActive ? 'green' : 'red',
@@ -141,39 +145,59 @@ function ExamPackReport() {
141
145
  })
142
146
  }];
143
147
  useEffect(() => {
144
- if (token == null) {
148
+ // if (token == null) { // ❌ OLD - Commented
149
+ if (tenantToken == null) {
150
+ // ✅ NEW
145
151
  navigate("/login");
146
152
  } else {
147
153
  fetchAllSubjects();
148
154
  }
149
155
  }, []);
156
+
157
+ // ❌ OLD - Commented
158
+ // const fetchAllSubjects = async () => {
159
+ // try {
160
+ // const response = await axios({
161
+ // method: "get",
162
+ // url: `${baseURL}api/showAllSubjects`,
163
+ // headers: { Authorization: `Bearer ${token}` },
164
+ // });
165
+ // setSubjects(response.data);
166
+ // } catch (error) {
167
+ // console.error('Error fetching subjects:', error);
168
+ // }
169
+ // };
170
+
171
+ // ✅ NEW - Using apiClient
150
172
  const fetchAllSubjects = async () => {
151
173
  try {
152
- const response = await axios({
153
- method: "get",
154
- url: `${baseURL}api/showAllSubjects`,
155
- headers: {
156
- Authorization: `Bearer ${token}`
157
- }
158
- });
159
- setSubjects(response.data);
174
+ const data = await apiClient.get('/api/showAllSubjects');
175
+ setSubjects(data);
160
176
  } catch (error) {
161
177
  console.error('Error fetching subjects:', error);
162
178
  }
163
179
  };
180
+
181
+ // ❌ OLD - Commented
182
+ // const fetchCourses = async (subjectId) => {
183
+ // try {
184
+ // const response = await axios({
185
+ // method: "get",
186
+ // params: { subjectId },
187
+ // url: `${baseURL}api/getCoursesBySubject`,
188
+ // headers: { Authorization: `Bearer ${token}` },
189
+ // });
190
+ // setCourses(response.data);
191
+ // } catch (error) {
192
+ // console.error('Error fetching courses:', error);
193
+ // }
194
+ // };
195
+
196
+ // ✅ NEW - Using apiClient
164
197
  const fetchCourses = async subjectId => {
165
198
  try {
166
- const response = await axios({
167
- method: "get",
168
- params: {
169
- subjectId
170
- },
171
- url: `${baseURL}api/getCoursesBySubject`,
172
- headers: {
173
- Authorization: `Bearer ${token}`
174
- }
175
- });
176
- setCourses(response.data);
199
+ const data = await apiClient.get(`/api/getCoursesBySubject?subjectId=${subjectId}`);
200
+ setCourses(data);
177
201
  } catch (error) {
178
202
  console.error('Error fetching courses:', error);
179
203
  }
@@ -208,24 +232,47 @@ function ExamPackReport() {
208
232
  };
209
233
  apiMap[reportType]?.(courseId);
210
234
  };
235
+
236
+ // ❌ OLD - Commented
237
+ // const getBatchWiseList = async () => {
238
+ // setLoading(true)
239
+ // try {
240
+ // const response = await axios.get(
241
+ // `${baseURL}api/getCorpCourseBatches?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`,
242
+ // { headers: { Authorization: `Bearer ${token}` } }
243
+ // );
244
+ // if (response.status === 200) {
245
+ // setUserSelect(false)
246
+ // setRows(response.data.corpCourseBatches)
247
+ // setColumns(batchListColumns)
248
+ // setTableShow(true)
249
+ // }
250
+ // } catch (error) {
251
+ // setAlertOpen(true)
252
+ // setAlertMessage(error.response.data.error)
253
+ // setTableShow(false)
254
+ // setRows([])
255
+ // setColumns([])
256
+ // console.error("Error fetching batch-wise data:", error);
257
+ // } finally {
258
+ // setLoading(false)
259
+ // }
260
+ // };
261
+
262
+ // ✅ NEW - Using apiClient
211
263
  const getBatchWiseList = async () => {
212
264
  setLoading(true);
213
265
  try {
214
- const response = await axios.get(`${baseURL}api/getCorpCourseBatches?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`, {
215
- headers: {
216
- Authorization: `Bearer ${token}`
217
- }
218
- });
219
- if (response.status === 200) {
266
+ const data = await apiClient.get(`/api/getCorpCourseBatches?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`);
267
+ if (data) {
220
268
  setUserSelect(false);
221
- setRows(response.data.corpCourseBatches);
269
+ setRows(data.corpCourseBatches || []);
222
270
  setColumns(batchListColumns);
223
271
  setTableShow(true);
224
272
  }
225
- console.log(response.data, "Batch Wise");
226
273
  } catch (error) {
227
274
  setAlertOpen(true);
228
- setAlertMessage(error.response.data.error);
275
+ setAlertMessage(error.response?.data?.error || 'Error fetching batch data');
229
276
  setTableShow(false);
230
277
  setRows([]);
231
278
  setColumns([]);
@@ -234,28 +281,51 @@ function ExamPackReport() {
234
281
  setLoading(false);
235
282
  }
236
283
  };
284
+
285
+ // ❌ OLD - Commented
286
+ // const getUserWiseList = async () => {
287
+ // setLoading(true)
288
+ // try {
289
+ // const response = await axios.get(
290
+ // `${baseURL}api/getCorpCourseUsers?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`,
291
+ // { headers: { Authorization: `Bearer ${token}` } }
292
+ // );
293
+ // if (response.status === 200) {
294
+ // setRows(response.data.users)
295
+ // setColumns(userListColumns)
296
+ // setTableShow(true)
297
+ // setUserSelect(true)
298
+ // }
299
+ // } catch (error) {
300
+ // setAlertOpen(true)
301
+ // setAlertMessage(error.response.data.error)
302
+ // setTableShow(false)
303
+ // setRows([])
304
+ // setColumns([])
305
+ // console.error("Error fetching batch-wise data:", error);
306
+ // } finally {
307
+ // setLoading(false)
308
+ // }
309
+ // };
310
+
311
+ // ✅ NEW - Using apiClient
237
312
  const getUserWiseList = async () => {
238
313
  setLoading(true);
239
314
  try {
240
- const response = await axios.get(`${baseURL}api/getCorpCourseUsers?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`, {
241
- headers: {
242
- Authorization: `Bearer ${token}`
243
- }
244
- });
245
- if (response.status === 200) {
246
- setRows(response.data.users);
315
+ const data = await apiClient.get(`/api/getCorpCourseUsers?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`);
316
+ if (data) {
317
+ setRows(data.users || []);
247
318
  setColumns(userListColumns);
248
319
  setTableShow(true);
249
320
  setUserSelect(true);
250
321
  }
251
- console.log(response.data, "User Wise");
252
322
  } catch (error) {
253
323
  setAlertOpen(true);
254
- setAlertMessage(error.response.data.error);
324
+ setAlertMessage(error.response?.data?.error || 'Error fetching user data');
255
325
  setTableShow(false);
256
326
  setRows([]);
257
327
  setColumns([]);
258
- console.error("Error fetching batch-wise data:", error);
328
+ console.error("Error fetching user-wise data:", error);
259
329
  } finally {
260
330
  setLoading(false);
261
331
  }
@@ -263,27 +333,47 @@ function ExamPackReport() {
263
333
  const handleRowSelection = newSelection => {
264
334
  setSelectedUserList(newSelection);
265
335
  };
336
+
337
+ // ❌ OLD - Commented
338
+ // const handleDownloadBatchReport = async (item) => {
339
+ // setLoading(true)
340
+ // try {
341
+ // let url;
342
+ // url = `${baseURL}api/downloadCourseAndBatchWiseReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}&batchId=${item.id}`
343
+ // const response = await axios.post(url, {}, {
344
+ // responseType: 'blob',
345
+ // headers: { Authorization: `Bearer ${token}` }
346
+ // });
347
+ // // ... rest of download logic
348
+ // } catch (error) {
349
+ // // ... error handling
350
+ // } finally {
351
+ // setLoading(false)
352
+ // }
353
+ // }
354
+
355
+ // ✅ NEW - Using fetch with tenant token
266
356
  const handleDownloadBatchReport = async item => {
267
357
  setLoading(true);
268
358
  try {
269
- let url;
270
- url = `${baseURL}api/downloadCourseAndBatchWiseReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}&batchId=${item.id}`;
271
- const response = await axios.post(url, {}, {
272
- responseType: 'blob',
359
+ const url = `${baseURL}/api/downloadCourseAndBatchWiseReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}&batchId=${item.id}`;
360
+ const response = await fetch(url, {
361
+ method: 'POST',
273
362
  headers: {
274
- Authorization: `Bearer ${token}`
363
+ 'X-Tenant-Token': apiClient.tenantToken
275
364
  }
276
365
  });
277
- const text = await response.data.text();
366
+ const blob = await response.blob();
367
+ const text = await blob.text();
278
368
  if (text.includes('Course not configured')) {
279
369
  setAlertMessage('Course not configured.');
280
370
  setAlertOpen(true);
281
371
  } else {
282
372
  const filename = `${item.batchName}_Batch_Report.xlsx`;
283
- const blob = new Blob([response.data], {
373
+ const downloadBlob = new Blob([blob], {
284
374
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
285
375
  });
286
- const blobUrl = URL.createObjectURL(blob);
376
+ const blobUrl = URL.createObjectURL(downloadBlob);
287
377
  const link = document.createElement('a');
288
378
  link.href = blobUrl;
289
379
  link.setAttribute('download', filename);
@@ -294,33 +384,38 @@ function ExamPackReport() {
294
384
  }
295
385
  } catch (error) {
296
386
  setAlertOpen(true);
297
- setAlertMessage(error.response.data.error);
387
+ setAlertMessage(error.message || 'Error downloading report');
298
388
  console.error('Error downloading course report:', error);
299
389
  } finally {
300
390
  setLoading(false);
301
391
  }
302
392
  };
393
+
394
+ // ❌ OLD - Commented (similar pattern for other download functions)
395
+ // const handleDownloadSingleUserReport = async (item) => { ... }
396
+ // const handleSummeryDownload = async () => { ... }
397
+
398
+ // ✅ NEW - handleDownloadSingleUserReport
303
399
  const handleDownloadSingleUserReport = async item => {
304
400
  setLoading(true);
305
401
  try {
306
- let url;
307
- url = `${baseURL}api/downloadExamPackReportByCourse?userId=${item.id}&corpCourseId=${selectedCourse.id}&subjectId=${selectedSubject.subjectId}`;
308
- const response = await axios.get(url, {
309
- responseType: 'blob',
402
+ const url = `${baseURL}/api/downloadExamPackReportByCourse?userId=${item.id}&corpCourseId=${selectedCourse.id}&subjectId=${selectedSubject.subjectId}`;
403
+ const response = await fetch(url, {
310
404
  headers: {
311
- Authorization: `Bearer ${token}`
405
+ 'X-Tenant-Token': apiClient.tenantToken
312
406
  }
313
407
  });
314
- const text = await response.data.text();
408
+ const blob = await response.blob();
409
+ const text = await blob.text();
315
410
  if (text.includes('Course not configured')) {
316
411
  setAlertMessage('Course not configured.');
317
412
  setAlertOpen(true);
318
413
  } else {
319
414
  const filename = `${item.userName}_Pack_Report.xlsx`;
320
- const blob = new Blob([response.data], {
415
+ const downloadBlob = new Blob([blob], {
321
416
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
322
417
  });
323
- const blobUrl = URL.createObjectURL(blob);
418
+ const blobUrl = URL.createObjectURL(downloadBlob);
324
419
  const link = document.createElement('a');
325
420
  link.href = blobUrl;
326
421
  link.setAttribute('download', filename);
@@ -331,36 +426,40 @@ function ExamPackReport() {
331
426
  }
332
427
  } catch (error) {
333
428
  setAlertOpen(true);
334
- setAlertMessage(error.response.data.error);
335
- console.error('Error downloading course report:', error);
429
+ setAlertMessage(error.message || 'Error downloading report');
430
+ console.error('Error downloading user report:', error);
336
431
  } finally {
337
432
  setLoading(false);
338
433
  }
339
434
  };
435
+
436
+ // ✅ NEW - handleSummeryDownload
340
437
  const handleSummeryDownload = async () => {
341
438
  setMultiLoading(true);
342
439
  const selectedRowIds = rows.filter(row => selectedUserList.includes(row.id)).map(row => row.id);
343
440
  try {
344
- let url;
345
- url = `${baseURL}api/downloadExamPacksAndUserIdsReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`;
346
- const response = await axios.post(url, {
347
- userIds: selectedRowIds
348
- }, {
349
- responseType: 'blob',
441
+ const url = `${baseURL}/api/downloadExamPacksAndUserIdsReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`;
442
+ const response = await fetch(url, {
443
+ method: 'POST',
350
444
  headers: {
351
- Authorization: `Bearer ${token}`
352
- }
445
+ 'Content-Type': 'application/json',
446
+ 'X-Tenant-Token': apiClient.tenantToken
447
+ },
448
+ body: JSON.stringify({
449
+ userIds: selectedRowIds
450
+ })
353
451
  });
354
- const text = await response.data.text();
452
+ const blob = await response.blob();
453
+ const text = await blob.text();
355
454
  if (text.includes('Course not configured')) {
356
455
  setAlertMessage('Course not configured.');
357
456
  setAlertOpen(true);
358
457
  } else {
359
458
  const filename = 'User_Exam_Pack_Report.xlsx';
360
- const blob = new Blob([response.data], {
459
+ const downloadBlob = new Blob([blob], {
361
460
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
362
461
  });
363
- const blobUrl = URL.createObjectURL(blob);
462
+ const blobUrl = URL.createObjectURL(downloadBlob);
364
463
  const link = document.createElement('a');
365
464
  link.href = blobUrl;
366
465
  link.setAttribute('download', filename);
@@ -371,8 +470,8 @@ function ExamPackReport() {
371
470
  }
372
471
  } catch (error) {
373
472
  setAlertOpen(true);
374
- setAlertMessage(error.response.data.error);
375
- console.error('Error downloading course report:', error);
473
+ setAlertMessage(error.message || 'Error downloading report');
474
+ console.error('Error downloading summary report:', error);
376
475
  } finally {
377
476
  setMultiLoading(false);
378
477
  }
@@ -1,14 +1,20 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import axios from 'axios';
2
+ // import axios from 'axios'; // ❌ OLD - Commented
3
3
  import { Autocomplete, FormControl, Button, Grid, Box, Typography, Paper, Snackbar, Alert, CircularProgress, TextField, Checkbox, FormControlLabel } from '@mui/material';
4
4
  import { useNavigate } from 'react-router-dom';
5
5
  import Header from '../components/Header';
6
6
  import Sidebar from '../components/sidebar';
7
7
  import '../App.css';
8
+ import { useTenant } from '../context/TenantProvider'; // ✅ NEW - Add this
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
10
  function ExamReport() {
10
- const [token, setToken] = useState(localStorage.getItem("token"));
11
+ // const [token, setToken] = useState(localStorage.getItem("token")); // ❌ OLD - Commented
12
+ const tenantToken = localStorage.getItem("tenantToken"); // ✅ NEW
11
13
  const navigate = useNavigate();
14
+ const {
15
+ apiClient
16
+ } = useTenant(); // ✅ NEW - Add this
17
+
12
18
  const [subjects, setSubjects] = useState([]);
13
19
  const [examPacks, setExamPacks] = useState([]);
14
20
  const [exams, setExams] = useState([]);
@@ -22,73 +28,109 @@ function ExamReport() {
22
28
  const [loading, setLoading] = useState(false);
23
29
  const baseURL = process.env.REACT_APP_BASE_URL;
24
30
  useEffect(() => {
25
- if (token == null) {
31
+ // if (token == null) { // ❌ OLD - Commented
32
+ if (tenantToken == null) {
33
+ // ✅ NEW
26
34
  navigate("/login");
27
35
  } else {
28
36
  fetchAllSubjects();
29
37
  }
30
38
  }, []);
39
+
40
+ // ❌ OLD - Commented
41
+ // const fetchAllSubjects = async () => {
42
+ // try {
43
+ // const response = await axios({
44
+ // method: "get",
45
+ // url: `${baseURL}api/showAllSubjects`,
46
+ // headers: { Authorization: `Bearer ${token}` },
47
+ // });
48
+ // setSubjects(response.data);
49
+ // } catch (error) {
50
+ // console.error('Error fetching subjects:', error);
51
+ // }
52
+ // };
53
+
54
+ // ✅ NEW - Using apiClient
31
55
  const fetchAllSubjects = async () => {
32
56
  try {
33
- const response = await axios({
34
- method: "get",
35
- url: `${baseURL}api/showAllSubjects`,
36
- headers: {
37
- Authorization: `Bearer ${token}`
38
- }
39
- });
40
- setSubjects(response.data);
57
+ const data = await apiClient.get('/api/showAllSubjects');
58
+ setSubjects(data);
41
59
  } catch (error) {
42
60
  console.error('Error fetching subjects:', error);
43
61
  }
44
62
  };
63
+
64
+ // ❌ OLD - Commented
65
+ // const fetchExamPacks = async (subjectId) => {
66
+ // try {
67
+ // const response = await axios({
68
+ // method: "get",
69
+ // params: { subjectId },
70
+ // url: `${baseURL}api/getAllExamPacks`,
71
+ // headers: { Authorization: `Bearer ${token}` },
72
+ // });
73
+ // setExamPacks(response.data);
74
+ // } catch (error) {
75
+ // console.error('Error fetching exam packs:', error);
76
+ // }
77
+ // };
78
+
79
+ // ✅ NEW - Using apiClient
45
80
  const fetchExamPacks = async subjectId => {
46
81
  try {
47
- const response = await axios({
48
- method: "get",
49
- params: {
50
- subjectId
51
- },
52
- url: `${baseURL}api/getAllExamPacks`,
53
- headers: {
54
- Authorization: `Bearer ${token}`
55
- }
56
- });
57
- setExamPacks(response.data);
82
+ const data = await apiClient.get(`/api/getAllExamPacks?subjectId=${subjectId}`);
83
+ setExamPacks(data);
58
84
  } catch (error) {
59
85
  console.error('Error fetching exam packs:', error);
60
86
  }
61
87
  };
88
+
89
+ // ❌ OLD - Commented
90
+ // const fetchExams = async (examPackId) => {
91
+ // try {
92
+ // const response = await axios({
93
+ // method: "get",
94
+ // params: { examPackId },
95
+ // url: `${baseURL}api/getAllExams`,
96
+ // headers: { Authorization: `Bearer ${token}` },
97
+ // });
98
+ // setExams(response.data);
99
+ // } catch (error) {
100
+ // console.error('Error fetching exams:', error);
101
+ // }
102
+ // };
103
+
104
+ // ✅ NEW - Using apiClient
62
105
  const fetchExams = async examPackId => {
63
106
  try {
64
- const response = await axios({
65
- method: "get",
66
- params: {
67
- examPackId
68
- },
69
- url: `${baseURL}api/getAllExams`,
70
- headers: {
71
- Authorization: `Bearer ${token}`
72
- }
73
- });
74
- setExams(response.data);
107
+ const data = await apiClient.get(`/api/getAllExams?examPackId=${examPackId}`);
108
+ setExams(data);
75
109
  } catch (error) {
76
110
  console.error('Error fetching exams:', error);
77
111
  }
78
112
  };
113
+
114
+ // ❌ OLD - Commented
115
+ // const fetchUsers = async (examId) => {
116
+ // try {
117
+ // const response = await axios({
118
+ // method: "get",
119
+ // params: { examId },
120
+ // url: `${baseURL}api/getAllUsers`,
121
+ // headers: { Authorization: `Bearer ${token}` },
122
+ // });
123
+ // setUsers(response.data);
124
+ // } catch (error) {
125
+ // console.error('Error fetching users:', error);
126
+ // }
127
+ // };
128
+
129
+ // ✅ NEW - Using apiClient
79
130
  const fetchUsers = async examId => {
80
131
  try {
81
- const response = await axios({
82
- method: "get",
83
- params: {
84
- examId
85
- },
86
- url: `${baseURL}api/getAllUsers`,
87
- headers: {
88
- Authorization: `Bearer ${token}`
89
- }
90
- });
91
- setUsers(response.data);
132
+ const data = await apiClient.get(`/api/getAllUsers?examId=${examId}`);
133
+ setUsers(data);
92
134
  } catch (error) {
93
135
  console.error('Error fetching users:', error);
94
136
  }
@@ -126,19 +168,45 @@ function ExamReport() {
126
168
  const handleUserChange = (event, newValue) => {
127
169
  setSelectedUser(newValue);
128
170
  };
171
+
172
+ // ❌ OLD - Commented
173
+ // const handleDownload = async () => {
174
+ // setLoading(true);
175
+ // try {
176
+ // const url = `${baseURL}api/generateReportForExam?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}`;
177
+ // const response = await axios.get(url, {
178
+ // responseType: 'blob',
179
+ // headers: {
180
+ // Authorization: `Bearer ${token}`
181
+ // }
182
+ // });
183
+ // const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
184
+ // const blobUrl = URL.createObjectURL(blob);
185
+ // const link = document.createElement('a');
186
+ // link.href = blobUrl;
187
+ // link.setAttribute('download', 'QuestionewiseExamReport.xlsx');
188
+ // document.body.appendChild(link);
189
+ // link.click();
190
+ // link.parentNode.removeChild(link);
191
+ // URL.revokeObjectURL(blobUrl);
192
+ // } catch (error) {
193
+ // console.error('Error downloading report:', error);
194
+ // } finally {
195
+ // setLoading(false);
196
+ // }
197
+ // };
198
+
199
+ // ✅ NEW - Using fetch with tenant token
129
200
  const handleDownload = async () => {
130
201
  setLoading(true);
131
202
  try {
132
- const url = `${baseURL}api/generateReportForExam?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}`;
133
- const response = await axios.get(url, {
134
- responseType: 'blob',
203
+ const url = `${baseURL}/api/generateReportForExam?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}`;
204
+ const response = await fetch(url, {
135
205
  headers: {
136
- Authorization: `Bearer ${token}`
206
+ 'X-Tenant-Token': apiClient.tenantToken
137
207
  }
138
208
  });
139
- const blob = new Blob([response.data], {
140
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
141
- });
209
+ const blob = await response.blob();
142
210
  const blobUrl = URL.createObjectURL(blob);
143
211
  const link = document.createElement('a');
144
212
  link.href = blobUrl;
@@ -39,6 +39,7 @@
39
39
  // export default ReportViewer;
40
40
 
41
41
  // ReportViewer.js
42
+
42
43
  import React from 'react';
43
44
  import Header from '../../components/Header';
44
45
  import Sidebar from '../../components/sidebar';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icleafreportui",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "private": false,
5
5
  "main": "dist/package.js",
6
6
  "files": [