@campxdev/shared 1.9.0 → 1.9.2
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/package.json +1 -1
- package/src/components/ApplicationProfile/ApplicationProfile.tsx +61 -27
- package/src/components/ApplicationProfile/DepartmentFilter.tsx +77 -0
- package/src/components/ApplicationProfile/services.ts +6 -3
- package/src/components/Institutions/InsititutionsDialog.tsx +34 -18
- package/src/components/Layout/Header/applications.ts +7 -7
- package/src/shared-state/PermissionsStore.ts +9 -1
package/package.json
CHANGED
|
@@ -28,10 +28,12 @@ import { axiosErrorToast } from '../../config/axios'
|
|
|
28
28
|
import { ValidateAccess } from '../../permissions'
|
|
29
29
|
import { Permission, PermissionsStore } from '../../shared-state'
|
|
30
30
|
import ActionButton from '../ActionButton'
|
|
31
|
+
import FilterButton from '../FilterComponents/FilterButton'
|
|
31
32
|
import SearchBar from '../FilterComponents/SearchBar'
|
|
32
33
|
import { SingleSelect } from '../Input'
|
|
33
|
-
import { DialogButton } from '../ModalButtons'
|
|
34
|
+
import { DialogButton, DrawerButton } from '../ModalButtons'
|
|
34
35
|
import Table from '../Tables/BasicTable/Table'
|
|
36
|
+
import DeprartmentFilter from './DepartmentFilter'
|
|
35
37
|
|
|
36
38
|
interface ApplicationProfileProps {
|
|
37
39
|
application: 'exams' | 'square' | 'payments' | 'enroll_x' | 'hostels'
|
|
@@ -49,10 +51,14 @@ function ApplicationProfile({
|
|
|
49
51
|
permissions,
|
|
50
52
|
}: ApplicationProfileProps) {
|
|
51
53
|
const { isConfirmed } = useConfirm()
|
|
52
|
-
const [
|
|
54
|
+
const [state, setState] = useImmer(defaultFilterObj)
|
|
55
|
+
|
|
53
56
|
const { data, isLoading, refetch } = useQuery(
|
|
54
|
-
[
|
|
55
|
-
|
|
57
|
+
[
|
|
58
|
+
'application-users',
|
|
59
|
+
...Object.keys(state.filters).map((key) => state.filters[key]),
|
|
60
|
+
],
|
|
61
|
+
() => fetchApplicationUsers({ application, ...state.filters }),
|
|
56
62
|
)
|
|
57
63
|
|
|
58
64
|
const { data: profiles, isLoading: profilesLoading } = useQuery(
|
|
@@ -63,7 +69,7 @@ function ApplicationProfile({
|
|
|
63
69
|
const { mutate, isLoading: removingUserProfile } = useMutation(
|
|
64
70
|
removeUserApplicationProfile,
|
|
65
71
|
{
|
|
66
|
-
onSuccess: (
|
|
72
|
+
onSuccess: () => {
|
|
67
73
|
refetch()
|
|
68
74
|
toast.success('User profile removed from application')
|
|
69
75
|
},
|
|
@@ -77,6 +83,7 @@ function ApplicationProfile({
|
|
|
77
83
|
if (!confirmed) return
|
|
78
84
|
mutate({ userId: data.id, application: application })
|
|
79
85
|
}
|
|
86
|
+
|
|
80
87
|
const columns = [
|
|
81
88
|
{
|
|
82
89
|
title: 'User',
|
|
@@ -122,15 +129,15 @@ function ApplicationProfile({
|
|
|
122
129
|
},
|
|
123
130
|
]
|
|
124
131
|
const handleLimitChange = (value: number) => {
|
|
125
|
-
|
|
126
|
-
s.limit = value
|
|
127
|
-
s.offset = 0
|
|
132
|
+
setState((s) => {
|
|
133
|
+
s.filters.limit = value
|
|
134
|
+
s.filters.offset = 0
|
|
128
135
|
})
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
const handlePagination = (value: number) => {
|
|
132
|
-
|
|
133
|
-
s.offset = value * s.limit - s.limit
|
|
139
|
+
setState((s) => {
|
|
140
|
+
s.filters.offset = value * s.filters.limit - s.filters.limit
|
|
134
141
|
})
|
|
135
142
|
}
|
|
136
143
|
|
|
@@ -168,29 +175,56 @@ function ApplicationProfile({
|
|
|
168
175
|
/>
|
|
169
176
|
<PageContent sx={{ marginTop: '25px' }}>
|
|
170
177
|
<StyledTableContainer>
|
|
171
|
-
<
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
<Box
|
|
179
|
+
sx={{
|
|
180
|
+
display: 'flex',
|
|
181
|
+
gap: '10px',
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
marginBottom: '10px',
|
|
176
184
|
}}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
185
|
+
>
|
|
186
|
+
<Box>
|
|
187
|
+
<SearchBar
|
|
188
|
+
onSearch={(value) =>
|
|
189
|
+
setState((s) => {
|
|
190
|
+
s.filters.search = value
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
textFieldProps={{
|
|
194
|
+
placeholder: 'Search by Name',
|
|
195
|
+
title: 'Search by Name',
|
|
196
|
+
sx: { width: '300px' },
|
|
197
|
+
size: 'medium',
|
|
198
|
+
}}
|
|
199
|
+
/>
|
|
200
|
+
</Box>
|
|
201
|
+
<DrawerButton
|
|
202
|
+
anchor={({ open }) => (
|
|
203
|
+
<FilterButton
|
|
204
|
+
onClick={open}
|
|
205
|
+
filtersApplied={state.filtersApplied}
|
|
206
|
+
/>
|
|
207
|
+
)}
|
|
208
|
+
content={({ close }) => (
|
|
209
|
+
<DeprartmentFilter
|
|
210
|
+
close={close}
|
|
211
|
+
setAppliedFilters={setState}
|
|
212
|
+
appliedFilters={state}
|
|
213
|
+
/>
|
|
214
|
+
)}
|
|
215
|
+
title="People Filters"
|
|
216
|
+
/>
|
|
217
|
+
</Box>
|
|
184
218
|
<Table
|
|
185
219
|
columns={columns}
|
|
186
220
|
dataSource={data?.result ?? []}
|
|
187
221
|
loading={isLoading || removingUserProfile}
|
|
188
222
|
pagination={{
|
|
189
|
-
limit: filters.limit,
|
|
223
|
+
limit: state.filters.limit,
|
|
190
224
|
onChangeLimit: handleLimitChange,
|
|
191
225
|
onChange: handlePagination,
|
|
192
226
|
totalCount: data?.count,
|
|
193
|
-
page: filters.offset / filters.limit,
|
|
227
|
+
page: state.filters.offset / state.filters.limit,
|
|
194
228
|
}}
|
|
195
229
|
/>
|
|
196
230
|
</StyledTableContainer>
|
|
@@ -218,14 +252,14 @@ export const RenderProfileDropDown = ({
|
|
|
218
252
|
})
|
|
219
253
|
|
|
220
254
|
useEffect(() => {
|
|
221
|
-
setState((
|
|
255
|
+
setState(() => ({
|
|
222
256
|
userId: data.id,
|
|
223
257
|
profileId: data?.profiles?.find((p) => p.application === application)?.id,
|
|
224
258
|
}))
|
|
225
259
|
}, [data])
|
|
226
260
|
|
|
227
261
|
const { mutate, isLoading } = useMutation(updateUserApplicationProfile, {
|
|
228
|
-
onSuccess: (
|
|
262
|
+
onSuccess: () => {
|
|
229
263
|
refetchFn()
|
|
230
264
|
toast.success('User application profile updated successfully')
|
|
231
265
|
},
|
|
@@ -333,7 +367,7 @@ export const StyledTableContainer = styled(Box)(({ theme }) => ({
|
|
|
333
367
|
},
|
|
334
368
|
}))
|
|
335
369
|
|
|
336
|
-
export const StyledDropDownContainer = styled(Box)((
|
|
370
|
+
export const StyledDropDownContainer = styled(Box)(() => ({
|
|
337
371
|
width: '200px',
|
|
338
372
|
'& .MuiTypography-root': {
|
|
339
373
|
display: 'none',
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Button, Stack } from '@mui/material'
|
|
2
|
+
import { useEffect } from 'react'
|
|
3
|
+
import { useQuery } from 'react-query'
|
|
4
|
+
import { useImmer } from 'use-immer'
|
|
5
|
+
import axios from '../../config/axios'
|
|
6
|
+
import { SingleSelect } from '../Input'
|
|
7
|
+
import Spinner from '../Spinner'
|
|
8
|
+
|
|
9
|
+
const defaultState = {
|
|
10
|
+
departmentId: '',
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const getDepartments = () => {
|
|
14
|
+
return axios.get('/square/departments').then((res) => res.data)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default function DeprartmentFilter({
|
|
18
|
+
close,
|
|
19
|
+
appliedFilters,
|
|
20
|
+
setAppliedFilters,
|
|
21
|
+
}) {
|
|
22
|
+
const [filter, setFilter] = useImmer(defaultState)
|
|
23
|
+
|
|
24
|
+
const { data, isLoading } = useQuery('department', () => getDepartments())
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
setFilter({ departmentId: appliedFilters.filters.departmentId })
|
|
28
|
+
}, [])
|
|
29
|
+
|
|
30
|
+
const applyFilter = () => {
|
|
31
|
+
close()
|
|
32
|
+
setAppliedFilters((s) => {
|
|
33
|
+
s.filters.departmentId = filter.departmentId
|
|
34
|
+
s.filtersApplied = filter.departmentId ? true : false
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
const clearFilter = () => {
|
|
38
|
+
setAppliedFilters((s) => {
|
|
39
|
+
s.filters.departmentId = ''
|
|
40
|
+
s.filtersApplied = false
|
|
41
|
+
})
|
|
42
|
+
close()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isLoading) return <Spinner />
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<Stack gap={3}>
|
|
49
|
+
<SingleSelect
|
|
50
|
+
label="Select Program"
|
|
51
|
+
onChange={(e) => {
|
|
52
|
+
setFilter((s) => {
|
|
53
|
+
s.departmentId = e.target.value
|
|
54
|
+
})
|
|
55
|
+
}}
|
|
56
|
+
value={filter.departmentId}
|
|
57
|
+
options={
|
|
58
|
+
data &&
|
|
59
|
+
data?.map((item) => ({
|
|
60
|
+
label: item?.name,
|
|
61
|
+
value: item?.id,
|
|
62
|
+
}))
|
|
63
|
+
}
|
|
64
|
+
/>
|
|
65
|
+
|
|
66
|
+
<Stack direction="row" gap={2} mt={0.5}>
|
|
67
|
+
<Button fullWidth onClick={applyFilter}>
|
|
68
|
+
Apply Filters
|
|
69
|
+
</Button>
|
|
70
|
+
<Button variant="outlined" fullWidth onClick={clearFilter}>
|
|
71
|
+
Clear Filters
|
|
72
|
+
</Button>
|
|
73
|
+
</Stack>
|
|
74
|
+
</Stack>
|
|
75
|
+
</>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as yup from 'yup'
|
|
2
2
|
import axios from '../../config/axios'
|
|
3
3
|
export const defaultFilterObj = {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
filters: {
|
|
5
|
+
search: null,
|
|
6
|
+
limit: 10,
|
|
7
|
+
offset: 0,
|
|
8
|
+
},
|
|
9
|
+
filtersApplied: false,
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
export const userProfileSchema = yup.object().shape({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Box, Typography } from '@mui/material'
|
|
1
|
+
import { Box, Stack, Typography, styled } from '@mui/material'
|
|
2
2
|
import { InsititutionsStore } from '../../shared-state/InstitutionsStore'
|
|
3
3
|
import Image from '../Image/Image'
|
|
4
4
|
|
|
@@ -6,30 +6,23 @@ export default function InsititutionsDialog({ close }) {
|
|
|
6
6
|
const { institutions } = InsititutionsStore.useState((s) => s)
|
|
7
7
|
|
|
8
8
|
return (
|
|
9
|
-
<
|
|
9
|
+
<Stack
|
|
10
|
+
gap={4}
|
|
10
11
|
sx={{
|
|
11
12
|
padding: '20px',
|
|
13
|
+
alignItems: 'center',
|
|
12
14
|
}}
|
|
13
15
|
>
|
|
14
16
|
<Typography variant="h3" textAlign={'center'}>
|
|
15
17
|
Select an Instituition
|
|
16
18
|
</Typography>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
alignItems: 'center',
|
|
25
|
-
}}
|
|
26
|
-
>
|
|
27
|
-
{institutions?.map((item, index) => (
|
|
28
|
-
<InstitutionCard institution={item} key={index} />
|
|
29
|
-
))}
|
|
30
|
-
</Box>
|
|
31
|
-
</Box>
|
|
32
|
-
</Box>
|
|
19
|
+
|
|
20
|
+
<StyledInstitutionContainer>
|
|
21
|
+
{institutions?.map((item, index) => (
|
|
22
|
+
<InstitutionCard institution={item} key={index} />
|
|
23
|
+
))}
|
|
24
|
+
</StyledInstitutionContainer>
|
|
25
|
+
</Stack>
|
|
33
26
|
)
|
|
34
27
|
}
|
|
35
28
|
|
|
@@ -68,3 +61,26 @@ const InstitutionCard = ({ institution }) => {
|
|
|
68
61
|
</Box>
|
|
69
62
|
)
|
|
70
63
|
}
|
|
64
|
+
|
|
65
|
+
export const StyledInstitutionContainer = styled(Box)(({ theme }) => ({
|
|
66
|
+
width: '87%',
|
|
67
|
+
overflowX: 'auto',
|
|
68
|
+
display: 'flex',
|
|
69
|
+
flex: 1,
|
|
70
|
+
justifyContent: 'flex-start',
|
|
71
|
+
padding: '20px',
|
|
72
|
+
gap: '20px',
|
|
73
|
+
'&::-webkit-scrollbar': {
|
|
74
|
+
width: '0.5em',
|
|
75
|
+
height: '0.5em',
|
|
76
|
+
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
|
77
|
+
},
|
|
78
|
+
'&::-webkit-scrollbar-thumb': {
|
|
79
|
+
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
|
80
|
+
borderRadius: '3px',
|
|
81
|
+
|
|
82
|
+
'&:hover': {
|
|
83
|
+
background: 'rgba(0, 0, 0, 0.3)',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
}))
|
|
@@ -81,13 +81,13 @@ export const applications = [
|
|
|
81
81
|
icon: hostelSmall,
|
|
82
82
|
description: 'Manage Hostels in the Campus',
|
|
83
83
|
},
|
|
84
|
-
{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
84
|
+
// {
|
|
85
|
+
// title: 'CommuteX',
|
|
86
|
+
// key: 'commute',
|
|
87
|
+
// path: isDevelopment ? origins.commute.dev : origins.commute.prod,
|
|
88
|
+
// icon: commuteSmall,
|
|
89
|
+
// description: 'Manage Commute in the Campus',
|
|
90
|
+
// },
|
|
91
91
|
...(isDevelopment
|
|
92
92
|
? [
|
|
93
93
|
{
|
|
@@ -349,7 +349,10 @@ export enum EnrollPermissions {
|
|
|
349
349
|
ADMISSIONS_CONFIRM = 'can_admissions_confirm',
|
|
350
350
|
CAN_ADMISSION_REJECT = 'can_admissions_reject',
|
|
351
351
|
CAN_ADMISSIONS_DASHBOARD_VIEW = 'can_admission_dashboard_view',
|
|
352
|
-
|
|
352
|
+
CAN_ADMISSIONS_GRAPH_VIEW = 'can_admission_graph_view',
|
|
353
|
+
CAN_ADMISSIONS_LEAD_REMARKS = 'can_admission_lead_remarks',
|
|
354
|
+
CAN_ENROLL_X_AUDIT_LOGS = 'can_enroll_x_view_audit_logs',
|
|
355
|
+
CAN_ADMISSION_APPROVAL = 'can_admission_approvals',
|
|
353
356
|
// CET & PHD
|
|
354
357
|
CAN_PHD_FORM_VIEW = 'can_admissions_view_phd_applications',
|
|
355
358
|
CAN_PHD_FORM_DOWNLOAD = 'can_admissions_download_phd_applications',
|
|
@@ -850,6 +853,7 @@ export enum Permission {
|
|
|
850
853
|
CAN_COUNSELLOR_VIEW = 'can_counsellor_view',
|
|
851
854
|
CAN_COUNSELLOR_ADD = 'can_counsellor_add',
|
|
852
855
|
CAN_COUNSELLOR_DELETE = 'can_counsellor_delete',
|
|
856
|
+
CAN_COUNSELLOR_REPORT_VIEW = 'can_counsellor_report_view',
|
|
853
857
|
|
|
854
858
|
// Notifications
|
|
855
859
|
CAN_NOTIFICATION_ADD = 'can_notification_add',
|
|
@@ -868,6 +872,10 @@ export enum Permission {
|
|
|
868
872
|
ADMISSIONS_CONFIRM = 'can_admissions_confirm',
|
|
869
873
|
CAN_ADMISSION_REJECT = 'can_admissions_reject',
|
|
870
874
|
CAN_ADMISSIONS_DASHBOARD_VIEW = 'can_admission_dashboard_view',
|
|
875
|
+
CAN_ADMISSIONS_LEAD_REMARKS = 'can_admission_lead_remarks',
|
|
876
|
+
CAN_ADMISSIONS_GRAPH_VIEW = 'can_admission_graph_view',
|
|
877
|
+
CAN_ENROLL_X_AUDIT_LOGS = 'can_enroll_x_view_audit_logs',
|
|
878
|
+
CAN_ADMISSION_APPROVAL = 'can_admission_approvals',
|
|
871
879
|
|
|
872
880
|
// CET & PHD
|
|
873
881
|
CAN_PHD_FORM_VIEW = 'can_admissions_view_phd_applications',
|