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.
@@ -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'; // ADD THIS
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(); // ADD THIS - gets API client with token
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: "100px 0px 0px 100px",
148
- marginLeft: "140px"
406
+ padding: contentPadding,
407
+ marginLeft: contentMarginLeft
149
408
  },
150
409
  children: [/*#__PURE__*/_jsx(Box, {
151
410
  sx: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icleafreportui",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "private": false,
5
5
  "main": "dist/package.js",
6
6
  "files": [