@campxdev/shared 0.3.15 → 0.3.16

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,146 @@
1
+ import {
2
+ Button,
3
+ CircularProgress,
4
+ Dialog,
5
+ DialogTitle,
6
+ IconButton,
7
+ InputAdornment,
8
+ Stack,
9
+ styled,
10
+ Typography,
11
+ } from "@mui/material";
12
+ import CloseIcon from "@mui/icons-material/Close";
13
+ import { Visibility, VisibilityOff } from "@mui/icons-material";
14
+ import React, { useState } from "react";
15
+ import { useForm } from "react-hook-form";
16
+ import { useModal } from "./DrawerWrapper/DrawerWrapper";
17
+ import { FormTextField } from ".";
18
+ import axios, { axiosErrorToast } from "../config/axios";
19
+ import { toast } from "react-toastify";
20
+
21
+ export interface DialogProps {
22
+ open: boolean;
23
+ onClose: any;
24
+ }
25
+
26
+ function ChangePassword(props: DialogProps) {
27
+ const { onClose, open } = props;
28
+ const handleClose = () => {
29
+ onClose();
30
+ };
31
+ const modal = useModal();
32
+
33
+ const [showPassword, setShowPassword] = useState({
34
+ oldPassword: false,
35
+ newPassword: false,
36
+ confirmPassword: false,
37
+ });
38
+ const [isLoading, setIsLoading] = useState(false);
39
+ const { handleSubmit, control } = useForm();
40
+ const onSubmit = async (formData) => {
41
+ setIsLoading(true);
42
+ try {
43
+ await axios.post("/auth/change-password", formData);
44
+ toast.success("Password Changed Successfully");
45
+ setIsLoading(false);
46
+ handleClose();
47
+ } catch (error) {
48
+ axiosErrorToast(error);
49
+ handleClose();
50
+ }
51
+ };
52
+
53
+ const fields = [
54
+ { label: "Old Password", name: "oldPassword" },
55
+ { label: "New Password", name: "newPassword" },
56
+ { label: "Confirm Password", name: "confirmPassword" },
57
+ ];
58
+
59
+ return (
60
+ <Dialog
61
+ open={open}
62
+ PaperProps={{
63
+ sx: {
64
+ borderRadius: "20px",
65
+ width: "500px",
66
+ padding: "20px",
67
+ },
68
+ }}
69
+ >
70
+ <StyledDialogTitle>
71
+ <Typography variant="h3">Change Password</Typography>
72
+ <IconButton onClick={handleClose}>
73
+ <CloseIcon />
74
+ </IconButton>
75
+ </StyledDialogTitle>
76
+ <form onSubmit={handleSubmit(onSubmit)}>
77
+ <Stack gap={2} direction="column">
78
+ {fields.map((item) => {
79
+ return (
80
+ <>
81
+ <FormTextField
82
+ label={item.label}
83
+ control={control}
84
+ name={item.name}
85
+ type={showPassword[item.name] ? "text" : "password"}
86
+ required
87
+ InputProps={{
88
+ endAdornment: (
89
+ <InputAdornment position="end">
90
+ <IconButton
91
+ size="small"
92
+ onClick={() =>
93
+ setShowPassword((prev) => ({
94
+ ...prev,
95
+ [item.name]: !prev[item.name],
96
+ }))
97
+ }
98
+ edge="end"
99
+ >
100
+ {showPassword[item.name] ? (
101
+ <VisibilityOff />
102
+ ) : (
103
+ <Visibility />
104
+ )}
105
+ </IconButton>
106
+ </InputAdornment>
107
+ ),
108
+ }}
109
+ />
110
+ </>
111
+ );
112
+ })}
113
+
114
+ <Stack direction={"row"} gap={2} sx={{ marginTop: "20px" }}>
115
+ <Button variant="outlined" onClick={handleClose}>
116
+ Cancel
117
+ </Button>
118
+ <Button
119
+ type="submit"
120
+ endIcon={
121
+ isLoading && (
122
+ <CircularProgress
123
+ style={{ color: "white" }}
124
+ size="30px"
125
+ thickness={1.7}
126
+ />
127
+ )
128
+ }
129
+ >
130
+ Submit
131
+ </Button>
132
+ </Stack>
133
+ </Stack>
134
+ </form>
135
+ </Dialog>
136
+ );
137
+ }
138
+
139
+ const StyledDialogTitle = styled(DialogTitle)({
140
+ display: "flex",
141
+ alignItems: "center",
142
+ justifyContent: "space-between",
143
+ padding: "10px",
144
+ marginBottom: "20px",
145
+ });
146
+ export default ChangePassword;
@@ -1,180 +1,229 @@
1
- import {Alert, Box, Button, styled, Typography} from '@mui/material'
1
+ import { Alert, Box, Button, styled, Typography } from "@mui/material";
2
+ import { useEffect, useState } from "react";
2
3
  import {
3
- internalserver,
4
- nointernet,
5
- pagenotfound,
6
- permissiondenied,
7
- unauth,
8
- } from '../../assets/images'
9
-
10
- const StyledAlert = styled(Alert)(({theme}) => ({
11
- border: `1px solid ${theme.palette.error.main}`,
12
- display: 'flex',
13
- alignItems: 'center',
14
- '& .MuiAlert-message': {
15
- padding: 0,
16
- },
17
- '& .MuiTypography-root': {
18
- margin: 0,
19
- },
20
- position: 'relative',
21
- '& .retryBtn': {
22
- color: '#661b2a',
23
- position: 'absolute',
24
- right: 8,
25
- top: 8,
26
- },
27
- }))
28
-
29
- const StyledBox = styled(Box)(({theme}) => ({
30
- width: '100%',
31
- display: 'flex',
32
- flexDirection: 'column',
33
- alignItems: 'center',
34
- justifyContent: 'center',
35
- }))
36
-
37
- export default function ErrorFallback({error, resetErrorBoundary}) {
38
- if (error?.response?.status) {
39
- switch (error?.response?.status) {
40
- case 401:
41
- return <UnAuth resetBoundary={resetErrorBoundary} />
42
-
43
- case 500:
44
- return <InternalServer resetBoundary={resetErrorBoundary} />
45
-
46
- case 403:
47
- return <PemissionDenied resetBoundary={resetErrorBoundary} />
48
-
49
- default:
50
- return <InternalServer resetBoundary={resetErrorBoundary} />
51
- }
52
- }
53
-
54
- if (error?.message === 'Network Error') {
55
- return <NoInternet resetBoundary={resetErrorBoundary} />
56
- }
57
-
58
- return (
59
- <Box sx={{marginTop: '16px', padding: '16px'}}>
60
- <StyledAlert severity='error'>
61
- {error?.response?.data?.message ?? error?.message}
62
- <Button
63
- className='retryBtn'
64
- onClick={() => resetErrorBoundary()}
65
- size='small'
66
- color='error'
67
- variant='outlined'
68
- >
69
- Try Again
70
- </Button>
71
- </StyledAlert>
72
- </Box>
73
- )
4
+ nointernet,
5
+ pagenotfound,
6
+ permissiondenied,
7
+ unauth,
8
+ internalserver,
9
+ } from "../../assets/images";
10
+ import Cookies from "js-cookie";
11
+ import LoginForm from "../LoginForm";
12
+ import { useModal } from "../DrawerWrapper/DrawerWrapper";
13
+ import { PermissionsStore } from "../../permissions";
14
+ import axios from "../../config/axios";
15
+
16
+ const StyledAlert = styled(Alert)(({ theme }) => ({
17
+ border: `1px solid ${theme.palette.error.main}`,
18
+ display: "flex",
19
+ alignItems: "center",
20
+ "& .MuiAlert-message": {
21
+ padding: 0,
22
+ },
23
+ "& .MuiTypography-root": {
24
+ margin: 0,
25
+ },
26
+ position: "relative",
27
+ "& .retryBtn": {
28
+ color: "#661b2a",
29
+ position: "absolute",
30
+ right: 8,
31
+ top: 8,
32
+ },
33
+ }));
34
+
35
+ const StyledBox = styled(Box)(({ theme }) => ({
36
+ width: "100%",
37
+ display: "flex",
38
+ flexDirection: "column",
39
+ alignItems: "center",
40
+ justifyContent: "center",
41
+ }));
42
+
43
+ export default function ErrorFallback({ error, resetErrorBoundary }) {
44
+ if (error?.response?.status) {
45
+ switch (error?.response?.status) {
46
+ case 401:
47
+ return <UnAuth resetBoundary={resetErrorBoundary} />;
48
+
49
+ case 500:
50
+ return <InternalServer resetBoundary={resetErrorBoundary} />;
51
+
52
+ case 403:
53
+ return <PemissionDenied resetBoundary={resetErrorBoundary} />;
54
+
55
+ default:
56
+ return <InternalServer resetBoundary={resetErrorBoundary} />;
57
+ }
58
+ }
59
+
60
+ if (error?.message === "Network Error") {
61
+ return <NoInternet resetBoundary={resetErrorBoundary} />;
62
+ }
63
+
64
+ return (
65
+ <Box sx={{ marginTop: "16px", padding: "16px" }}>
66
+ <StyledAlert severity="error">
67
+ {error?.response?.data?.message ?? error?.message}
68
+ <Button
69
+ className="retryBtn"
70
+ onClick={() => resetErrorBoundary()}
71
+ size="small"
72
+ color="error"
73
+ variant="outlined"
74
+ >
75
+ Try Again
76
+ </Button>
77
+ </StyledAlert>
78
+ </Box>
79
+ );
74
80
  }
75
81
 
76
- export function PageNotFound({resetBoundary}) {
77
- return (
78
- <>
79
- <StyledBox>
80
- <img
81
- src={pagenotfound}
82
- alt='page not found'
83
- width={470}
84
- style={{marginTop: '20px'}}
85
- />
86
- <Typography variant='h1'>Page Not Found.</Typography>
87
- <Button sx={{marginTop: '20px'}} onClick={() => resetBoundary()}>
88
- Try Again
89
- </Button>
90
- </StyledBox>
91
- </>
92
- )
82
+ export function PageNotFound({ resetBoundary }) {
83
+ return (
84
+ <>
85
+ <StyledBox>
86
+ <img
87
+ src={pagenotfound}
88
+ alt="page not found"
89
+ width={470}
90
+ style={{ marginTop: "20px" }}
91
+ />
92
+ <Typography variant="h1">Page Not Found.</Typography>
93
+ <Button sx={{ marginTop: "20px" }} onClick={() => resetBoundary()}>
94
+ Try Again
95
+ </Button>
96
+ </StyledBox>
97
+ </>
98
+ );
93
99
  }
94
100
 
95
- export function NoInternet({resetBoundary}) {
96
- return (
97
- <>
98
- <StyledBox>
99
- <img src={nointernet} alt='No Internet Found' width={470} />
100
- <Typography variant='h1'>No Internet Found.</Typography>
101
- <Button sx={{marginTop: '20px'}} onClick={() => resetBoundary()}>
102
- Try Again
103
- </Button>
104
- </StyledBox>
105
- </>
106
- )
101
+ export function NoInternet({ resetBoundary }) {
102
+ return (
103
+ <>
104
+ <StyledBox>
105
+ <img src={nointernet} alt="No Internet Found" width={470} />
106
+ <Typography variant="h1">No Internet Found.</Typography>
107
+ <Button sx={{ marginTop: "20px" }} onClick={() => resetBoundary()}>
108
+ Try Again
109
+ </Button>
110
+ </StyledBox>
111
+ </>
112
+ );
107
113
  }
108
114
 
109
- export function PemissionDenied({resetBoundary}) {
110
- return (
111
- <>
112
- <StyledBox>
113
- <img src={permissiondenied} alt='permission denied' width={470} />
114
- <Typography variant='h1'>Permission Denied.</Typography>
115
- <Button sx={{marginTop: '20px'}} onClick={() => resetBoundary()}>
116
- Try Again
117
- </Button>
118
- </StyledBox>
119
- </>
120
- )
115
+ export function PemissionDenied({ resetBoundary }) {
116
+ return (
117
+ <>
118
+ <StyledBox>
119
+ <img src={permissiondenied} alt="permission denied" width={470} />
120
+ <Typography variant="h1">Permission Denied.</Typography>
121
+ <Button sx={{ marginTop: "20px" }} onClick={() => resetBoundary()}>
122
+ Try Again
123
+ </Button>
124
+ </StyledBox>
125
+ </>
126
+ );
121
127
  }
122
128
 
123
- export function InternalServer({resetBoundary}) {
124
- return (
125
- <>
126
- <StyledBox>
127
- <img src={internalserver} alt='internal server error' width={470} />
128
- <Typography variant='h1' marginTop={'20px'}>
129
- Internal Server Error.
130
- </Typography>
131
- <Button
132
- size='small'
133
- variant='outlined'
134
- sx={{marginTop: '20px'}}
135
- onClick={() => resetBoundary()}
136
- >
137
- Try Again
138
- </Button>
139
- </StyledBox>
140
- </>
141
- )
129
+ export function InternalServer({ resetBoundary }) {
130
+ return (
131
+ <>
132
+ <StyledBox>
133
+ <img src={internalserver} alt="internal server error" width={470} />
134
+ <Typography variant="h1" marginTop={"20px"}>
135
+ Internal Server Error.
136
+ </Typography>
137
+ <Button
138
+ size="small"
139
+ variant="outlined"
140
+ sx={{ marginTop: "20px" }}
141
+ onClick={() => resetBoundary()}
142
+ >
143
+ Try Again
144
+ </Button>
145
+ </StyledBox>
146
+ </>
147
+ );
142
148
  }
143
149
 
144
- export function UnAuth({resetBoundary}) {
145
- const url = window.location.origin
146
- return (
147
- <>
148
- <StyledBox>
149
- <img src={unauth} alt='unauthorized' width={470} />
150
- <Typography variant='h1' marginTop={'20px'}>
151
- UnAuthorized.
152
- </Typography>
153
- <Box
154
- sx={{
155
- display: 'flex',
156
- marginTop: '20px',
157
- }}
158
- >
159
- <Button
160
- variant='outlined'
161
- sx={{marginRight: '10px'}}
162
- onClick={() => resetBoundary()}
163
- >
164
- Try Again
165
- </Button>
166
-
167
- <Button
168
- onClick={() =>
169
- window.location.replace(
170
- `https://www.id.campx.in/?redirect_to=${url}`
171
- )
172
- }
173
- >
174
- Click here to Login
175
- </Button>
176
- </Box>
177
- </StyledBox>
178
- </>
179
- )
150
+ export function UnAuth({ resetBoundary }) {
151
+ const modal = useModal();
152
+ const [username, setUsername] = useState("");
153
+ const [loading, setLoading] = useState(false);
154
+
155
+ const url = window.location.origin;
156
+ const origin = window?.location?.origin?.split(".");
157
+ const isLocalHost =
158
+ process.env.NODE_ENV === "development" ||
159
+ origin?.slice(-2).join(".") === "campx.dev";
160
+ const sessionCookie = Cookies.get("campx_session_key");
161
+ const appinit = async () => {
162
+ setLoading(true);
163
+ await axios
164
+ .get("/auth/my-permissions")
165
+ .then((res) => {
166
+ setUsername(res.data.user.fullName);
167
+ PermissionsStore.update((s) => {
168
+ s.permissions = {
169
+ ...res.data?.permissions,
170
+ can_settings_view: 1,
171
+ can_dashboard_view: 1,
172
+ can_individual_pages_view: 1,
173
+ } as any;
174
+ });
175
+ setLoading(false);
176
+ })
177
+ .catch((e) => {
178
+ modal({
179
+ title: "Login",
180
+ content: () => <LoginForm />,
181
+ });
182
+ });
183
+ };
184
+ function LoginPage() {
185
+ if (isLocalHost) {
186
+ if (!sessionCookie) {
187
+ modal({
188
+ title: "Login",
189
+ content: () => <LoginForm />,
190
+ });
191
+ } else {
192
+ appinit();
193
+ }
194
+ } else {
195
+ if (!sessionCookie) {
196
+ window.location.replace(`https://www.id.campx.in/?redirect_to=${url}`);
197
+ } else {
198
+ appinit();
199
+ }
200
+ }
201
+ }
202
+
203
+ return (
204
+ <>
205
+ <StyledBox>
206
+ <img src={unauth} alt="unauthorized" width={470} />
207
+ <Typography variant="h1" marginTop={"20px"}>
208
+ UnAuthorized.
209
+ </Typography>
210
+ <Box
211
+ sx={{
212
+ display: "flex",
213
+ marginTop: "20px",
214
+ }}
215
+ >
216
+ <Button
217
+ variant="outlined"
218
+ sx={{ marginRight: "10px" }}
219
+ onClick={() => resetBoundary()}
220
+ >
221
+ Try Again
222
+ </Button>
223
+
224
+ <Button onClick={() => LoginPage()}>Click here to Login</Button>
225
+ </Box>
226
+ </StyledBox>
227
+ </>
228
+ );
180
229
  }