@campxdev/shared 0.2.9 → 0.2.11

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campxdev/shared",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "main": "./exports.ts",
5
5
  "scripts": {
6
6
  "start": "react-scripts start",
@@ -5,15 +5,17 @@ const taskAttachmentImage = require('./taskAttachment.png')
5
5
  const pdfImage = require('./pdf.png')
6
6
  const NoPart = require('./NoPart.png')
7
7
  const FileBundleImage = require('./Filebundle.png')
8
-
9
8
  const resultProcessingImage = require('./ResultProcess.png')
9
+ const campxLogoPrimary = require('./campx_logo__full_primary.png')
10
+
10
11
  export {
11
- attachmentImage,
12
- avatarImage,
13
- welcomeImage,
14
- taskAttachmentImage,
15
- pdfImage,
16
- NoPart,
17
- resultProcessingImage,
18
- FileBundleImage,
12
+ attachmentImage,
13
+ avatarImage,
14
+ welcomeImage,
15
+ taskAttachmentImage,
16
+ pdfImage,
17
+ NoPart,
18
+ resultProcessingImage,
19
+ FileBundleImage,
20
+ campxLogoPrimary,
19
21
  }
@@ -1,175 +1,107 @@
1
- import {Box, IconButton, Menu, styled, Typography} from '@mui/material'
2
- import {useState} from 'react'
1
+ import {Box, styled, Typography} from '@mui/material'
3
2
  import {Link} from 'react-router-dom'
3
+ import {campxLogoPrimary} from '../../../assets/images'
4
4
  import {applications} from './applications'
5
+ import AppsMenu from './AppsMenu'
5
6
  import {collegex, enrollx, examx, payx, peoplex} from './assets'
6
7
  import CogWheelMenu from './CogWheelMenu'
7
8
  import FreshDeskHelpButton from './FreshDeskHelpButton'
8
- import {AppsIcon} from './icons'
9
9
  import Notification from './Notification'
10
10
  import {StyledHeader, StyledImageWrapper} from './styles'
11
11
  import UserBox from './UserBox'
12
12
 
13
+ const StyledLogosWrapper = styled(Box)(() => ({
14
+ display: 'flex',
15
+ alignItems: 'center',
16
+ gap: '10px',
17
+ padding: '10px',
18
+ transition: 'background ease 0.3s',
19
+ borderRadius: '5px',
20
+ '&:hover': {
21
+ background: 'rgba(0, 0, 0, 0.05)',
22
+ },
23
+ }))
24
+
25
+ const StyledLink = styled(Link)(() => ({
26
+ textDecoration: 'none',
27
+ }))
28
+
13
29
  const imageMap = {
14
30
  ums: collegex,
15
31
  enroll: enrollx,
16
32
  exams: examx,
17
33
  payments: payx,
18
34
  peoplex: peoplex,
19
- local: collegex,
35
+ campx: campxLogoPrimary,
20
36
  }
21
37
 
22
- const isDev = process.env.NODE_ENV === 'development'
38
+ interface AppHeaderProps {
39
+ clientLogo: string
40
+ username: string
41
+ profileIcon: string
42
+ permissions: any
43
+ }
23
44
 
24
- export default function AppHeader({title}: {title?: string}) {
25
- const originSubdomain = `https://www.exams.ums.in`.split('.')?.slice(-3)[0]
26
- console.log(originSubdomain)
27
- const currentApp =
28
- applications.find((item) => item.key === originSubdomain)?.key ?? 'local'
45
+ const isDev = process.env.NODE_ENV === 'development'
29
46
 
47
+ export default function AppHeader({
48
+ clientLogo = imageMap.campx,
49
+ username,
50
+ profileIcon,
51
+ permissions,
52
+ }: AppHeaderProps) {
30
53
  return (
31
54
  <StyledHeader>
32
- <Box sx={{display: 'flex', alignItems: 'center', gap: '20px'}}>
55
+ <Box sx={{display: 'flex', alignItems: 'center', gap: '10px'}}>
33
56
  <AppsMenu />
34
-
35
- <Link to={'/'}>
36
- {title ? (
37
- <Typography variant='h1'>{title}</Typography>
38
- ) : (
39
- <StyledImageWrapper>
40
- {isDev ? (
41
- <Typography variant='h6'>CampX</Typography>
42
- ) : (
43
- <img
44
- src={imageMap[currentApp]}
45
- style={{
46
- width: '200px',
47
- height: 'auto',
48
- }}
49
- />
50
- )}
51
- </StyledImageWrapper>
52
- )}
53
- </Link>
57
+ <AppLogo clientLogo={clientLogo} />
54
58
  </Box>
55
59
  <Box className='actions'>
56
60
  <FreshDeskHelpButton />
57
61
  <Notification />
58
62
  <CogWheelMenu />
59
- <UserBox />
63
+ <UserBox username={username} profileIcon={profileIcon} />
60
64
  </Box>
61
65
  </StyledHeader>
62
66
  )
63
67
  }
64
68
 
65
- const AppsMenu = () => {
66
- const [anchorEl, setAnchorEl] = useState<any>(null)
67
- const open = Boolean(anchorEl)
68
-
69
- const handleClick = (event) => {
70
- setAnchorEl(event.currentTarget)
71
- }
72
-
73
- const handleClose = () => {
74
- setAnchorEl(null)
75
- }
69
+ const AppLogo = ({clientLogo}) => {
70
+ const originSubdomain =
71
+ window.location.origin.split('.')?.slice(-3)[0] ?? 'ums'
72
+ const currentApp =
73
+ applications.find((item) => item.key === originSubdomain)?.key ?? 'local'
76
74
 
77
75
  return (
78
- <Box sx={{marginRight: '10px'}}>
79
- <StyledIconButton onClick={handleClick}>
80
- <AppsIcon />
81
- </StyledIconButton>
82
-
83
- <Menu
84
- elevation={2}
85
- id='basic-menu'
86
- anchorEl={anchorEl}
87
- open={open}
88
- onClose={handleClose}
89
- MenuListProps={{
90
- sx: {
91
- padding: 0,
92
- margin: 0,
93
- },
94
- }}
95
- anchorOrigin={{
96
- vertical: 'bottom',
97
- horizontal: 'left',
98
- }}
99
- transformOrigin={{
100
- vertical: 'top',
101
- horizontal: 'left',
102
- }}
103
- sx={{
104
- '& .MuiPaper-root': {
105
- left: '0px',
106
- },
107
- }}
108
- >
109
- <Box sx={{padding: '1rem 1.5rem'}}>
110
- <Typography variant='h6'>Switch to</Typography>
111
- </Box>
112
- <Box>
113
- {applications.map((item, index) => (
114
- <StyledMenuItemContainer
115
- key={index}
116
- onClick={() => {
117
- window.location.href = item.path
118
- handleClose()
76
+ <StyledLink to={'/'}>
77
+ <StyledLogosWrapper>
78
+ <StyledImageWrapper>
79
+ {isDev ? (
80
+ <img src={imageMap.campx} />
81
+ ) : (
82
+ <img src={imageMap[currentApp]} />
83
+ )}
84
+ </StyledImageWrapper>
85
+ <Box
86
+ sx={{
87
+ height: '26px',
88
+ width: '2px',
89
+ background: 'gray',
90
+ }}
91
+ ></Box>
92
+ <StyledImageWrapper>
93
+ {isDev ? (
94
+ <Typography variant='h1'>Developer</Typography>
95
+ ) : (
96
+ <img
97
+ src={clientLogo}
98
+ onError={(e: any) => {
99
+ e.target.src = imageMap.campx
119
100
  }}
120
- >
121
- <StyledMenuItem data={item} />
122
- </StyledMenuItemContainer>
123
- ))}
124
- </Box>
125
- </Menu>
126
- </Box>
127
- )
128
- }
129
-
130
- const StyledMenuItem = ({data}) => {
131
- return (
132
- <StyledMenuitem>
133
- <Box>{data.icon}</Box>
134
- <Box>
135
- <Typography variant='h1'>{data?.title}</Typography>
136
- <StyledDescription>{data?.description}</StyledDescription>
137
- </Box>
138
- </StyledMenuitem>
101
+ />
102
+ )}
103
+ </StyledImageWrapper>
104
+ </StyledLogosWrapper>
105
+ </StyledLink>
139
106
  )
140
107
  }
141
-
142
- const StyledIconButton = styled(IconButton)({
143
- padding: '20px',
144
- backgroundColor: 'black',
145
- display: 'flex',
146
- alignItems: 'center',
147
- justifyContent: 'center',
148
- borderRadius: '0px',
149
- })
150
-
151
- const StyledDescription = styled(Typography)(({theme}) => ({
152
- fontSize: '15px',
153
- fontWeight: 500,
154
- color: theme?.palette?.secondary?.main,
155
- }))
156
-
157
- const StyledMenuitem = styled(Box)({
158
- height: '72px',
159
- width: '400px',
160
- padding: '40px 20px',
161
- '&:hover': {
162
- background: 'rgba(0, 0, 0, 0.03)',
163
- },
164
- display: 'flex',
165
- alignItems: 'center',
166
- gap: '10px',
167
- })
168
-
169
- const StyledMenuItemContainer = styled(Box)(({theme}) => ({
170
- cursor: 'pointer',
171
- borderBottom: `1px solid ${theme?.palette?.secondary?.lighter}`,
172
- '&:last-of-type': {
173
- border: 'none',
174
- },
175
- }))
@@ -0,0 +1,85 @@
1
+ import {Box, Menu, Typography} from '@mui/material'
2
+ import {useState} from 'react'
3
+ import {applications} from './applications'
4
+ import {AppsIcon} from './icons'
5
+ import {
6
+ StyledDescription,
7
+ StyledIconButton,
8
+ StyledMenuItem,
9
+ StyledMenuItemContainer,
10
+ } from './styles'
11
+
12
+ const AppsMenu = () => {
13
+ const [anchorEl, setAnchorEl] = useState<any>(null)
14
+ const open = Boolean(anchorEl)
15
+
16
+ const handleClick = (event) => {
17
+ setAnchorEl(event.currentTarget)
18
+ }
19
+
20
+ const handleClose = () => {
21
+ setAnchorEl(null)
22
+ }
23
+
24
+ return (
25
+ <>
26
+ <StyledIconButton onClick={handleClick}>
27
+ <AppsIcon />
28
+ </StyledIconButton>
29
+
30
+ <Menu
31
+ transitionDuration={150}
32
+ elevation={3}
33
+ id='basic-menu'
34
+ anchorEl={anchorEl}
35
+ open={open}
36
+ onClose={handleClose}
37
+ anchorOrigin={{
38
+ vertical: 'bottom',
39
+ horizontal: 'left',
40
+ }}
41
+ transformOrigin={{
42
+ vertical: 'top',
43
+ horizontal: 'left',
44
+ }}
45
+ sx={{
46
+ '& .MuiPaper-root': {
47
+ left: '0 !important',
48
+ top: '65px !important',
49
+ },
50
+ }}
51
+ >
52
+ <Box sx={{padding: '0.3rem 1rem'}}>
53
+ <Typography variant='body2'>Switch to</Typography>
54
+ </Box>
55
+ <Box>
56
+ {applications.map((item, index) => (
57
+ <StyledMenuItemContainer
58
+ key={index}
59
+ onClick={() => {
60
+ window.location.href = item.path
61
+ handleClose()
62
+ }}
63
+ >
64
+ <MenuItem data={item} />
65
+ </StyledMenuItemContainer>
66
+ ))}
67
+ </Box>
68
+ </Menu>
69
+ </>
70
+ )
71
+ }
72
+
73
+ export default AppsMenu
74
+
75
+ const MenuItem = ({data}) => {
76
+ return (
77
+ <StyledMenuItem>
78
+ <Box height={'20px'}>{data.icon}</Box>
79
+ <Box>
80
+ <Typography variant='h1'>{data?.title}</Typography>
81
+ <StyledDescription>{data?.description}</StyledDescription>
82
+ </Box>
83
+ </StyledMenuItem>
84
+ )
85
+ }
@@ -1,51 +1,87 @@
1
1
  import {
2
- ExitToAppOutlined,
3
- HttpsOutlined,
4
- PermIdentityOutlined,
2
+ ExitToAppOutlined,
3
+ HttpsOutlined,
4
+ PermIdentityOutlined,
5
5
  } from '@mui/icons-material'
6
- import { Avatar, Typography } from '@mui/material'
7
- import { useHistory } from '../../../hooks/useRouter'
8
- import { avatarImage } from '../../../assets/images'
9
- import { UserStore } from '../../../shared-state/UserStore'
6
+ import {Avatar, Box, CircularProgress, Typography} from '@mui/material'
7
+ import {useHistory} from '../../../hooks/useRouter'
8
+ import {avatarImage} from '../../../assets/images'
10
9
  import MenuButton from '../../MenuButton'
11
- import { StyledUser } from './styles'
10
+ import {StyledUser} from './styles'
11
+ import axios from 'axios'
12
+ import {axiosErrorToast} from '../../../config/axios'
13
+ import {isDevelopment} from '../../../constants/isDevelopment'
14
+ import Cookies from 'js-cookie'
15
+ import {useState} from 'react'
12
16
 
13
- async function logout() {
14
- localStorage.removeItem('token')
15
- window.location.reload()
16
- }
17
+ export default function UserBox({
18
+ username,
19
+ profileIcon,
20
+ }: {
21
+ username: string
22
+ profileIcon: string
23
+ }) {
24
+ const history = useHistory()
25
+ const [posting, setPosting] = useState(false)
26
+
27
+ async function logout() {
28
+ if (isDevelopment) {
29
+ Cookies.remove('campx_session_key')
30
+ window.location.href = '/'
31
+ return
32
+ }
17
33
 
18
- export default function UserBox() {
19
- const user = UserStore.useState((s) => s).user
20
- const history = useHistory()
34
+ setPosting(true)
35
+ axios
36
+ .post(`${process.env.REACT_APP_API_HOST}/auth/logout`)
37
+ .then((res) => {
38
+ setPosting(false)
39
+ window.location.href = '/'
40
+ })
41
+ .catch((err) => {
42
+ setPosting(false)
43
+ axiosErrorToast('Unable To Logout.')
44
+ })
45
+ }
21
46
 
22
- return (
23
- <MenuButton
24
- anchor={
25
- <StyledUser>
26
- <Avatar src={user?.picture?.url ?? avatarImage} />
27
- <Typography variant="h6">{user?.fullName}</Typography>
28
- </StyledUser>
29
- }
30
- menu={[
31
- {
32
- label: 'Profile',
33
- icon: <PermIdentityOutlined />,
34
- onClick: () => {
35
- history.push('/profile')
36
- },
37
- },
38
- {
39
- label: 'Change Password',
40
- icon: <HttpsOutlined />,
41
- onClick: () => {},
42
- },
43
- {
44
- label: 'Logout',
45
- icon: <ExitToAppOutlined />,
46
- onClick: logout,
47
- },
48
- ]}
49
- />
50
- )
47
+ return (
48
+ <MenuButton
49
+ anchor={
50
+ <Box minWidth={'80px'} textAlign='center'>
51
+ {!posting ? (
52
+ <StyledUser>
53
+ <Avatar src={profileIcon ?? avatarImage} />
54
+ <Typography variant='h6'>{username}</Typography>
55
+ </StyledUser>
56
+ ) : (
57
+ <CircularProgress
58
+ size={16}
59
+ sx={{
60
+ color: ({palette}) => palette.primary.main,
61
+ }}
62
+ />
63
+ )}
64
+ </Box>
65
+ }
66
+ menu={[
67
+ {
68
+ label: 'Profile',
69
+ icon: <PermIdentityOutlined />,
70
+ onClick: () => {
71
+ history.push('/profile')
72
+ },
73
+ },
74
+ {
75
+ label: 'Change Password',
76
+ icon: <HttpsOutlined />,
77
+ onClick: () => {},
78
+ },
79
+ {
80
+ label: 'Logout',
81
+ icon: <ExitToAppOutlined />,
82
+ onClick: logout,
83
+ },
84
+ ]}
85
+ />
86
+ )
51
87
  }
@@ -1,48 +1,92 @@
1
- import { AppBar, Box, ListItemText, styled } from '@mui/material'
1
+ import {
2
+ AppBar,
3
+ Box,
4
+ IconButton,
5
+ ListItemText,
6
+ styled,
7
+ Typography,
8
+ } from '@mui/material'
2
9
 
3
10
  export const StyledImageWrapper = styled('div')`
4
- width: auto;
5
- height: 24px;
6
- & img {
7
- width: 100%;
8
- height: 100%;
9
- object-fit: contain;
10
- }
11
+ width: auto;
12
+ height: 20px;
13
+ & img {
14
+ width: 100%;
15
+ height: 100%;
16
+ object-fit: contain;
17
+ }
11
18
  `
12
19
 
13
- export const StyledItemText = styled(ListItemText)(({ theme }) => ({
14
- color: theme.palette.text.primary,
15
- transition: '0.2s ease',
20
+ export const StyledItemText = styled(ListItemText)(({theme}) => ({
21
+ color: theme.palette.text.primary,
22
+ transition: '0.2s ease',
16
23
  }))
17
24
 
18
- export const StyledAppBar = styled(AppBar)(({ theme }) => ({
19
- backgroundColor: 'white',
20
- boxShadow: '0px 8px 28px rgb(136,136,136, 0.3)',
25
+ export const StyledAppBar = styled(AppBar)(({theme}) => ({
26
+ backgroundColor: 'white',
27
+ boxShadow: '0px 8px 28px rgb(136,136,136, 0.3)',
21
28
  }))
22
29
 
23
- export const StyledHeader = styled(Box)(({ theme }) => ({
24
- boxShadow: '0px 2px 10px #0000001a',
25
- // padding: '0 1rem',
26
- backgroundColor: 'white',
27
- display: 'flex',
28
- alignItems: 'center',
29
- justifyContent: 'space-between',
30
- '& .actions': {
31
- display: 'flex',
32
- alignItems: 'center',
33
- gap: '14px',
34
- },
30
+ export const StyledHeader = styled(Box)(({theme}) => ({
31
+ boxShadow: '0px 2px 10px #0000001a',
32
+ // padding: '0 1rem',
33
+ backgroundColor: 'white',
34
+ display: 'flex',
35
+ alignItems: 'center',
36
+ justifyContent: 'space-between',
37
+ '& .actions': {
38
+ marginRight: '10px',
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ gap: '14px',
42
+ },
35
43
  }))
36
44
 
37
- export const StyledUser = styled(Box)(({ theme }) => ({
38
- cursor: 'pointer',
39
- borderRadius: '5px',
40
- transition: 'background 0.2s ease',
41
- padding: '5px 10px',
42
- display: 'flex',
43
- alignItems: 'center',
44
- gap: '10px',
45
- '&:hover': {
46
- background: theme.palette.secondary.light,
47
- },
45
+ export const StyledUser = styled(Box)(({theme}) => ({
46
+ cursor: 'pointer',
47
+ borderRadius: '5px',
48
+ transition: 'background 0.2s ease',
49
+ padding: '5px 10px',
50
+ display: 'flex',
51
+ alignItems: 'center',
52
+ gap: '10px',
53
+ '&:hover': {
54
+ background: theme.palette.secondary.light,
55
+ },
56
+ }))
57
+
58
+ export const StyledIconButton = styled(IconButton)({
59
+ padding: '20px',
60
+ backgroundColor: 'black',
61
+ display: 'flex',
62
+ alignItems: 'center',
63
+ justifyContent: 'center',
64
+ borderRadius: '0px',
65
+ })
66
+
67
+ export const StyledDescription = styled(Typography)(({theme}) => ({
68
+ fontSize: '15px',
69
+ fontWeight: 500,
70
+ color: theme?.palette?.secondary?.main,
71
+ }))
72
+
73
+ export const StyledMenuItem = styled(Box)({
74
+ height: '64px',
75
+ width: '360px',
76
+ padding: '20px',
77
+ transition: 'background ease 0.3s',
78
+ '&:hover': {
79
+ background: 'rgba(0, 0, 0, 0.03)',
80
+ },
81
+ display: 'flex',
82
+ alignItems: 'center',
83
+ gap: '10px',
84
+ })
85
+
86
+ export const StyledMenuItemContainer = styled(Box)(({theme}) => ({
87
+ cursor: 'pointer',
88
+ borderBottom: `1px solid ${theme?.palette?.secondary?.lighter}`,
89
+ '&:last-of-type': {
90
+ border: 'none',
91
+ },
48
92
  }))
@@ -1,84 +1,85 @@
1
- import { Close } from '@mui/icons-material'
1
+ import {Close} from '@mui/icons-material'
2
2
  import {
3
- alpha,
4
- Box,
5
- ButtonProps,
6
- Dialog,
7
- DialogProps,
8
- IconButton,
9
- styled,
10
- Typography,
3
+ alpha,
4
+ Box,
5
+ ButtonProps,
6
+ Dialog,
7
+ DialogProps,
8
+ IconButton,
9
+ styled,
10
+ Typography,
11
11
  } from '@mui/material'
12
- import { createElement, ReactNode, useState } from 'react'
12
+ import {createElement, ReactNode, useState} from 'react'
13
13
 
14
- const StyledDialogHeader = styled(Box)(({ theme }) => ({
15
- height: '64px',
16
- backgroundColor: alpha(theme.palette.text.secondary, 0.1),
17
- display: 'flex',
18
- justifyContent: 'space-between',
19
- alignItems: 'center',
20
- padding: '0.6rem 1rem',
14
+ const StyledDialogHeader = styled(Box)(({theme}) => ({
15
+ height: '64px',
16
+ backgroundColor: alpha(theme.palette.text.secondary, 0.1),
17
+ display: 'flex',
18
+ justifyContent: 'space-between',
19
+ alignItems: 'center',
20
+ padding: '0.6rem 1rem',
21
21
  }))
22
22
 
23
- const StyledDialogContent = styled(Box)(({ theme }) => ({
24
- width: '100%',
25
- padding: '1rem',
23
+ const StyledDialogContent = styled(Box)(({theme}) => ({
24
+ width: '100%',
25
+ padding: '1rem',
26
26
  }))
27
27
 
28
28
  type ContentProps = {
29
- close: () => void
29
+ close: () => void
30
30
  }
31
31
 
32
32
  interface DrawerButtonProps {
33
- button: any
34
- content: (props: ContentProps) => ReactNode
35
- title: string | ReactNode
36
- btnTxt?: string | ReactNode
37
- btnProps?: ButtonProps
38
- dialogProps?: Omit<DialogProps, 'open'>
33
+ button: any
34
+ content: (props: ContentProps) => ReactNode
35
+ title: string | ReactNode
36
+ btnTxt?: string | ReactNode
37
+ btnProps?: ButtonProps
38
+ dialogProps?: Omit<DialogProps, 'open'>
39
39
  }
40
40
 
41
41
  export default function DialogButton({
42
- button: Button,
43
- content,
44
- title,
45
- btnTxt,
46
- btnProps,
47
- dialogProps,
42
+ button: Button,
43
+ content,
44
+ title,
45
+ btnTxt,
46
+ btnProps,
47
+ dialogProps,
48
48
  }: DrawerButtonProps) {
49
- const [open, setOpen] = useState(false)
49
+ const [open, setOpen] = useState(false)
50
50
 
51
- const ButtonEl = (props) => (
52
- <Button {...props} {...btnProps}>
53
- {btnTxt}
54
- </Button>
55
- )
51
+ const ButtonEl = (props) => (
52
+ <Button {...props} {...btnProps}>
53
+ {btnTxt}
54
+ </Button>
55
+ )
56
56
 
57
- const MyButton = createElement(ButtonEl, {
58
- onClick: () => setOpen(true),
59
- })
57
+ const MyButton = createElement(ButtonEl, {
58
+ onClick: () => setOpen(true),
59
+ })
60
60
 
61
- const onClose = () => {
62
- setOpen(false)
63
- }
64
- return (
65
- <>
66
- {MyButton}
67
- <Dialog
68
- PaperProps={{ sx: { borderRadius: '10px' } }}
69
- fullWidth
70
- onClose={onClose}
71
- open={open}
72
- {...dialogProps}
73
- >
74
- <StyledDialogHeader>
75
- <Typography fontWeight={600}>{title}</Typography>
76
- <IconButton onClick={onClose}>
77
- <Close />
78
- </IconButton>
79
- </StyledDialogHeader>
80
- <StyledDialogContent>{content({ close: onClose })}</StyledDialogContent>
81
- </Dialog>
82
- </>
83
- )
61
+ const onClose = () => {
62
+ setOpen(false)
63
+ }
64
+ return (
65
+ <>
66
+ {MyButton}
67
+ <Dialog
68
+ PaperProps={{sx: {borderRadius: '10px'}}}
69
+ fullWidth
70
+ onClose={onClose}
71
+ open={open}
72
+ transitionDuration={200}
73
+ {...dialogProps}
74
+ >
75
+ <StyledDialogHeader>
76
+ <Typography fontWeight={600}>{title}</Typography>
77
+ <IconButton onClick={onClose}>
78
+ <Close />
79
+ </IconButton>
80
+ </StyledDialogHeader>
81
+ <StyledDialogContent>{content({close: onClose})}</StyledDialogContent>
82
+ </Dialog>
83
+ </>
84
+ )
84
85
  }
@@ -1,33 +1,34 @@
1
1
  import {
2
- Button,
3
- Dialog,
4
- DialogActions,
5
- DialogContent,
6
- DialogTitle,
2
+ Button,
3
+ Dialog,
4
+ DialogActions,
5
+ DialogContent,
6
+ DialogTitle,
7
7
  } from '@mui/material'
8
8
  import useConfirm from './useConfirm'
9
9
 
10
10
  const PopupConfirm = () => {
11
- const { prompt = '', isOpen = false, proceed, cancel } = useConfirm()
12
- return (
13
- <Dialog
14
- sx={{ zIndex: 1600 }}
15
- keepMounted
16
- maxWidth="sm"
17
- fullWidth
18
- open={isOpen}
19
- >
20
- <DialogTitle>Confirm</DialogTitle>
21
- <DialogContent sx={{ minHeight: '40px' }}>{prompt}</DialogContent>
22
- <DialogActions>
23
- <Button variant="contained" color="primary" onClick={proceed}>
24
- Ok
25
- </Button>
26
- <Button color="secondary" variant="outlined" onClick={cancel}>
27
- Cancel
28
- </Button>
29
- </DialogActions>
30
- </Dialog>
31
- )
11
+ const {prompt = '', isOpen = false, proceed, cancel} = useConfirm()
12
+ return (
13
+ <Dialog
14
+ sx={{zIndex: 1600}}
15
+ keepMounted
16
+ maxWidth='sm'
17
+ fullWidth
18
+ open={isOpen}
19
+ transitionDuration={150}
20
+ >
21
+ <DialogTitle>Confirm</DialogTitle>
22
+ <DialogContent sx={{minHeight: '40px'}}>{prompt}</DialogContent>
23
+ <DialogActions>
24
+ <Button variant='contained' color='primary' onClick={proceed}>
25
+ Ok
26
+ </Button>
27
+ <Button color='secondary' variant='outlined' onClick={cancel}>
28
+ Cancel
29
+ </Button>
30
+ </DialogActions>
31
+ </Dialog>
32
+ )
32
33
  }
33
34
  export default PopupConfirm
@@ -0,0 +1,3 @@
1
+ export const isDevelopment =
2
+ process.env.NODE_ENV === 'development' ||
3
+ window.location.origin.split('.').slice(-2).join('.') === 'campx.dev'
@@ -1,166 +1,167 @@
1
- import { Spinner } from '../../components'
2
- import { useFetch } from '../../hooks'
3
- import axios from '../../config/axios'
4
- import { Visibility, VisibilityOff } from '@mui/icons-material'
1
+ import {Spinner} from '../../components'
2
+ import {useFetch} from '../../hooks'
3
+ import {Visibility, VisibilityOff} from '@mui/icons-material'
5
4
  import {
6
- Alert,
7
- Box,
8
- IconButton,
9
- InputAdornment,
10
- Stack,
11
- Typography,
5
+ Alert,
6
+ Box,
7
+ IconButton,
8
+ InputAdornment,
9
+ Stack,
10
+ Typography,
12
11
  } from '@mui/material'
13
- import { useState } from 'react'
14
- import { useForm } from 'react-hook-form'
15
- import { welcomeImage } from '../../assets/images'
12
+ import {useState} from 'react'
13
+ import {useForm} from 'react-hook-form'
14
+ import {welcomeImage} from '../../assets/images'
16
15
  import {
17
- StyledBanner,
18
- StyledBannerFooter,
19
- StyledBannerImage,
20
- StyledButton,
21
- StyledFormSection,
22
- StyledLink,
23
- StyledMain,
24
- StyledTextField,
16
+ StyledBanner,
17
+ StyledBannerFooter,
18
+ StyledBannerImage,
19
+ StyledButton,
20
+ StyledFormSection,
21
+ StyledLink,
22
+ StyledMain,
23
+ StyledTextField,
25
24
  } from './styles'
26
- import { useNavigate } from 'react-router-dom'
25
+ import {useNavigate} from 'react-router-dom'
27
26
  import Cookies from 'js-cookie'
28
27
  import axiosBase from 'axios'
29
28
 
30
29
  const LoginPage = () => {
31
- const { loading, data: assets } = useFetch('/assets')
30
+ const {loading, data: assets} = useFetch('/assets')
32
31
 
33
- if (loading) {
34
- return <Spinner />
35
- }
32
+ if (loading) {
33
+ return <Spinner />
34
+ }
36
35
 
37
- return (
38
- <>
39
- <StyledMain>
40
- <StyledBanner>
41
- <StyledBannerImage>
42
- <img src={welcomeImage} alt="login-banner" />
43
- </StyledBannerImage>
44
- <StyledBannerFooter>
45
- <div className="logo">
46
- <Typography variant="body1">Powered By</Typography>
47
- <img
48
- src={
49
- 'https://campx-logos.s3.ap-south-1.amazonaws.com/CampX.png'
50
- }
51
- alt="login-banner"
52
- />
53
- </div>
54
- <div className="copyright">
55
- <Typography variant="subtitle1">
56
- &#169; All Rights reserved to CampX Edutech Pvt. Ltd., 2022
57
- </Typography>
58
- </div>
59
- </StyledBannerFooter>
60
- </StyledBanner>
61
- <StyledFormSection>
62
- <Box width={'100%'}>
63
- <Box
64
- sx={{
65
- display: 'flex',
66
- justifyContent: 'center',
67
- marginBottom: '54px',
68
- }}
69
- >
70
- <img
71
- src={assets?.logo}
72
- style={{
73
- width: '200px',
74
- }}
75
- />
76
- </Box>
77
- <LoginForm />
78
- </Box>
79
- </StyledFormSection>
80
- </StyledMain>
81
- <StyledLink
82
- style={{
83
- textAlign: 'right',
84
- display: 'block',
85
- position: 'absolute',
86
- top: '20px',
87
- right: '20px',
88
- }}
89
- href="/results/search"
90
- >
91
- Student Results
92
- </StyledLink>
93
- </>
94
- )
36
+ return (
37
+ <>
38
+ <StyledMain>
39
+ <StyledBanner>
40
+ <StyledBannerImage>
41
+ <img src={welcomeImage} alt='login-banner' />
42
+ </StyledBannerImage>
43
+ <StyledBannerFooter>
44
+ <div className='logo'>
45
+ <Typography variant='body1'>Powered By</Typography>
46
+ <img
47
+ src={
48
+ 'https://campx-logos.s3.ap-south-1.amazonaws.com/CampX.png'
49
+ }
50
+ alt='login-banner'
51
+ />
52
+ </div>
53
+ <div className='copyright'>
54
+ <Typography variant='subtitle1'>
55
+ &#169; All Rights reserved to CampX Edutech Pvt. Ltd., 2022
56
+ </Typography>
57
+ </div>
58
+ </StyledBannerFooter>
59
+ </StyledBanner>
60
+ <StyledFormSection>
61
+ <Box width={'100%'}>
62
+ <Box
63
+ sx={{
64
+ display: 'flex',
65
+ justifyContent: 'center',
66
+ marginBottom: '54px',
67
+ }}
68
+ >
69
+ <img
70
+ src={assets?.logo}
71
+ style={{
72
+ width: '200px',
73
+ }}
74
+ />
75
+ </Box>
76
+ <LoginForm />
77
+ </Box>
78
+ </StyledFormSection>
79
+ </StyledMain>
80
+ <StyledLink
81
+ style={{
82
+ textAlign: 'right',
83
+ display: 'block',
84
+ position: 'absolute',
85
+ top: '20px',
86
+ right: '20px',
87
+ }}
88
+ href='/results/search'
89
+ >
90
+ Student Results
91
+ </StyledLink>
92
+ </>
93
+ )
95
94
  }
96
95
 
97
96
  export default LoginPage
98
97
 
99
98
  export function LoginForm() {
100
- const [showPassword, setShowPassword] = useState(false)
101
- const { handleSubmit, control } = useForm()
102
- const [error, setError] = useState('')
99
+ const [showPassword, setShowPassword] = useState(false)
100
+ const {handleSubmit, control} = useForm()
101
+ const [error, setError] = useState('')
103
102
 
104
- const onSubmit = async (values) => {
105
- try {
106
- const res = await axiosBase.post(
107
- `https://auth-api.campx.in/auth/login`,
108
- values,
109
- )
110
- Cookies.set('campx_session_key', res.data.cookie)
111
- window.location.href = '/'
112
- } catch (err) {
113
- // eslint-disable-next-line no-console
114
- console.log(err)
115
- setError(err.response.data.message ?? 'Server Error')
116
- }
117
- }
103
+ const onSubmit = async (values) => {
104
+ try {
105
+ const res = await axiosBase({
106
+ baseURL: process.env.REACT_APP_API_URL,
107
+ url: '/auth/login',
108
+ data: {
109
+ values,
110
+ },
111
+ })
112
+ Cookies.set('campx_session_key', res.data.cookie)
113
+ window.location.href = '/'
114
+ } catch (err) {
115
+ // eslint-disable-next-line no-console
116
+ console.log(err)
117
+ setError(err.response.data.message ?? 'Server Error')
118
+ }
119
+ }
118
120
 
119
- return (
120
- <Box sx={{ maxWidth: '500px' }} margin="0 auto" padding={'0 1rem'}>
121
- <form onSubmit={handleSubmit(onSubmit)}>
122
- <Stack gap={'40px'}>
123
- <Box>
124
- <StyledTextField
125
- size="medium"
126
- control={control}
127
- name="username"
128
- label="User ID"
129
- required
130
- />
131
- </Box>
132
- <Box>
133
- <StyledTextField
134
- control={control}
135
- name="password"
136
- label="Password"
137
- type={showPassword ? 'text' : 'password'}
138
- required
139
- InputProps={{
140
- endAdornment: (
141
- <InputAdornment position="end">
142
- <IconButton
143
- size="small"
144
- aria-label="toggle password visibility"
145
- onClick={() => setShowPassword((prev) => !prev)}
146
- edge="end"
147
- >
148
- {showPassword ? <VisibilityOff /> : <Visibility />}
149
- </IconButton>
150
- </InputAdornment>
151
- ),
152
- }}
153
- />
154
- </Box>
155
- <StyledButton type="submit">Login</StyledButton>
156
- </Stack>
157
- </form>
158
- {error && (
159
- <Alert severity="error" sx={{ marginTop: '20px' }}>
160
- {error}
161
- </Alert>
162
- )}
163
- </Box>
164
- )
121
+ return (
122
+ <Box sx={{maxWidth: '500px'}} margin='0 auto' padding={'0 1rem'}>
123
+ <form onSubmit={handleSubmit(onSubmit)}>
124
+ <Stack gap={'40px'}>
125
+ <Box>
126
+ <StyledTextField
127
+ size='medium'
128
+ control={control}
129
+ name='username'
130
+ label='User ID'
131
+ required
132
+ />
133
+ </Box>
134
+ <Box>
135
+ <StyledTextField
136
+ control={control}
137
+ name='password'
138
+ label='Password'
139
+ type={showPassword ? 'text' : 'password'}
140
+ required
141
+ InputProps={{
142
+ endAdornment: (
143
+ <InputAdornment position='end'>
144
+ <IconButton
145
+ size='small'
146
+ aria-label='toggle password visibility'
147
+ onClick={() => setShowPassword((prev) => !prev)}
148
+ edge='end'
149
+ >
150
+ {showPassword ? <VisibilityOff /> : <Visibility />}
151
+ </IconButton>
152
+ </InputAdornment>
153
+ ),
154
+ }}
155
+ />
156
+ </Box>
157
+ <StyledButton type='submit'>Login</StyledButton>
158
+ </Stack>
159
+ </form>
160
+ {error && (
161
+ <Alert severity='error' sx={{marginTop: '20px'}}>
162
+ {error}
163
+ </Alert>
164
+ )}
165
+ </Box>
166
+ )
165
167
  }
166
-
@@ -1,6 +0,0 @@
1
- export default function MainAppHeader() {
2
- return (
3
- // <div>MainAppHeader</div
4
- <></>
5
- )
6
- }