icleafreportui 0.2.5 → 0.2.7

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.
@@ -0,0 +1,522 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import { Autocomplete, FormControl, Button, Grid, Box, Typography, Paper, Snackbar, Alert, CircularProgress, TextField, InputAdornment } from '@mui/material';
3
+ import { DataGrid } from '@mui/x-data-grid';
4
+ import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
5
+ import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined';
6
+ import Backdrop from '@mui/material/Backdrop';
7
+ import { useTenant } from '../context/TenantProvider';
8
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
9
+ function ExamPackReportContent() {
10
+ const {
11
+ apiClient
12
+ } = useTenant();
13
+ const [subjects, setSubjects] = useState([]);
14
+ const [courses, setCourses] = useState([]);
15
+ const [selectedSubject, setSelectedSubject] = useState(null);
16
+ const [selectedCourse, setSelectedCourse] = useState(null);
17
+ const [alertMessage, setAlertMessage] = useState('');
18
+ const [loading, setLoading] = useState(false);
19
+ const [alertOpen, setAlertOpen] = useState(false);
20
+ const reportType = [{
21
+ value: "Batch Wise",
22
+ label: "Batch Wise"
23
+ }, {
24
+ value: "User Wise",
25
+ label: "User Wise"
26
+ }];
27
+ const [selectedReportType, setSelectedReportType] = useState(null);
28
+ const [columns, setColumns] = useState(null);
29
+ const [rows, setRows] = useState([]);
30
+ const [tableShow, setTableShow] = useState(false);
31
+ const [multiLoading, setMultiLoading] = useState(false);
32
+ const [userSelect, setUserSelect] = useState(false);
33
+ const [selectedUserList, setSelectedUserList] = useState([]);
34
+ const [tableKey, setTableKey] = useState(0);
35
+ const [searchQuery, setSearchQuery] = useState("");
36
+ const baseURL = apiClient?.baseURL || process.env.REACT_APP_BASE_URL;
37
+ const filteredRows = userSelect ? rows.filter(row => {
38
+ const searchTerms = searchQuery.split(',').map(term => term.trim().toLowerCase()).filter(term => term.length > 0);
39
+ if (searchTerms.length === 0) return true;
40
+ const email = row.userName?.toLowerCase() || '';
41
+ const localPart = email.split('@')[0];
42
+ return searchTerms.some(term => {
43
+ if (term.includes('@')) {
44
+ return email === term;
45
+ } else {
46
+ return localPart.includes(term);
47
+ }
48
+ });
49
+ }) : rows;
50
+ const batchListColumns = [{
51
+ field: 'sno',
52
+ headerName: 'S.No',
53
+ width: 60,
54
+ sortable: false,
55
+ renderCell: params => params.api.getAllRowIds().indexOf(params.id) + 1
56
+ }, {
57
+ field: 'batchName',
58
+ headerName: 'Batch Name',
59
+ width: 230
60
+ }, {
61
+ field: 'batchStatus',
62
+ headerName: 'Status',
63
+ width: 170,
64
+ renderCell: params => /*#__PURE__*/_jsx("span", {
65
+ style: {
66
+ color: params.value ? 'green' : 'red',
67
+ fontWeight: 'bold'
68
+ },
69
+ children: params.value ? 'Active' : 'Inactive'
70
+ })
71
+ }, {
72
+ field: 'dailyProgressMail',
73
+ headerName: 'Daily Progress Mail',
74
+ width: 130,
75
+ renderCell: params => /*#__PURE__*/_jsx("span", {
76
+ style: {
77
+ color: params.value ? 'green' : 'red',
78
+ fontWeight: 'bold'
79
+ },
80
+ children: params.value ? 'Active' : 'Inactive'
81
+ })
82
+ }, {
83
+ field: "report",
84
+ headerName: "Report",
85
+ sortable: false,
86
+ width: 70,
87
+ renderCell: params => /*#__PURE__*/_jsx(FileDownloadOutlinedIcon, {
88
+ onClick: () => handleDownloadBatchReport(params.row),
89
+ fontSize: "small",
90
+ style: {
91
+ cursor: "pointer"
92
+ }
93
+ })
94
+ }];
95
+ const userListColumns = [{
96
+ field: 'sno',
97
+ headerName: 'S.No',
98
+ width: 60,
99
+ sortable: false,
100
+ renderCell: params => params.api.getAllRowIds().indexOf(params.id) + 1
101
+ }, {
102
+ field: 'userName',
103
+ headerName: 'User Name',
104
+ width: 280
105
+ }, {
106
+ field: 'userRoleType',
107
+ headerName: 'Role Type',
108
+ width: 200,
109
+ renderCell: params => /*#__PURE__*/_jsx("span", {
110
+ style: {
111
+ color: params.value ? 'green' : 'red',
112
+ fontWeight: 'bold'
113
+ },
114
+ children: params.value ? 'User' : ''
115
+ })
116
+ }, {
117
+ field: "report",
118
+ headerName: "Report",
119
+ sortable: false,
120
+ width: 70,
121
+ renderCell: params => /*#__PURE__*/_jsx(FileDownloadOutlinedIcon, {
122
+ onClick: () => handleDownloadSingleUserReport(params.row),
123
+ fontSize: "small",
124
+ style: {
125
+ cursor: "pointer"
126
+ }
127
+ })
128
+ }];
129
+ useEffect(() => {
130
+ fetchAllSubjects();
131
+ }, []);
132
+ const fetchAllSubjects = async () => {
133
+ try {
134
+ const data = await apiClient.get('/api/showAllSubjects');
135
+ setSubjects(data);
136
+ } catch (error) {
137
+ console.error('Error fetching subjects:', error);
138
+ }
139
+ };
140
+ const fetchCourses = async subjectId => {
141
+ try {
142
+ const data = await apiClient.get(`/api/getCoursesBySubject?subjectId=${subjectId}`);
143
+ setCourses(data);
144
+ } catch (error) {
145
+ console.error('Error fetching courses:', error);
146
+ }
147
+ };
148
+ const handleSubjectChange = (event, newValue) => {
149
+ setSelectedSubject(newValue);
150
+ setSelectedCourse(null);
151
+ setCourses([]);
152
+ setSelectedReportType(null);
153
+ setTableShow(false);
154
+ setRows([]);
155
+ setColumns([]);
156
+ if (newValue?.subjectId) {
157
+ fetchCourses(newValue.subjectId);
158
+ }
159
+ };
160
+ const handleCourseChange = (event, newValue) => {
161
+ setSelectedCourse(newValue);
162
+ setTableKey(prevKey => prevKey + 1);
163
+ fetchReportData(newValue?.id, selectedReportType?.value);
164
+ };
165
+ const handleReportTypeChange = (event, newValue) => {
166
+ setSelectedReportType(newValue);
167
+ setTableKey(prevKey => prevKey + 1);
168
+ fetchReportData(selectedCourse?.id, newValue?.value);
169
+ };
170
+ const fetchReportData = (courseId, reportTypeValue) => {
171
+ if (!selectedSubject?.subjectId || !courseId) return;
172
+ const apiMap = {
173
+ "Batch Wise": getBatchWiseList,
174
+ "User Wise": getUserWiseList
175
+ };
176
+ apiMap[reportTypeValue]?.(courseId);
177
+ };
178
+ const getBatchWiseList = async () => {
179
+ setLoading(true);
180
+ try {
181
+ const data = await apiClient.get(`/api/getCorpCourseBatches?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`);
182
+ if (data) {
183
+ setUserSelect(false);
184
+ setRows(data.corpCourseBatches || []);
185
+ setColumns(batchListColumns);
186
+ setTableShow(true);
187
+ }
188
+ } catch (error) {
189
+ setAlertOpen(true);
190
+ setAlertMessage(error.response?.data?.error || 'Error fetching batch data');
191
+ setTableShow(false);
192
+ setRows([]);
193
+ setColumns([]);
194
+ console.error("Error fetching batch-wise data:", error);
195
+ } finally {
196
+ setLoading(false);
197
+ }
198
+ };
199
+ const getUserWiseList = async () => {
200
+ setLoading(true);
201
+ try {
202
+ const data = await apiClient.get(`/api/getCorpCourseUsers?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`);
203
+ if (data) {
204
+ setRows(data.users || []);
205
+ setColumns(userListColumns);
206
+ setTableShow(true);
207
+ setUserSelect(true);
208
+ }
209
+ } catch (error) {
210
+ setAlertOpen(true);
211
+ setAlertMessage(error.response?.data?.error || 'Error fetching user data');
212
+ setTableShow(false);
213
+ setRows([]);
214
+ setColumns([]);
215
+ console.error("Error fetching user-wise data:", error);
216
+ } finally {
217
+ setLoading(false);
218
+ }
219
+ };
220
+ const handleRowSelection = newSelection => {
221
+ setSelectedUserList(newSelection);
222
+ };
223
+ const handleDownloadBatchReport = async item => {
224
+ setLoading(true);
225
+ try {
226
+ const blob = await apiClient.download(`/api/downloadCourseAndBatchWiseReport`, {
227
+ subjectId: selectedSubject.subjectId,
228
+ corpCourseId: selectedCourse.id,
229
+ batchId: item.id
230
+ });
231
+ const text = await blob.text();
232
+ if (text.includes('Course not configured')) {
233
+ setAlertMessage('Course not configured.');
234
+ setAlertOpen(true);
235
+ } else {
236
+ const filename = `${item.batchName}_Batch_Report.xlsx`;
237
+ const blobUrl = URL.createObjectURL(blob);
238
+ const link = document.createElement('a');
239
+ link.href = blobUrl;
240
+ link.setAttribute('download', filename);
241
+ document.body.appendChild(link);
242
+ link.click();
243
+ link.parentNode.removeChild(link);
244
+ URL.revokeObjectURL(blobUrl);
245
+ }
246
+ } catch (error) {
247
+ setAlertOpen(true);
248
+ setAlertMessage(error.response?.data?.error || 'Error downloading report');
249
+ console.error('Error downloading batch report:', error);
250
+ } finally {
251
+ setLoading(false);
252
+ }
253
+ };
254
+ const handleDownloadSingleUserReport = async item => {
255
+ setLoading(true);
256
+ try {
257
+ const blob = await apiClient.download(`/api/downloadExamPackReportByCourse`, {
258
+ userId: item.id,
259
+ corpCourseId: selectedCourse.id,
260
+ subjectId: selectedSubject.subjectId
261
+ });
262
+ const text = await blob.text();
263
+ if (text.includes('Course not configured')) {
264
+ setAlertMessage('Course not configured.');
265
+ setAlertOpen(true);
266
+ } else {
267
+ const filename = `${item.userName}_Pack_Report.xlsx`;
268
+ const blobUrl = URL.createObjectURL(blob);
269
+ const link = document.createElement('a');
270
+ link.href = blobUrl;
271
+ link.setAttribute('download', filename);
272
+ document.body.appendChild(link);
273
+ link.click();
274
+ link.parentNode.removeChild(link);
275
+ URL.revokeObjectURL(blobUrl);
276
+ }
277
+ } catch (error) {
278
+ setAlertOpen(true);
279
+ setAlertMessage(error.response?.data?.error || 'Error downloading report');
280
+ console.error('Error downloading user report:', error);
281
+ } finally {
282
+ setLoading(false);
283
+ }
284
+ };
285
+ const handleSummaryDownload = async () => {
286
+ setMultiLoading(true);
287
+ const selectedRowIds = rows.filter(row => selectedUserList.includes(row.id)).map(row => row.id);
288
+ try {
289
+ const response = await fetch(`${baseURL}/api/downloadExamPacksAndUserIdsReport?subjectId=${selectedSubject.subjectId}&corpCourseId=${selectedCourse.id}`, {
290
+ method: 'POST',
291
+ headers: {
292
+ 'Content-Type': 'application/json',
293
+ 'X-Tenant-Token': apiClient.tenantToken
294
+ },
295
+ body: JSON.stringify({
296
+ userIds: selectedRowIds
297
+ })
298
+ });
299
+ const blob = await response.blob();
300
+ const text = await blob.text();
301
+ if (text.includes('Course not configured')) {
302
+ setAlertMessage('Course not configured.');
303
+ setAlertOpen(true);
304
+ } else {
305
+ const filename = 'User_Exam_Pack_Report.xlsx';
306
+ const blobUrl = URL.createObjectURL(blob);
307
+ const link = document.createElement('a');
308
+ link.href = blobUrl;
309
+ link.setAttribute('download', filename);
310
+ document.body.appendChild(link);
311
+ link.click();
312
+ link.parentNode.removeChild(link);
313
+ URL.revokeObjectURL(blobUrl);
314
+ }
315
+ } catch (error) {
316
+ setAlertOpen(true);
317
+ setAlertMessage(error.response?.data?.error || 'Error downloading report');
318
+ console.error('Error downloading summary report:', error);
319
+ } finally {
320
+ setMultiLoading(false);
321
+ }
322
+ };
323
+
324
+ // Add download method to apiClient if not exists
325
+ const download = async function (endpoint) {
326
+ let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
327
+ const query = new URLSearchParams(params).toString();
328
+ const url = `${endpoint}?${query}`;
329
+ const response = await fetch(`${baseURL}/${url}`, {
330
+ headers: {
331
+ 'X-Tenant-Token': apiClient.tenantToken
332
+ }
333
+ });
334
+ return response.blob();
335
+ };
336
+
337
+ // Add download method to apiClient
338
+ if (apiClient && !apiClient.download) {
339
+ apiClient.download = download;
340
+ }
341
+ const paginationModel = {
342
+ page: 0,
343
+ pageSize: 5
344
+ };
345
+ return /*#__PURE__*/_jsxs(Box, {
346
+ sx: {
347
+ maxWidth: 1000,
348
+ mx: 'auto',
349
+ my: 4,
350
+ p: 3,
351
+ backgroundColor: '#f5f5f5',
352
+ borderRadius: 2
353
+ },
354
+ children: [/*#__PURE__*/_jsxs(Paper, {
355
+ elevation: 6,
356
+ sx: {
357
+ p: 5,
358
+ textAlign: 'center',
359
+ backgroundColor: '#fff'
360
+ },
361
+ children: [/*#__PURE__*/_jsx(Typography, {
362
+ variant: "h4",
363
+ component: "h1",
364
+ gutterBottom: true,
365
+ sx: {
366
+ color: '#3f51b5',
367
+ marginBottom: "20px"
368
+ },
369
+ children: "Exam Pack Report"
370
+ }), /*#__PURE__*/_jsxs(Grid, {
371
+ container: true,
372
+ spacing: 2,
373
+ justifyContent: "center",
374
+ children: [/*#__PURE__*/_jsx(Grid, {
375
+ item: true,
376
+ xs: 12,
377
+ sm: 4,
378
+ children: /*#__PURE__*/_jsx(FormControl, {
379
+ fullWidth: true,
380
+ children: /*#__PURE__*/_jsx(Autocomplete, {
381
+ options: subjects,
382
+ getOptionLabel: option => option.subjectName,
383
+ value: selectedSubject,
384
+ onChange: handleSubjectChange,
385
+ renderInput: params => /*#__PURE__*/_jsx(TextField, {
386
+ ...params,
387
+ label: "Subject"
388
+ })
389
+ })
390
+ })
391
+ }), /*#__PURE__*/_jsx(Grid, {
392
+ item: true,
393
+ xs: 12,
394
+ sm: 4,
395
+ children: /*#__PURE__*/_jsx(FormControl, {
396
+ fullWidth: true,
397
+ children: /*#__PURE__*/_jsx(Autocomplete, {
398
+ options: courses,
399
+ getOptionLabel: option => option.courseName,
400
+ value: selectedCourse,
401
+ onChange: handleCourseChange,
402
+ renderInput: params => /*#__PURE__*/_jsx(TextField, {
403
+ ...params,
404
+ label: "Course"
405
+ })
406
+ })
407
+ })
408
+ }), /*#__PURE__*/_jsx(Grid, {
409
+ item: true,
410
+ xs: 12,
411
+ sm: 4,
412
+ children: /*#__PURE__*/_jsx(FormControl, {
413
+ fullWidth: true,
414
+ children: /*#__PURE__*/_jsx(Autocomplete, {
415
+ options: reportType,
416
+ getOptionLabel: option => option.label,
417
+ value: selectedReportType,
418
+ onChange: handleReportTypeChange,
419
+ renderInput: params => /*#__PURE__*/_jsx(TextField, {
420
+ ...params,
421
+ label: "Report Type"
422
+ })
423
+ })
424
+ })
425
+ })]
426
+ }), tableShow && /*#__PURE__*/_jsxs(_Fragment, {
427
+ children: [/*#__PURE__*/_jsx(Box, {
428
+ sx: {
429
+ display: "flex",
430
+ justifyContent: "flex-end",
431
+ width: "100%",
432
+ margin: "20px 0px"
433
+ },
434
+ children: userSelect && /*#__PURE__*/_jsx(Button, {
435
+ variant: "contained",
436
+ color: "primary",
437
+ onClick: handleSummaryDownload,
438
+ disabled: selectedUserList.length <= 1,
439
+ sx: {
440
+ width: 'auto',
441
+ backgroundColor: '#3f51b5'
442
+ },
443
+ children: multiLoading ? 'Downloading...' : 'Download Report'
444
+ })
445
+ }), /*#__PURE__*/_jsxs(Paper, {
446
+ sx: {
447
+ width: '100%'
448
+ },
449
+ children: [/*#__PURE__*/_jsx("div", {
450
+ style: {
451
+ display: "flex",
452
+ justifyContent: "end",
453
+ alignItems: "center",
454
+ height: "100%",
455
+ padding: "10px 5px"
456
+ },
457
+ children: userSelect && /*#__PURE__*/_jsx(TextField, {
458
+ label: "Search",
459
+ variant: "outlined",
460
+ size: "small",
461
+ sx: {
462
+ mb: 2
463
+ },
464
+ value: searchQuery,
465
+ onChange: e => setSearchQuery(e.target.value),
466
+ InputProps: {
467
+ endAdornment: /*#__PURE__*/_jsx(InputAdornment, {
468
+ position: "start",
469
+ children: /*#__PURE__*/_jsx(SearchOutlinedIcon, {})
470
+ })
471
+ }
472
+ })
473
+ }), /*#__PURE__*/_jsx(DataGrid, {
474
+ rows: userSelect ? filteredRows : rows,
475
+ columns: columns,
476
+ initialState: {
477
+ pagination: {
478
+ paginationModel
479
+ }
480
+ },
481
+ pageSizeOptions: [5, 10, 50, 100],
482
+ checkboxSelection: userSelect,
483
+ disableRowSelectionOnClick: true,
484
+ onRowSelectionModelChange: handleRowSelection,
485
+ sx: {
486
+ border: 0,
487
+ "& .MuiTablePagination-selectLabel": {
488
+ margin: "unset"
489
+ },
490
+ "& .MuiTablePagination-displayedRows": {
491
+ margin: "unset"
492
+ }
493
+ }
494
+ }, tableKey)]
495
+ })]
496
+ })]
497
+ }), /*#__PURE__*/_jsx(Snackbar, {
498
+ open: alertOpen,
499
+ autoHideDuration: 6000,
500
+ onClose: () => setAlertOpen(false),
501
+ anchorOrigin: {
502
+ vertical: 'top',
503
+ horizontal: 'center'
504
+ },
505
+ children: /*#__PURE__*/_jsx(Alert, {
506
+ onClose: () => setAlertOpen(false),
507
+ severity: "info",
508
+ children: alertMessage
509
+ })
510
+ }), /*#__PURE__*/_jsx(Backdrop, {
511
+ sx: theme => ({
512
+ color: '#fff',
513
+ zIndex: theme.zIndex.drawer + 1
514
+ }),
515
+ open: loading || multiLoading,
516
+ children: /*#__PURE__*/_jsx(CircularProgress, {
517
+ color: "inherit"
518
+ })
519
+ })]
520
+ });
521
+ }
522
+ export default ExamPackReportContent;