@campxdev/shared 1.2.9 → 1.3.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.
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@campxdev/shared",
3
- "version": "1.2.9",
3
+ "version": "1.3.0",
4
4
  "main": "./exports.ts",
5
5
  "scripts": {
6
6
  "start": "react-scripts start",
7
+ "dev": "react-scripts start",
7
8
  "build": "CI=false && react-scripts build",
8
9
  "test": "react-scripts test",
9
10
  "eject": "react-scripts eject",
@@ -3,26 +3,17 @@ import React from 'react'
3
3
 
4
4
  interface ActionButtonProps extends ButtonProps {
5
5
  loading?: boolean
6
- [key: string]: any
7
- variant?: any
8
6
  }
9
7
 
10
- export default function ActionButton({
11
- children,
12
- loading,
13
- ...props
14
- }: ActionButtonProps) {
8
+ export default function ActionButton({ loading, ...props }: ActionButtonProps) {
15
9
  return (
16
- <React.Fragment>
17
- <Button
18
- variant={!props?.variant ? 'contained' : props?.variant}
19
- color="primary"
20
- endIcon={loading ? <CircularProgress size={20} /> : null}
21
- disabled={loading}
22
- {...props}
23
- >
24
- {children}
25
- </Button>
26
- </React.Fragment>
10
+ <Button
11
+ variant={!props?.variant ? 'contained' : props?.variant}
12
+ endIcon={loading ? <CircularProgress size={20} /> : null}
13
+ disabled={loading}
14
+ {...props}
15
+ >
16
+ {props.children}
17
+ </Button>
27
18
  )
28
19
  }
@@ -1,43 +1,28 @@
1
+ import { Visibility, VisibilityOff } from '@mui/icons-material'
1
2
  import {
2
3
  Button,
3
4
  CircularProgress,
4
- Dialog,
5
- DialogTitle,
6
5
  IconButton,
7
6
  InputAdornment,
8
7
  Stack,
9
- styled,
10
- Typography,
11
8
  } from '@mui/material'
12
- import { isDevelopment } from '../constants/isDevelopment'
13
- import CloseIcon from '@mui/icons-material/Close'
14
- import { Visibility, VisibilityOff } from '@mui/icons-material'
15
- import React, { useState } from 'react'
9
+ import { useState } from 'react'
16
10
  import { useForm } from 'react-hook-form'
17
- import { useModal } from './DrawerWrapper/DrawerWrapper'
11
+ import { toast } from 'react-toastify'
18
12
  import { FormTextField } from '.'
19
13
  import axios, { axiosErrorToast } from '../config/axios'
20
- import { toast } from 'react-toastify'
21
-
22
- export interface DialogProps {
23
- open: boolean
24
- onClose: any
25
- }
26
-
27
- function ChangePassword(props: DialogProps) {
28
- const { onClose, open } = props
29
- const handleClose = () => {
30
- onClose()
31
- }
32
- const modal = useModal()
14
+ import { isDevelopment } from '../constants/isDevelopment'
33
15
 
16
+ function ChangePassword({ close }) {
34
17
  const [showPassword, setShowPassword] = useState({
35
18
  oldPassword: false,
36
19
  newPassword: false,
37
20
  confirmPassword: false,
38
21
  })
39
22
  const [isLoading, setIsLoading] = useState(false)
23
+
40
24
  const { handleSubmit, control, reset } = useForm()
25
+
41
26
  const onSubmit = async (formData) => {
42
27
  setIsLoading(true)
43
28
  const { oldPassword, newPassword, confirmPassword } = formData
@@ -55,12 +40,10 @@ function ChangePassword(props: DialogProps) {
55
40
  toast.success('Password Changed Successfully')
56
41
  setIsLoading(false)
57
42
  reset()
58
- handleClose()
43
+ close()
59
44
  } catch (error) {
60
45
  axiosErrorToast(error)
61
46
  setIsLoading(false)
62
- reset()
63
- handleClose()
64
47
  }
65
48
  } else {
66
49
  toast.error('New Password, Confirm Password must be same')
@@ -75,90 +58,66 @@ function ChangePassword(props: DialogProps) {
75
58
  ]
76
59
 
77
60
  return (
78
- <Dialog
79
- open={open}
80
- PaperProps={{
81
- sx: {
82
- borderRadius: '20px',
83
- width: '500px',
84
- padding: '20px',
85
- },
86
- }}
87
- >
88
- <StyledDialogTitle>
89
- <Typography variant="h3">Change Password</Typography>
90
- <IconButton onClick={handleClose}>
91
- <CloseIcon />
92
- </IconButton>
93
- </StyledDialogTitle>
94
- <form onSubmit={handleSubmit(onSubmit)}>
95
- <Stack gap={2} direction="column">
96
- {fields.map((item) => {
97
- return (
98
- <>
99
- <FormTextField
100
- label={item.label}
101
- control={control}
102
- name={item.name}
103
- type={showPassword[item.name] ? 'text' : 'password'}
104
- required
105
- InputProps={{
106
- endAdornment: (
107
- <InputAdornment position="end">
108
- <IconButton
109
- size="small"
110
- onClick={() =>
111
- setShowPassword((prev) => ({
112
- ...prev,
113
- [item.name]: !prev[item.name],
114
- }))
115
- }
116
- edge="end"
117
- >
118
- {showPassword[item.name] ? (
119
- <VisibilityOff />
120
- ) : (
121
- <Visibility />
122
- )}
123
- </IconButton>
124
- </InputAdornment>
125
- ),
126
- }}
127
- />
128
- </>
129
- )
130
- })}
61
+ <form onSubmit={handleSubmit(onSubmit)}>
62
+ <Stack gap={2} direction="column">
63
+ {fields.map((item) => {
64
+ return (
65
+ <>
66
+ <FormTextField
67
+ label={item.label}
68
+ control={control}
69
+ name={item.name}
70
+ type={showPassword[item.name] ? 'text' : 'password'}
71
+ required
72
+ InputProps={{
73
+ endAdornment: (
74
+ <InputAdornment position="end">
75
+ <IconButton
76
+ size="small"
77
+ onClick={() =>
78
+ setShowPassword((prev) => ({
79
+ ...prev,
80
+ [item.name]: !prev[item.name],
81
+ }))
82
+ }
83
+ edge="end"
84
+ >
85
+ {showPassword[item.name] ? (
86
+ <VisibilityOff />
87
+ ) : (
88
+ <Visibility />
89
+ )}
90
+ </IconButton>
91
+ </InputAdornment>
92
+ ),
93
+ }}
94
+ />
95
+ </>
96
+ )
97
+ })}
131
98
 
132
- <Stack direction={'row'} gap={2} sx={{ marginTop: '20px' }}>
133
- <Button variant="outlined" onClick={handleClose}>
134
- Cancel
135
- </Button>
136
- <Button
137
- type="submit"
138
- endIcon={
139
- isLoading && (
140
- <CircularProgress
141
- style={{ color: 'white' }}
142
- size="30px"
143
- thickness={1.7}
144
- />
145
- )
146
- }
147
- >
148
- Submit
149
- </Button>
150
- </Stack>
99
+ <Stack direction={'row'} gap={2} sx={{ marginTop: '20px' }}>
100
+ <Button variant="outlined" onClick={close}>
101
+ Cancel
102
+ </Button>
103
+ <Button
104
+ type="submit"
105
+ endIcon={
106
+ isLoading && (
107
+ <CircularProgress
108
+ style={{ color: 'white' }}
109
+ size="30px"
110
+ thickness={1.7}
111
+ />
112
+ )
113
+ }
114
+ >
115
+ Submit
116
+ </Button>
151
117
  </Stack>
152
- </form>
153
- </Dialog>
118
+ </Stack>
119
+ </form>
154
120
  )
155
121
  }
156
122
 
157
- const StyledDialogTitle = styled(DialogTitle)({
158
- display: 'flex',
159
- alignItems: 'center',
160
- justifyContent: 'space-between',
161
- padding: '10px',
162
- marginBottom: '20px',
163
- })
164
123
  export default ChangePassword
@@ -0,0 +1,170 @@
1
+ import { KeyboardArrowDown, MoreVert } from '@mui/icons-material'
2
+ import {
3
+ ButtonProps,
4
+ CircularProgress,
5
+ IconButtonProps,
6
+ ListItemIcon,
7
+ ListItemText,
8
+ Menu,
9
+ MenuItem,
10
+ MenuListProps,
11
+ MenuProps,
12
+ } from '@mui/material'
13
+ import { ReactNode, useState } from 'react'
14
+ import {
15
+ StyledDropDownButton,
16
+ StyledIconButton,
17
+ StyledMenuItem,
18
+ } from './styles'
19
+
20
+ type MenuItem =
21
+ | {
22
+ label: string | ReactNode
23
+ icon?: ReactNode
24
+ onClick: (props?: any) => any
25
+ }
26
+ | { customButton?: ReactNode }
27
+
28
+ interface DropDownButtonProps {
29
+ icon?: {
30
+ icon: ReactNode
31
+ iconProps?: IconButtonProps
32
+ outlined?: boolean
33
+ }
34
+ button?: {
35
+ label?: string
36
+ buttonProps?: ButtonProps
37
+ }
38
+ anchor?: (props: { open: () => void }) => ReactNode
39
+ loading?: boolean
40
+ menu: MenuItem[]
41
+ menuProps?: Omit<MenuProps, 'open'>
42
+ menuListProps?: MenuListProps
43
+ }
44
+ const defaultIcon = {
45
+ icon: <MoreVert color="primary" />,
46
+ outlined: true,
47
+ }
48
+
49
+ const RenderAnchor = ({ button, icon, handleClick, loading, anchor }) => {
50
+ if (anchor) return <>{anchor({ open: handleClick })}</>
51
+
52
+ if (button)
53
+ return (
54
+ <StyledDropDownButton
55
+ onClick={handleClick}
56
+ disabled={loading}
57
+ endIcon={
58
+ loading ? (
59
+ <CircularProgress size="20px" thickness={1.7} />
60
+ ) : (
61
+ <KeyboardArrowDown />
62
+ )
63
+ }
64
+ {...button?.buttonProps}
65
+ >
66
+ {button?.label}
67
+ </StyledDropDownButton>
68
+ )
69
+ if (!button) {
70
+ return (
71
+ <StyledIconButton
72
+ outlined={icon?.outlined ?? false}
73
+ onClick={handleClick}
74
+ {...icon.iconProps}
75
+ >
76
+ {icon.icon}
77
+ </StyledIconButton>
78
+ )
79
+ }
80
+ }
81
+
82
+ const DropDownButton = ({
83
+ button,
84
+ icon = defaultIcon,
85
+ menu = [],
86
+ menuProps,
87
+ menuListProps,
88
+ loading = false,
89
+ anchor,
90
+ }: DropDownButtonProps) => {
91
+ const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)
92
+ const open = Boolean(anchorEl)
93
+
94
+ const handleClick = (event: any) => {
95
+ setAnchorEl(event.currentTarget)
96
+ }
97
+
98
+ const handleClose = () => {
99
+ setAnchorEl(null)
100
+ }
101
+
102
+ return (
103
+ <>
104
+ <RenderAnchor
105
+ anchor={anchor}
106
+ loading={loading}
107
+ button={button}
108
+ icon={icon}
109
+ handleClick={handleClick}
110
+ />
111
+ <Menu
112
+ elevation={2}
113
+ id="basic-menu"
114
+ anchorEl={anchorEl}
115
+ open={open}
116
+ onClose={handleClose}
117
+ MenuListProps={{ sx: { padding: 0 }, ...menuListProps }}
118
+ anchorOrigin={{
119
+ vertical: 'bottom',
120
+ horizontal: 'right',
121
+ }}
122
+ transformOrigin={{
123
+ vertical: 'top',
124
+ horizontal: 'right',
125
+ }}
126
+ {...menuProps}
127
+ >
128
+ <RenderMenuItems menu={menu} handleClose={handleClose} />
129
+ </Menu>
130
+ </>
131
+ )
132
+ }
133
+
134
+ DropDownButton.MenuItem = ({ icon, label, ...props }) => {
135
+ return (
136
+ <StyledMenuItem
137
+ sx={{ minWidth: '120px', width: '100%', ...props?.sx }}
138
+ {...props}
139
+ >
140
+ {icon && <ListItemIcon>{icon}</ListItemIcon>}
141
+ <ListItemText>{label}</ListItemText>
142
+ </StyledMenuItem>
143
+ )
144
+ }
145
+
146
+ export default DropDownButton
147
+
148
+ const RenderMenuItems = ({ menu, handleClose }) => {
149
+ return (
150
+ <>
151
+ {menu.map((item, index) => (
152
+ <>
153
+ {item?.customButton ? (
154
+ item.customButton
155
+ ) : (
156
+ <DropDownButton.MenuItem
157
+ icon={item?.icon}
158
+ label={item?.label}
159
+ key={index}
160
+ onClick={() => {
161
+ handleClose()
162
+ item.onClick()
163
+ }}
164
+ />
165
+ )}
166
+ </>
167
+ ))}
168
+ </>
169
+ )
170
+ }
@@ -0,0 +1 @@
1
+ export { default } from './DropDownButton'
@@ -0,0 +1,29 @@
1
+ import { Button, IconButton, MenuItem, styled } from '@mui/material'
2
+
3
+ export const StyledIconButton = styled(IconButton, {
4
+ shouldForwardProp: (prop) => prop !== 'outlined',
5
+ })<{ outlined?: boolean }>(({ theme, outlined }) => ({
6
+ ...(outlined && {
7
+ border: `1px solid ${theme.palette.primary.main}`,
8
+ borderRadius: '5px',
9
+ }),
10
+ }))
11
+
12
+ export const StyledMenuItem = styled(MenuItem)(({}) => ({
13
+ display: 'flex',
14
+ alignItems: 'center',
15
+ '& .MuiListItemIcon-root': {
16
+ minWidth: '24px',
17
+ },
18
+ '& .MuiSvgIcon-root': {
19
+ height: '18px',
20
+ width: '18px',
21
+ },
22
+ '& .MuiTypography-root': {
23
+ fontWeight: 600,
24
+ },
25
+ }))
26
+
27
+ export const StyledDropDownButton = styled(Button)(({}) => ({
28
+ padding: '0 14px',
29
+ }))
@@ -1,6 +1,5 @@
1
- import { Box, styled, Typography } from '@mui/material'
1
+ import { Box, Typography } from '@mui/material'
2
2
  import { ReactNode } from 'react'
3
- import { Link } from 'react-router-dom'
4
3
  import { isDevelopment } from '../../../constants/isDevelopment'
5
4
  import { applications } from './applications'
6
5
  import AppsMenu from './AppsMenu'
@@ -15,26 +14,15 @@ import {
15
14
  } from './assets'
16
15
 
17
16
  import CogWheelMenu from './CogWheelMenu'
18
- import HelpWidget from './HelpWidget/HelpWidget'
19
- import { StyledHeader, StyledImageWrapper } from './styles'
17
+ import HelpWidgetButton from './HelpWidget/HelpWidget'
18
+ import {
19
+ StyledHeader,
20
+ StyledImageWrapper,
21
+ StyledLogosWrapper,
22
+ StyledRouterLink,
23
+ } from './styles'
20
24
  import UserBox from './UserBox'
21
25
 
22
- const StyledLogosWrapper = styled(Box)(() => ({
23
- display: 'flex',
24
- alignItems: 'center',
25
- gap: '10px',
26
- padding: '10px',
27
- transition: 'background ease 0.3s',
28
- borderRadius: '5px',
29
- '&:hover': {
30
- background: 'rgba(0, 0, 0, 0.05)',
31
- },
32
- }))
33
-
34
- const StyledLink = styled(Link)(() => ({
35
- textDecoration: 'none',
36
- }))
37
-
38
26
  const imageMap = {
39
27
  ums: collegex,
40
28
  enroll: enrollx,
@@ -48,9 +36,7 @@ const imageMap = {
48
36
 
49
37
  interface AppHeaderProps {
50
38
  clientLogo: string
51
- username: string
52
- profileIcon: string
53
- permissions?: any
39
+ fullName: string
54
40
  userBoxActions: {
55
41
  label: ReactNode
56
42
  icon?: ReactNode
@@ -61,9 +47,7 @@ interface AppHeaderProps {
61
47
 
62
48
  export default function AppHeader({
63
49
  clientLogo = imageMap.campx,
64
- username,
65
- profileIcon,
66
- permissions,
50
+ fullName,
67
51
  userBoxActions = [],
68
52
  cogWheelMenu = [],
69
53
  }: AppHeaderProps) {
@@ -74,14 +58,9 @@ export default function AppHeader({
74
58
  <AppLogo clientLogo={clientLogo} />
75
59
  </Box>
76
60
  <Box className="actions">
77
- <HelpWidget />
78
- {/* <Notification /> */}
61
+ <HelpWidgetButton />
79
62
  {cogWheelMenu?.length ? <CogWheelMenu menu={cogWheelMenu} /> : null}
80
- <UserBox
81
- username={username}
82
- profileIcon={profileIcon}
83
- actions={userBoxActions}
84
- />
63
+ <UserBox fullName={fullName} actions={userBoxActions} />
85
64
  </Box>
86
65
  </StyledHeader>
87
66
  )
@@ -93,7 +72,7 @@ const AppLogo = ({ clientLogo }) => {
93
72
  applications.find((item) => item.key === originSubdomain)?.key ?? 'campx'
94
73
 
95
74
  return (
96
- <StyledLink to={'/'}>
75
+ <StyledRouterLink to={'/'}>
97
76
  <StyledLogosWrapper>
98
77
  <StyledImageWrapper>
99
78
  <img src={imageMap[currentApp]} />
@@ -118,6 +97,6 @@ const AppLogo = ({ clientLogo }) => {
118
97
  )}
119
98
  </StyledImageWrapper>
120
99
  </StyledLogosWrapper>
121
- </StyledLink>
100
+ </StyledRouterLink>
122
101
  )
123
102
  }
@@ -1,18 +1,18 @@
1
1
  import { SettingsOutlined } from '@mui/icons-material'
2
2
  import { IconButton } from '@mui/material'
3
3
  import { useHistory } from '../../../hooks/useRouter'
4
- import MenuButton from '../../MenuButton'
4
+ import DropDownButton from '../../DropDownButton/DropDownButton'
5
5
 
6
6
  const CogWheelMenu = ({ menu }) => {
7
7
  const history = useHistory()
8
8
 
9
9
  return (
10
- <MenuButton
11
- anchor={
12
- <IconButton color="secondary">
10
+ <DropDownButton
11
+ anchor={({ open }) => (
12
+ <IconButton color="secondary" onClick={open}>
13
13
  <SettingsOutlined />
14
14
  </IconButton>
15
- }
15
+ )}
16
16
  menu={menu?.map((item) => ({
17
17
  label: item?.label,
18
18
  onClick: () => {
@@ -23,7 +23,7 @@ const CogWheelMenu = ({ menu }) => {
23
23
  PaperProps: { sx: { top: '64px !important' } },
24
24
  transformOrigin: {
25
25
  horizontal: 'center',
26
- vertical: 'bottom',
26
+ vertical: 'top',
27
27
  },
28
28
  }}
29
29
  />