icleafreportui 0.2.2 → 0.2.4
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/Reports/Report.js +291 -32
- package/package.json +1 -1
package/dist/Reports/Report.js
CHANGED
|
@@ -1,15 +1,294 @@
|
|
|
1
|
+
// import React, { useState, useEffect } from 'react';
|
|
2
|
+
// import { Autocomplete, FormControl, Button, Grid, Box, Typography, Paper, Snackbar, Alert, CircularProgress, TextField, Checkbox, FormControlLabel } from '@mui/material';
|
|
3
|
+
// import { useNavigate } from 'react-router-dom';
|
|
4
|
+
// import Header from '../components/Header';
|
|
5
|
+
// import Sidebar from '../components/sidebar';
|
|
6
|
+
// import { useTenant } from '../context/TenantProvider'; // ADD THIS
|
|
7
|
+
// import '../App.css';
|
|
8
|
+
|
|
9
|
+
// function Report() {
|
|
10
|
+
// const { apiClient } = useTenant(); // ADD THIS - gets API client with token
|
|
11
|
+
// const navigate = useNavigate();
|
|
12
|
+
// const [subjects, setSubjects] = useState([]);
|
|
13
|
+
// const [examPacks, setExamPacks] = useState([]);
|
|
14
|
+
// const [exams, setExams] = useState([]);
|
|
15
|
+
// const [users, setUsers] = useState([]);
|
|
16
|
+
// const [selectedSubject, setSelectedSubject] = useState(null);
|
|
17
|
+
// const [selectedExamPack, setSelectedExamPack] = useState(null);
|
|
18
|
+
// const [selectedExam, setSelectedExam] = useState(null);
|
|
19
|
+
// const [selectedUser, setSelectedUser] = useState(null);
|
|
20
|
+
// const [alertMessage, setAlertMessage] = useState('');
|
|
21
|
+
// const [openAlert, setOpenAlert] = useState(false);
|
|
22
|
+
// const [loading, setLoading] = useState(false);
|
|
23
|
+
// const [onlyWrongAnswers, setOnlyWrongAnswers] = useState(false);
|
|
24
|
+
|
|
25
|
+
// const baseURL = process.env.REACT_APP_BASE_URL;
|
|
26
|
+
|
|
27
|
+
// useEffect(() => {
|
|
28
|
+
// // REMOVE token check - no more JWT
|
|
29
|
+
// fetchAllSubjects();
|
|
30
|
+
// }, []);
|
|
31
|
+
|
|
32
|
+
// const fetchAllSubjects = async () => {
|
|
33
|
+
// try {
|
|
34
|
+
// // OLD WAY with axios and JWT
|
|
35
|
+
// // const response = await axios({
|
|
36
|
+
// // method: "get",
|
|
37
|
+
// // url: `${baseURL}api/showAllSubjects`,
|
|
38
|
+
// // headers: { Authorization: `Bearer ${token}` },
|
|
39
|
+
// // });
|
|
40
|
+
|
|
41
|
+
// // NEW WAY with apiClient
|
|
42
|
+
// const data = await apiClient.get('/api/showAllSubjects');
|
|
43
|
+
// setSubjects(data);
|
|
44
|
+
// } catch (error) {
|
|
45
|
+
// console.error('Error fetching subjects:', error);
|
|
46
|
+
// }
|
|
47
|
+
// };
|
|
48
|
+
|
|
49
|
+
// const fetchExamPacks = async (subjectId) => {
|
|
50
|
+
// try {
|
|
51
|
+
// // OLD WAY
|
|
52
|
+
// // const response = await axios({
|
|
53
|
+
// // method: "get",
|
|
54
|
+
// // params: { subjectId },
|
|
55
|
+
// // url: `${baseURL}api/getAllExamPacks`,
|
|
56
|
+
// // headers: { Authorization: `Bearer ${token}` },
|
|
57
|
+
// // });
|
|
58
|
+
|
|
59
|
+
// // NEW WAY
|
|
60
|
+
// const data = await apiClient.get(`/api/getAllExamPacks?subjectId=${subjectId}`);
|
|
61
|
+
// setExamPacks(data);
|
|
62
|
+
// } catch (error) {
|
|
63
|
+
// console.error('Error fetching exam packs:', error);
|
|
64
|
+
// }
|
|
65
|
+
// };
|
|
66
|
+
|
|
67
|
+
// const fetchExams = async (examPackId) => {
|
|
68
|
+
// try {
|
|
69
|
+
// const data = await apiClient.get(`/api/getAllExams?examPackId=${examPackId}`);
|
|
70
|
+
// setExams(data);
|
|
71
|
+
// } catch (error) {
|
|
72
|
+
// console.error('Error fetching exams:', error);
|
|
73
|
+
// }
|
|
74
|
+
// };
|
|
75
|
+
|
|
76
|
+
// const fetchUsers = async (examId) => {
|
|
77
|
+
// try {
|
|
78
|
+
// const data = await apiClient.get(`/api/getAllUsers?examId=${examId}`);
|
|
79
|
+
// setUsers(data);
|
|
80
|
+
// } catch (error) {
|
|
81
|
+
// console.error('Error fetching users:', error);
|
|
82
|
+
// }
|
|
83
|
+
// };
|
|
84
|
+
|
|
85
|
+
// const handleSubjectChange = (event, newValue) => {
|
|
86
|
+
// setSelectedSubject(newValue);
|
|
87
|
+
// setSelectedExamPack(null);
|
|
88
|
+
// setSelectedExam(null);
|
|
89
|
+
// setSelectedUser(null);
|
|
90
|
+
// setExamPacks([]);
|
|
91
|
+
// setExams([]);
|
|
92
|
+
// setUsers([]);
|
|
93
|
+
// if (newValue) {
|
|
94
|
+
// fetchExamPacks(newValue.subjectId);
|
|
95
|
+
// }
|
|
96
|
+
// };
|
|
97
|
+
|
|
98
|
+
// const handleExamPackChange = (event, newValue) => {
|
|
99
|
+
// setSelectedExamPack(newValue);
|
|
100
|
+
// setSelectedExam(null);
|
|
101
|
+
// setSelectedUser(null);
|
|
102
|
+
// setExams([]);
|
|
103
|
+
// setUsers([]);
|
|
104
|
+
// if (newValue) {
|
|
105
|
+
// fetchExams(newValue.id);
|
|
106
|
+
// }
|
|
107
|
+
// };
|
|
108
|
+
|
|
109
|
+
// const handleExamChange = (event, newValue) => {
|
|
110
|
+
// setSelectedExam(newValue);
|
|
111
|
+
// setSelectedUser(null);
|
|
112
|
+
// setUsers([]);
|
|
113
|
+
// if (newValue) {
|
|
114
|
+
// fetchUsers(newValue.id);
|
|
115
|
+
// }
|
|
116
|
+
// };
|
|
117
|
+
|
|
118
|
+
// const handleUserChange = (event, newValue) => {
|
|
119
|
+
// setSelectedUser(newValue);
|
|
120
|
+
// };
|
|
121
|
+
|
|
122
|
+
// const handleDownload = async () => {
|
|
123
|
+
// setLoading(true);
|
|
124
|
+
// try {
|
|
125
|
+
// // OLD WAY with axios
|
|
126
|
+
// // const url = `${baseURL}api/generateReportForSingleUser?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}&userId=${selectedUser.id}&wrongAnswerFlag=${onlyWrongAnswers}`;
|
|
127
|
+
// // const response = await axios.get(url, {
|
|
128
|
+
// // responseType: 'blob',
|
|
129
|
+
// // headers: { Authorization: `Bearer ${token}` }
|
|
130
|
+
// // });
|
|
131
|
+
|
|
132
|
+
// // NEW WAY - need blob response
|
|
133
|
+
// const response = await fetch(`${baseURL}api/generateReportForSingleUser?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}&userId=${selectedUser.id}&wrongAnswerFlag=${onlyWrongAnswers}`, {
|
|
134
|
+
// headers: {
|
|
135
|
+
// 'X-Tenant-Token': apiClient.tenantToken
|
|
136
|
+
// }
|
|
137
|
+
// });
|
|
138
|
+
|
|
139
|
+
// const blob = await response.blob();
|
|
140
|
+
// const blobUrl = URL.createObjectURL(blob);
|
|
141
|
+
// const link = document.createElement('a');
|
|
142
|
+
// link.href = blobUrl;
|
|
143
|
+
// link.setAttribute('download', 'Report.xlsx');
|
|
144
|
+
// document.body.appendChild(link);
|
|
145
|
+
// link.click();
|
|
146
|
+
// link.parentNode.removeChild(link);
|
|
147
|
+
// URL.revokeObjectURL(blobUrl);
|
|
148
|
+
// } catch (error) {
|
|
149
|
+
// console.error('Error downloading report:', error);
|
|
150
|
+
// } finally {
|
|
151
|
+
// setLoading(false);
|
|
152
|
+
// }
|
|
153
|
+
// };
|
|
154
|
+
|
|
155
|
+
// return (
|
|
156
|
+
// <div>
|
|
157
|
+
// <Header />
|
|
158
|
+
// <Sidebar />
|
|
159
|
+
// <div style={{ padding: "100px 0px 0px 100px", marginLeft: "140px" }}>
|
|
160
|
+
// <Box sx={{ maxWidth: 800, mx: 'auto', my: 4, p: 3, backgroundColor: '#f5f5f5', borderRadius: 2 }}>
|
|
161
|
+
// <Paper elevation={6} sx={{ p: 5, textAlign: 'center', backgroundColor: '#fff' }}>
|
|
162
|
+
// <Typography variant="h4" component="h1" gutterBottom sx={{ color: '#3f51b5', marginBottom: "20px" }}>
|
|
163
|
+
// Exam Report
|
|
164
|
+
// </Typography>
|
|
165
|
+
// <Grid container spacing={2} justifyContent="center">
|
|
166
|
+
// <Grid item xs={12} sm={6}>
|
|
167
|
+
// <FormControl fullWidth>
|
|
168
|
+
// <Autocomplete
|
|
169
|
+
// id="ddlSubject"
|
|
170
|
+
// options={subjects}
|
|
171
|
+
// getOptionLabel={(option) => option.subjectName}
|
|
172
|
+
// value={selectedSubject}
|
|
173
|
+
// onChange={handleSubjectChange}
|
|
174
|
+
// renderInput={(params) => <TextField {...params} label="Subject" />}
|
|
175
|
+
// />
|
|
176
|
+
// </FormControl>
|
|
177
|
+
// </Grid>
|
|
178
|
+
|
|
179
|
+
// <Grid item xs={12} sm={6}>
|
|
180
|
+
// <FormControl fullWidth>
|
|
181
|
+
// <Autocomplete
|
|
182
|
+
// id="ddlExamPack"
|
|
183
|
+
// options={examPacks}
|
|
184
|
+
// getOptionLabel={(option) => option.name}
|
|
185
|
+
// value={selectedExamPack}
|
|
186
|
+
// onChange={handleExamPackChange}
|
|
187
|
+
// renderInput={(params) => <TextField {...params} label="Exam Pack" />}
|
|
188
|
+
// />
|
|
189
|
+
// </FormControl>
|
|
190
|
+
// </Grid>
|
|
191
|
+
|
|
192
|
+
// <Grid item xs={12} sm={6}>
|
|
193
|
+
// <FormControl fullWidth>
|
|
194
|
+
// <Autocomplete
|
|
195
|
+
// id="ddlExam"
|
|
196
|
+
// options={exams}
|
|
197
|
+
// getOptionLabel={(option) => option.examName}
|
|
198
|
+
// value={selectedExam}
|
|
199
|
+
// onChange={handleExamChange}
|
|
200
|
+
// renderInput={(params) => <TextField {...params} label="Exam" />}
|
|
201
|
+
// />
|
|
202
|
+
// </FormControl>
|
|
203
|
+
// </Grid>
|
|
204
|
+
|
|
205
|
+
// <Grid item xs={12} sm={6}>
|
|
206
|
+
// <FormControl fullWidth>
|
|
207
|
+
// <Autocomplete
|
|
208
|
+
// id="ddlUser"
|
|
209
|
+
// options={users}
|
|
210
|
+
// getOptionLabel={(option) => option.userName}
|
|
211
|
+
// value={selectedUser}
|
|
212
|
+
// onChange={handleUserChange}
|
|
213
|
+
// renderInput={(params) => <TextField {...params} label="User" />}
|
|
214
|
+
// />
|
|
215
|
+
// </FormControl>
|
|
216
|
+
// </Grid>
|
|
217
|
+
// </Grid>
|
|
218
|
+
|
|
219
|
+
// <Box sx={{ mt: 3, position: 'relative' }}>
|
|
220
|
+
// <FormControlLabel
|
|
221
|
+
// control={
|
|
222
|
+
// <Checkbox
|
|
223
|
+
// checked={onlyWrongAnswers}
|
|
224
|
+
// onChange={(e) => setOnlyWrongAnswers(e.target.checked)}
|
|
225
|
+
// />
|
|
226
|
+
// }
|
|
227
|
+
// label="Only Wrong Answers"
|
|
228
|
+
// />
|
|
229
|
+
// <Box sx={{ mt: 2, position: 'relative' }}>
|
|
230
|
+
// <Button
|
|
231
|
+
// variant="contained"
|
|
232
|
+
// color="primary"
|
|
233
|
+
// onClick={handleDownload}
|
|
234
|
+
// disabled={!selectedSubject || !selectedExamPack || !selectedExam || !selectedUser || loading}
|
|
235
|
+
// sx={{ width: 'auto', backgroundColor: '#3f51b5', '&:hover': { backgroundColor: '#303f9f' } }}
|
|
236
|
+
// >
|
|
237
|
+
// {loading ? 'Downloading...' : 'Download Report'}
|
|
238
|
+
// </Button>
|
|
239
|
+
// {loading && (
|
|
240
|
+
// <CircularProgress
|
|
241
|
+
// size={24}
|
|
242
|
+
// sx={{
|
|
243
|
+
// position: 'absolute',
|
|
244
|
+
// top: '50%',
|
|
245
|
+
// left: '50%',
|
|
246
|
+
// marginTop: '-12px',
|
|
247
|
+
// marginLeft: '-12px',
|
|
248
|
+
// }}
|
|
249
|
+
// />
|
|
250
|
+
// )}
|
|
251
|
+
// </Box>
|
|
252
|
+
// </Box>
|
|
253
|
+
// </Paper>
|
|
254
|
+
// </Box>
|
|
255
|
+
|
|
256
|
+
// <Snackbar
|
|
257
|
+
// open={openAlert}
|
|
258
|
+
// autoHideDuration={6000}
|
|
259
|
+
// onClose={() => setOpenAlert(false)}
|
|
260
|
+
// anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
|
|
261
|
+
// >
|
|
262
|
+
// <Alert onClose={() => setOpenAlert(false)} severity="info" sx={{ width: '100%' }}>
|
|
263
|
+
// {alertMessage}
|
|
264
|
+
// </Alert>
|
|
265
|
+
// </Snackbar>
|
|
266
|
+
// </div>
|
|
267
|
+
// </div>
|
|
268
|
+
// );
|
|
269
|
+
// }
|
|
270
|
+
|
|
271
|
+
// export default Report;
|
|
272
|
+
|
|
1
273
|
import React, { useState, useEffect } from 'react';
|
|
2
274
|
import { Autocomplete, FormControl, Button, Grid, Box, Typography, Paper, Snackbar, Alert, CircularProgress, TextField, Checkbox, FormControlLabel } from '@mui/material';
|
|
3
275
|
import { useNavigate } from 'react-router-dom';
|
|
4
276
|
import Header from '../components/Header';
|
|
5
277
|
import Sidebar from '../components/sidebar';
|
|
6
|
-
import { useTenant } from '../context/TenantProvider';
|
|
278
|
+
import { useTenant } from '../context/TenantProvider';
|
|
7
279
|
import '../App.css';
|
|
8
280
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
function Report() {
|
|
281
|
+
function Report(_ref) {
|
|
282
|
+
let {
|
|
283
|
+
embedded = false,
|
|
284
|
+
// If true, hide Header and Sidebar
|
|
285
|
+
showHeader = true,
|
|
286
|
+
// Control header visibility
|
|
287
|
+
showSidebar = true // Control sidebar visibility
|
|
288
|
+
} = _ref;
|
|
10
289
|
const {
|
|
11
290
|
apiClient
|
|
12
|
-
} = useTenant();
|
|
291
|
+
} = useTenant();
|
|
13
292
|
const navigate = useNavigate();
|
|
14
293
|
const [subjects, setSubjects] = useState([]);
|
|
15
294
|
const [examPacks, setExamPacks] = useState([]);
|
|
@@ -25,19 +304,10 @@ function Report() {
|
|
|
25
304
|
const [onlyWrongAnswers, setOnlyWrongAnswers] = useState(false);
|
|
26
305
|
const baseURL = process.env.REACT_APP_BASE_URL;
|
|
27
306
|
useEffect(() => {
|
|
28
|
-
// REMOVE token check - no more JWT
|
|
29
307
|
fetchAllSubjects();
|
|
30
308
|
}, []);
|
|
31
309
|
const fetchAllSubjects = async () => {
|
|
32
310
|
try {
|
|
33
|
-
// OLD WAY with axios and JWT
|
|
34
|
-
// const response = await axios({
|
|
35
|
-
// method: "get",
|
|
36
|
-
// url: `${baseURL}api/showAllSubjects`,
|
|
37
|
-
// headers: { Authorization: `Bearer ${token}` },
|
|
38
|
-
// });
|
|
39
|
-
|
|
40
|
-
// NEW WAY with apiClient
|
|
41
311
|
const data = await apiClient.get('/api/showAllSubjects');
|
|
42
312
|
setSubjects(data);
|
|
43
313
|
} catch (error) {
|
|
@@ -46,15 +316,6 @@ function Report() {
|
|
|
46
316
|
};
|
|
47
317
|
const fetchExamPacks = async subjectId => {
|
|
48
318
|
try {
|
|
49
|
-
// OLD WAY
|
|
50
|
-
// const response = await axios({
|
|
51
|
-
// method: "get",
|
|
52
|
-
// params: { subjectId },
|
|
53
|
-
// url: `${baseURL}api/getAllExamPacks`,
|
|
54
|
-
// headers: { Authorization: `Bearer ${token}` },
|
|
55
|
-
// });
|
|
56
|
-
|
|
57
|
-
// NEW WAY
|
|
58
319
|
const data = await apiClient.get(`/api/getAllExamPacks?subjectId=${subjectId}`);
|
|
59
320
|
setExamPacks(data);
|
|
60
321
|
} catch (error) {
|
|
@@ -113,14 +374,6 @@ function Report() {
|
|
|
113
374
|
const handleDownload = async () => {
|
|
114
375
|
setLoading(true);
|
|
115
376
|
try {
|
|
116
|
-
// OLD WAY with axios
|
|
117
|
-
// const url = `${baseURL}api/generateReportForSingleUser?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}&userId=${selectedUser.id}&wrongAnswerFlag=${onlyWrongAnswers}`;
|
|
118
|
-
// const response = await axios.get(url, {
|
|
119
|
-
// responseType: 'blob',
|
|
120
|
-
// headers: { Authorization: `Bearer ${token}` }
|
|
121
|
-
// });
|
|
122
|
-
|
|
123
|
-
// NEW WAY - need blob response
|
|
124
377
|
const response = await fetch(`${baseURL}api/generateReportForSingleUser?subjectId=${selectedSubject.subjectId}&examPackId=${selectedExamPack.id}&examId=${selectedExam.id}&userId=${selectedUser.id}&wrongAnswerFlag=${onlyWrongAnswers}`, {
|
|
125
378
|
headers: {
|
|
126
379
|
'X-Tenant-Token': apiClient.tenantToken
|
|
@@ -141,11 +394,17 @@ function Report() {
|
|
|
141
394
|
setLoading(false);
|
|
142
395
|
}
|
|
143
396
|
};
|
|
397
|
+
|
|
398
|
+
// Determine what to show based on props
|
|
399
|
+
const shouldShowHeader = !embedded && showHeader;
|
|
400
|
+
const shouldShowSidebar = !embedded && showSidebar;
|
|
401
|
+
const contentPadding = shouldShowHeader ? "100px 0px 0px 100px" : "20px";
|
|
402
|
+
const contentMarginLeft = shouldShowSidebar ? "140px" : "0";
|
|
144
403
|
return /*#__PURE__*/_jsxs("div", {
|
|
145
|
-
children: [/*#__PURE__*/_jsx(Header, {}), /*#__PURE__*/_jsx(Sidebar, {}), /*#__PURE__*/_jsxs("div", {
|
|
404
|
+
children: [shouldShowHeader && /*#__PURE__*/_jsx(Header, {}), shouldShowSidebar && /*#__PURE__*/_jsx(Sidebar, {}), /*#__PURE__*/_jsxs("div", {
|
|
146
405
|
style: {
|
|
147
|
-
padding:
|
|
148
|
-
marginLeft:
|
|
406
|
+
padding: contentPadding,
|
|
407
|
+
marginLeft: contentMarginLeft
|
|
149
408
|
},
|
|
150
409
|
children: [/*#__PURE__*/_jsx(Box, {
|
|
151
410
|
sx: {
|