@campxdev/campx-web-utils 1.1.8 → 1.2.0

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.
Files changed (43) hide show
  1. package/export.ts +9 -0
  2. package/package.json +7 -4
  3. package/src/App.css +38 -0
  4. package/src/App.tsx +16 -0
  5. package/src/AppContent.tsx +19 -0
  6. package/src/components/ActivityLog.tsx +96 -0
  7. package/src/components/ChangePassword.tsx +183 -0
  8. package/src/config/axios.ts +146 -0
  9. package/src/context/ConfirmDialogProvider.tsx +78 -0
  10. package/src/context/ErrorBoundary/ErrorBoundary.tsx +131 -0
  11. package/src/context/ErrorBoundary/Login.tsx +206 -0
  12. package/src/context/Providers.tsx +76 -0
  13. package/src/context/SnackbarProvider.tsx +42 -0
  14. package/src/context/application-store.ts +86 -0
  15. package/src/context/export.ts +5 -0
  16. package/src/hooks/export.ts +1 -0
  17. package/src/hooks/useConfirm.ts +57 -0
  18. package/src/index.css +13 -0
  19. package/src/index.tsx +19 -0
  20. package/src/layout/AppLayout/AppLayout.tsx +155 -0
  21. package/src/layout/AppLayout/components/HelpDocs.tsx +121 -0
  22. package/src/logo.svg +1 -0
  23. package/src/react-app-env.d.ts +1 -0
  24. package/src/reportWebVitals.ts +15 -0
  25. package/src/routes/main.tsx +32 -0
  26. package/src/selectors/BatchSelector.tsx +15 -0
  27. package/src/selectors/CourseSelector.tsx +16 -0
  28. package/src/selectors/DepartmentSelector.tsx +19 -0
  29. package/src/selectors/EmployeesSelector.tsx +20 -0
  30. package/src/selectors/FeeTypeSelector.tsx +15 -0
  31. package/src/selectors/HostelBlocksSelector.tsx +19 -0
  32. package/src/selectors/HostelFloorSelector.tsx +19 -0
  33. package/src/selectors/HostelRoomSelector.tsx +20 -0
  34. package/src/selectors/PrintFormatSelector.tsx +17 -0
  35. package/src/selectors/ProgramSelector.tsx +16 -0
  36. package/src/selectors/RegulationSelector.tsx +19 -0
  37. package/src/selectors/SemesterSelector.tsx +16 -0
  38. package/src/selectors/YearRangeSelector.tsx +26 -0
  39. package/src/selectors/export.ts +13 -0
  40. package/src/selectors/utils.tsx +39 -0
  41. package/src/setupTests.ts +5 -0
  42. package/src/utils/constants.ts +7 -0
  43. package/src/utils/functions.tsx +11 -0
@@ -0,0 +1,155 @@
1
+ import {
2
+ AppHeader,
3
+ Sidebar,
4
+ SideMenuItemProps,
5
+ Spinner,
6
+ } from '@campxdev/react-blueprint';
7
+ import { Box, Stack, styled, useMediaQuery, useTheme } from '@mui/material';
8
+ import { motion } from 'framer-motion';
9
+ import Cookies from 'js-cookie';
10
+ import { ReactNode, Suspense, useState } from 'react';
11
+ import { ChangePasswordDialog } from '../../components/ChangePassword';
12
+ import { axios } from '../../config/axios';
13
+ import { ErrorBoundary } from '../../context/export';
14
+ import { HelpDocs } from './components/HelpDocs';
15
+
16
+ type Props = {
17
+ actions?: ReactNode[];
18
+ profileActions?: ReactNode[];
19
+ children?: ReactNode;
20
+ menu: SideMenuItemProps[];
21
+ mainContainerSx?: any;
22
+ handleLogout?: any;
23
+ userName?: string;
24
+ designation?: string;
25
+ clientName?: string;
26
+ institutionData?: any[];
27
+ defaultCollapsed?: boolean;
28
+ helpDocsConfig?: Record<
29
+ string,
30
+ { actions: { name: string; onClick: () => void }[] }
31
+ >;
32
+ };
33
+
34
+ export const AppLayout: React.FC<Props> = ({
35
+ actions = [],
36
+ profileActions = [],
37
+ children,
38
+ institutionData = [],
39
+ menu,
40
+ mainContainerSx,
41
+ handleLogout,
42
+ userName = '',
43
+ designation = '',
44
+ clientName = '',
45
+ defaultCollapsed = true,
46
+ helpDocsConfig,
47
+ }) => {
48
+ const [collapsed, setCollapsed] = useState(defaultCollapsed);
49
+ const theme = useTheme();
50
+ const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
51
+
52
+ function logout() {
53
+ axios
54
+ .post('/auth-server/auth/logout')
55
+ .then((res) => {
56
+ Cookies.remove('campx_tenant');
57
+ Cookies.remove('campx_session_key');
58
+ Cookies.remove('campx_institution');
59
+ window.location.href = '/';
60
+ })
61
+ .catch((err) => {
62
+ // toast("Unable To Logout.");
63
+ });
64
+ }
65
+
66
+ const fullPath = window.location.pathname;
67
+ const pathSegments = fullPath.split('/').filter(Boolean);
68
+ const actualPath = pathSegments.slice(1).join('/');
69
+ const normalizedPath = actualPath.replace(/\/\d+/g, '/:id');
70
+ const helpDocsActions = helpDocsConfig?.[`/${normalizedPath}`]?.actions || [];
71
+
72
+ return (
73
+ <AppLayoutContainer>
74
+ <Sidebar menu={menu} collapsed={collapsed} setCollapsed={setCollapsed} />
75
+ <motion.div
76
+ animate={{
77
+ width: collapsed ? 'calc(100% - 84px)' : 'calc(100% - 278px)',
78
+ }}
79
+ transition={{ duration: 0.3, ease: 'circOut' }}
80
+ style={{
81
+ margin: '12px 12px 12px 0px',
82
+ width: isSmallScreen ? '100%' : 'calc(100% - 84px)',
83
+ display: isSmallScreen ? 'contents' : 'block',
84
+ }}
85
+ >
86
+ <AppHeader
87
+ clientName={clientName}
88
+ userFullName={userName}
89
+ designation={designation}
90
+ actions={actions}
91
+ profileActions={[<ChangePasswordDialog />, ...profileActions]}
92
+ collapsed={collapsed}
93
+ showActiveDevices={false}
94
+ onLogoutClick={handleLogout ?? logout}
95
+ institutionsData={institutionData}
96
+ {...(isSmallScreen && {
97
+ profileSx: { width: 32, height: 32, fontSize: '12px' },
98
+ })}
99
+ />
100
+ {helpDocsConfig && helpDocsActions.length > 0 && (
101
+ <HelpDocs actions={helpDocsActions} />
102
+ )}
103
+
104
+ <OutletContainer
105
+ sx={{
106
+ margin: '12px 0px 0px 0px',
107
+ backgroundColor: theme.palette.surface.paperBackground,
108
+ ...mainContainerSx,
109
+ }}
110
+ onClick={() => {
111
+ setCollapsed(true);
112
+ }}
113
+ >
114
+ <Suspense fallback={<Spinner />}>
115
+ <ErrorBoundary>{children}</ErrorBoundary>
116
+ </Suspense>
117
+ </OutletContainer>
118
+ </motion.div>
119
+ </AppLayoutContainer>
120
+ );
121
+ };
122
+
123
+ const AppLayoutContainer = styled(Stack)(({ theme }: { theme?: any }) => ({
124
+ flexDirection: 'row',
125
+ backgroundColor: theme.palette.surface.defaultBackground,
126
+
127
+ [theme.breakpoints.down('md')]: { flexWrap: 'wrap' },
128
+ }));
129
+
130
+ const OutletContainer = styled(Box)(({ theme }: { theme?: any }) => ({
131
+ borderRadius: '8px',
132
+ height: 'calc(100vh - 96px)',
133
+ overflowY: 'scroll',
134
+ width: '100%',
135
+
136
+ '&::-webkit-scrollbar': {
137
+ width: '0.5em',
138
+ height: '0.2em',
139
+ backgroundColor: theme.palette.surface.defaultBackground,
140
+ },
141
+
142
+ '&::-webkit-scrollbar-thumb': {
143
+ backgroundColor: theme.palette.primary.light,
144
+ borderRadius: '3px',
145
+
146
+ '&:hover': { backgroundColor: theme.palette.primary.main },
147
+ },
148
+
149
+ [theme.breakpoints.down('md')]: {
150
+ margin: '0px 12px 12px 12px',
151
+ height: 'calc(100vh - 118px)',
152
+
153
+ '&::-webkit-scrollbar': { display: 'none' },
154
+ },
155
+ }));
@@ -0,0 +1,121 @@
1
+ import { Icons } from '@campxdev/react-blueprint';
2
+ import { Backdrop, useTheme } from '@mui/material';
3
+ import Box from '@mui/material/Box';
4
+ import SpeedDial from '@mui/material/SpeedDial';
5
+ import SpeedDialAction from '@mui/material/SpeedDialAction';
6
+ import * as React from 'react';
7
+
8
+ interface HelpDocsActionType {
9
+ name: string;
10
+ onClick?: () => void;
11
+ backgroundColor?: string;
12
+ }
13
+
14
+ interface HelpDocsProps {
15
+ actions: HelpDocsActionType[];
16
+ }
17
+
18
+ export const HelpDocs: React.FC<HelpDocsProps> = ({ actions }) => {
19
+ const theme = useTheme();
20
+ const [open, setOpen] = React.useState(false);
21
+
22
+ const handleOpen = () => setOpen(true);
23
+ const handleClose = () => setOpen(false);
24
+
25
+ return (
26
+ <Box
27
+ sx={{
28
+ position: 'fixed',
29
+ bottom: 26,
30
+ right: 0,
31
+ zIndex: 1000,
32
+ }}
33
+ >
34
+ <Backdrop open={open} />
35
+ <SpeedDial
36
+ ariaLabel="Custom Help Docs"
37
+ sx={{
38
+ position: 'absolute',
39
+ bottom: 0,
40
+ right: 40,
41
+ display: 'flex',
42
+ alignItems: 'flex-end',
43
+ '& .MuiFab-primary': {
44
+ backgroundColor: theme.palette.highlight.highlightBlue,
45
+ borderRadius: '8px',
46
+ width: '50px',
47
+ height: '50px',
48
+ display: 'flex',
49
+ justifyContent: 'center',
50
+ alignItems: 'center',
51
+ '&:hover': {
52
+ backgroundColor: theme.palette.highlight.highlightBlue,
53
+ },
54
+ },
55
+ '& .MuiSpeedDialAction-fab': {
56
+ margin: '0 0 16px 0',
57
+ '&:not(:last-child)': {
58
+ marginBottom: '8px',
59
+ },
60
+ },
61
+ }}
62
+ icon={<Icons.HelpDocsIcon size={20} />}
63
+ onClose={handleClose}
64
+ onOpen={handleOpen}
65
+ open={open}
66
+ direction="up"
67
+ >
68
+ {actions.map((action: HelpDocsActionType) => (
69
+ <SpeedDialAction
70
+ key={action.name}
71
+ onClick={() => {
72
+ action.onClick?.();
73
+ handleClose();
74
+ }}
75
+ icon={
76
+ <span
77
+ style={{
78
+ display: 'flex',
79
+ alignItems: 'center',
80
+ justifyContent: 'center',
81
+ width: '100%',
82
+ height: '100%',
83
+ fontWeight: 'bold',
84
+ whiteSpace: 'nowrap',
85
+ overflow: 'hidden',
86
+ textOverflow: 'ellipsis',
87
+ }}
88
+ >
89
+ {action.name}
90
+ </span>
91
+ }
92
+ FabProps={{
93
+ sx: {
94
+ width: 'auto',
95
+ minWidth: '180px',
96
+ maxWidth: '280px',
97
+ padding: '8px 12px',
98
+ boxShadow: 'none',
99
+ height: '40px',
100
+ borderRadius: '8px',
101
+ backgroundColor: theme.palette.surface.defaultBackground,
102
+ color: theme.palette.text.primary,
103
+ fontWeight: 500,
104
+ fontFamily: 'Heebo',
105
+ fontSize: '12px',
106
+ whiteSpace: 'nowrap',
107
+ textAlign: 'right',
108
+ display: 'flex',
109
+ justifyContent: 'flex-end',
110
+ alignItems: 'center',
111
+ '&:hover': {
112
+ backgroundColor: theme.palette.surface.defaultBackground,
113
+ },
114
+ },
115
+ }}
116
+ />
117
+ ))}
118
+ </SpeedDial>
119
+ </Box>
120
+ );
121
+ };
package/src/logo.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
@@ -0,0 +1 @@
1
+ /// <reference types="react-scripts" />
@@ -0,0 +1,15 @@
1
+ import { ReportHandler } from 'web-vitals';
2
+
3
+ const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4
+ if (onPerfEntry && onPerfEntry instanceof Function) {
5
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6
+ getCLS(onPerfEntry);
7
+ getFID(onPerfEntry);
8
+ getFCP(onPerfEntry);
9
+ getLCP(onPerfEntry);
10
+ getTTFB(onPerfEntry);
11
+ });
12
+ }
13
+ };
14
+
15
+ export default reportWebVitals;
@@ -0,0 +1,32 @@
1
+ import { AppLayout, Icons } from '@campxdev/react-blueprint';
2
+ import { Navigate, Outlet } from 'react-router-dom';
3
+ import AppContent from '../AppContent';
4
+
5
+ export const mainRoutes = [
6
+ {
7
+ path: '/',
8
+ element: (
9
+ <AppLayout
10
+ menu={[
11
+ {
12
+ name: 'App Content',
13
+ path: '/app-content',
14
+ icon: <Icons.AdminIcon size={20} />,
15
+ },
16
+ ]}
17
+ >
18
+ <Outlet />
19
+ </AppLayout>
20
+ ),
21
+ children: [
22
+ {
23
+ index: true,
24
+ element: <Navigate to={'app-content/abc/xyz/digital-notice-board'} />,
25
+ },
26
+ {
27
+ path: 'app-content/abc/xyz/digital-notice-board',
28
+ element: <AppContent />,
29
+ },
30
+ ],
31
+ },
32
+ ];
@@ -0,0 +1,15 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { batchOptions } from './utils';
3
+
4
+ export const BatchSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ label="Batch"
8
+ options={batchOptions?.map((item: { label: string; value: string }) => ({
9
+ label: item.label,
10
+ value: item.value,
11
+ }))}
12
+ {...props}
13
+ />
14
+ );
15
+ };
@@ -0,0 +1,16 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const CourseSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbLabelProps={{
8
+ labelKey: 'courseName',
9
+ subLabelKey: 'level',
10
+ }}
11
+ {...props}
12
+ externalAxios={axios}
13
+ optionsApiEndPoint="/dropdowns/courses"
14
+ />
15
+ );
16
+ };
@@ -0,0 +1,19 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const DepartmentSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbLabelProps={{
8
+ labelKey: 'name',
9
+ }}
10
+ dbValueProps={{
11
+ valueKey: '_id',
12
+ isObjectId: true,
13
+ }}
14
+ {...props}
15
+ externalAxios={axios}
16
+ optionsApiEndPoint="/dropdowns/departments"
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,20 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const EmployeesSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbValueProps={{
8
+ valueKey: '_id',
9
+ isObjectId: true,
10
+ }}
11
+ dbLabelProps={{
12
+ labelKey: 'fullName',
13
+ subLabelKey: 'employeeId',
14
+ }}
15
+ {...props}
16
+ externalAxios={axios}
17
+ optionsApiEndPoint="/dropdowns/employees"
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,15 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { FeeTypes } from './utils';
3
+
4
+ export const FeeTypeSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ label="Fee Type"
8
+ options={FeeTypes?.map((item: { label: string; value: string }) => ({
9
+ label: item.label,
10
+ value: item.value,
11
+ }))}
12
+ {...props}
13
+ />
14
+ );
15
+ };
@@ -0,0 +1,19 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const HostelBlocksSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbValueProps={{
8
+ valueKey: 'id',
9
+ isInt: true,
10
+ }}
11
+ dbLabelProps={{
12
+ labelKey: 'name',
13
+ }}
14
+ {...props}
15
+ externalAxios={axios}
16
+ optionsApiEndPoint="/dropdowns/hostel-blocks"
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,19 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const HostelFloorSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ label="Hostel Room No."
8
+ dbValueProps={{
9
+ valueKey: 'floor',
10
+ }}
11
+ dbLabelProps={{
12
+ labelKey: 'floor',
13
+ }}
14
+ {...props}
15
+ externalAxios={axios}
16
+ optionsApiEndPoint="dropdowns/floors"
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,20 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const HostelRoomSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ label="Hostel Room No."
8
+ dbValueProps={{
9
+ valueKey: 'id',
10
+ }}
11
+ dbLabelProps={{
12
+ labelKey: 'room_number',
13
+ subLabelKey: 'floor',
14
+ }}
15
+ {...props}
16
+ optionsApiEndPoint="dropdowns/hostel-rooms"
17
+ externalAxios={axios}
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,17 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const PrintFormatSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbLabelProps={{
8
+ labelKey: 'name',
9
+ subLabelKey: 'type',
10
+ useSubLabelStartCase: true,
11
+ }}
12
+ {...props}
13
+ externalAxios={axios}
14
+ optionsApiEndPoint="/dropdowns/print-formats"
15
+ />
16
+ );
17
+ };
@@ -0,0 +1,16 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const ProgramSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbLabelProps={{
8
+ labelKey: 'branchCode',
9
+ subLabelKey: 'branchDisplay',
10
+ }}
11
+ {...props}
12
+ externalAxios={axios}
13
+ optionsApiEndPoint="/dropdowns/programs"
14
+ />
15
+ );
16
+ };
@@ -0,0 +1,19 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const RegulationSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ label="Regulation"
8
+ dbValueProps={{
9
+ valueKey: 'regulation_id',
10
+ }}
11
+ dbLabelProps={{
12
+ labelKey: 'r.name',
13
+ }}
14
+ {...props}
15
+ optionsApiEndPoint="dropdowns/regulations"
16
+ externalAxios={axios}
17
+ />
18
+ );
19
+ };
@@ -0,0 +1,16 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { axios } from '../config/axios';
3
+
4
+ export const SemesterSelector = (props: SingleSelectProps) => {
5
+ return (
6
+ <SingleSelect
7
+ dbLabelProps={{
8
+ labelKey: 'name',
9
+ subLabelKey: 'year',
10
+ }}
11
+ {...props}
12
+ optionsApiEndPoint="/dropdowns/semesters"
13
+ externalAxios={axios}
14
+ />
15
+ );
16
+ };
@@ -0,0 +1,26 @@
1
+ import { SingleSelect, SingleSelectProps } from '@campxdev/react-blueprint';
2
+ import { years } from './utils';
3
+
4
+ interface YearRangeSelectorProps extends SingleSelectProps {
5
+ suffix?: string | null;
6
+ valueKey?: 'yearRange' | 'year';
7
+ }
8
+
9
+ export const YearRangeSelector = ({
10
+ suffix = null,
11
+ valueKey = 'yearRange',
12
+ ...props
13
+ }: YearRangeSelectorProps) => {
14
+ return (
15
+ <SingleSelect
16
+ label="Year Range"
17
+ options={years?.map((year: number) => ({
18
+ label: suffix
19
+ ? `${suffix} ${year} - ${year + 1}`
20
+ : `${year} - ${year + 1}`,
21
+ value: valueKey === 'yearRange' ? `${year} - ${year + 1}` : year,
22
+ }))}
23
+ {...props}
24
+ />
25
+ );
26
+ };
@@ -0,0 +1,13 @@
1
+ export * from './BatchSelector';
2
+ export * from './CourseSelector';
3
+ export * from './DepartmentSelector';
4
+ export * from './EmployeesSelector';
5
+ export * from './FeeTypeSelector';
6
+ export * from './HostelBlocksSelector';
7
+ export * from './HostelFloorSelector';
8
+ export * from './HostelRoomSelector';
9
+ export * from './PrintFormatSelector';
10
+ export * from './ProgramSelector';
11
+ export * from './RegulationSelector';
12
+ export * from './SemesterSelector';
13
+ export * from './YearRangeSelector';
@@ -0,0 +1,39 @@
1
+ export const FeeTypes: {
2
+ label: string;
3
+ value: string;
4
+ }[] = [
5
+ {
6
+ label: 'Tuition Fee',
7
+ value: 'tuition_fee',
8
+ },
9
+
10
+ {
11
+ label: 'Admission Fee',
12
+ value: 'admission_fee',
13
+ },
14
+ {
15
+ label: 'Hostel Fee',
16
+ value: 'hostel_fee',
17
+ },
18
+ {
19
+ label: 'Transport Fee',
20
+ value: 'transport_fee',
21
+ },
22
+ {
23
+ label: 'Exam Fee',
24
+ value: 'exam_fee',
25
+ },
26
+ {
27
+ label: 'Other Fee',
28
+ value: 'other_fee',
29
+ },
30
+ ];
31
+
32
+ export const years = Array.from({ length: 6 }, (_, i) => {
33
+ return new Date().getFullYear() - i;
34
+ });
35
+
36
+ export const batchOptions = Array.from({ length: 12 }, (_, i) => ({
37
+ label: `${new Date().getFullYear() - i} - ${new Date().getFullYear() - i + 1}`,
38
+ value: `${new Date().getFullYear() - i} - ${new Date().getFullYear() - i + 1}`,
39
+ }));
@@ -0,0 +1,5 @@
1
+ // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
+ // allows you to do things like:
3
+ // expect(element).toHaveTextContent(/react/i)
4
+ // learn more: https://github.com/testing-library/jest-dom
5
+ import '@testing-library/jest-dom';
@@ -0,0 +1,7 @@
1
+ export const isDevelopment = window.location.hostname.includes('localhost');
2
+
3
+ export const tenantCode = window.location.hostname.split('.')[0];
4
+
5
+ // if url searched is aupulse.campx.in then redirect to aupulse.campx.in/aupulse
6
+ export const institutionCode = window.location.pathname.split('/')[1];
7
+ export const workspace = window.location.pathname.split('/')[2];
@@ -0,0 +1,11 @@
1
+ export const openInNewTab = (pathAfterBase: string) => {
2
+ const currentPath = window.location.pathname;
3
+ const segments = currentPath.split('/');
4
+
5
+ // Get the dynamic basename (/aupulse/workspace)
6
+ const base = '/' + segments[1] + '/' + segments[2]; // careful with trailing slashes
7
+
8
+ // Construct full URL and open in new tab
9
+ const fullPath = `${window.location.origin}${base}/${pathAfterBase}`;
10
+ window.open(fullPath, '_blank');
11
+ };