Skip to content

Commit 7c59e90

Browse files
authored
Merge pull request #19 from omthakare16/main
added UserButton Component + token in headers if not null
2 parents e0be2dc + a106b57 commit 7c59e90

File tree

7 files changed

+232
-11
lines changed

7 files changed

+232
-11
lines changed

.eslintrc.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@ module.exports = {
1818
sourceType: 'module',
1919
},
2020
plugins: ['react'],
21-
rules: {},
21+
rules: {
22+
'max-len': 'off',
23+
'require-jsdoc': 'off',
24+
},
2225
};

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
"devDependencies": {
2424
"@babel/preset-env": "^7.22.4",
2525
"@babel/preset-react": "^7.22.3",
26+
"@emotion/react": "^11.11.1",
27+
"@emotion/styled": "^11.11.0",
2628
"@microsoft/eslint-formatter-sarif": "^3.0.0",
29+
"@mui/material": "^5.13.5",
2730
"@rollup/plugin-commonjs": "^25.0.0",
2831
"@rollup/plugin-node-resolve": "^15.1.0",
2932
"eslint": "^8.41.0",

src/api/api.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,18 @@ const commonAPICall = async (
2222
'Content-Type': 'application/json',
2323
},
2424
) => {
25+
const token = tokenLocalStorage();
2526
const FULLPATH = BASE_URL + PATH;
27+
if (token) {
28+
headers = {
29+
...headers,
30+
Authorization: `Bearer ${token}`,
31+
};
32+
}
2633
const response = await fetch(FULLPATH, {
2734
method: METHOD,
2835
body: BODY,
29-
headers: {
30-
...headers,
31-
Authorization: `Bearer ${tokenLocalStorage()}`,
32-
},
36+
headers: headers,
3337
});
3438

3539
return response;
+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import React, {useState, useRef, useEffect} from 'react';
2+
import {useUser} from '../../hooks/useUser/useUser.jsx';
3+
import {useEasyauth} from '../../hooks/useEasyauth/useEasyauth.jsx';
4+
import PropTypes from 'prop-types';
5+
import {iconUser} from '../uiComponents/iconUser.js';
6+
import {Box, Modal} from '@mui/material';
7+
import {UserProfile} from '../UserProfile/UserProfile.jsx';
8+
9+
10+
export const UserButton = ({position, profileRedirect}) => {
11+
const auth = useEasyauth();
12+
const {user} = useUser();
13+
const [isOpen, setIsOpen] = useState(false);
14+
const cardRef = useRef(null);
15+
const [open, setOpen] = useState(false);
16+
17+
18+
const ProfileModal = () => {
19+
const handleClose = () => {
20+
setOpen(false);
21+
};
22+
return (
23+
<>
24+
<Modal open={open} onClose={handleClose}>
25+
<Box>
26+
<div
27+
style={{
28+
display: 'flex',
29+
justifyContent: 'center',
30+
}}
31+
>
32+
<UserProfile />
33+
</div>
34+
</Box>
35+
</Modal>
36+
</>
37+
);
38+
};
39+
40+
const handleButtonClick = () => {
41+
setIsOpen(!isOpen);
42+
};
43+
44+
const handleLogout = () => {
45+
auth.removeUser();
46+
};
47+
48+
const handleAccount = () => {
49+
setIsOpen(false);
50+
if (!profileRedirect) {
51+
setOpen(true);
52+
}
53+
};
54+
55+
const cardStyle = {
56+
position: 'absolute',
57+
top: '50px',
58+
borderRadius: '8px',
59+
backgroundColor: '#fff',
60+
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)',
61+
padding: '10px',
62+
display: 'flex',
63+
flexDirection: 'column',
64+
};
65+
useEffect(() => {
66+
function handleClickOutside(event) {
67+
if (cardRef.current && !cardRef.current.contains(event.target)) {
68+
setIsOpen(false);
69+
}
70+
}
71+
72+
document.addEventListener('mousedown', handleClickOutside);
73+
return () => {
74+
document.removeEventListener('mousedown', handleClickOutside);
75+
};
76+
}, []);
77+
if (position === 'left') {
78+
cardStyle.left = '0';
79+
} else if (position === 'right') {
80+
cardStyle.right = '0';
81+
} else {
82+
cardStyle.right = '0';
83+
}
84+
85+
return (
86+
<>
87+
<div style={{position: 'relative', display: 'inline-block'}}>
88+
<button
89+
style={{
90+
width: '40px',
91+
height: '40px',
92+
borderRadius: '50%',
93+
padding: '0',
94+
border: 'none',
95+
backgroundColor: '#ccc',
96+
}}
97+
onClick={handleButtonClick}
98+
>
99+
<img
100+
src={iconUser()}
101+
alt="profile icon"
102+
style={{width: '100%', height: '100%'}}
103+
/>
104+
</button>
105+
106+
<ProfileModal/>
107+
{isOpen && (
108+
<div ref={cardRef} style={cardStyle}>
109+
<div
110+
style={{
111+
display: 'flex',
112+
alignItems: 'center',
113+
marginBottom: '10px',
114+
overflow: 'hidden',
115+
textOverflow: 'ellipsis',
116+
}}
117+
>
118+
<img
119+
src={iconUser()}
120+
alt="Profile Icon"
121+
style={{width: '30px', height: '30px', marginRight: '10px'}}
122+
/>
123+
<div
124+
style={{
125+
color: 'black',
126+
fontSize: '16px',
127+
overflow: 'hidden',
128+
textOverflow: 'ellipsis',
129+
}}
130+
>
131+
{user.email}
132+
</div>
133+
</div>
134+
<button
135+
style={{
136+
backgroundColor: '#007bff',
137+
color: '#fff',
138+
padding: '5px 10px',
139+
marginBottom: '10px',
140+
border: 'none',
141+
borderRadius: '3px',
142+
cursor: 'pointer',
143+
}}
144+
onClick={handleLogout}
145+
>
146+
Logout
147+
</button>
148+
<a
149+
href={profileRedirect}
150+
style={{
151+
backgroundColor: '#17a2b8',
152+
}}
153+
>
154+
<button
155+
style={{
156+
backgroundColor: '#17a2b8',
157+
color: '#fff',
158+
padding: '5px 10px',
159+
border: 'none',
160+
borderRadius: '3px',
161+
cursor: 'pointer',
162+
}}
163+
onClick={handleAccount}
164+
>
165+
Account
166+
</button>
167+
</a>
168+
</div>
169+
)}
170+
</div>
171+
</>
172+
);
173+
};
174+
175+
176+
UserButton.propTypes = {
177+
position: PropTypes.string,
178+
profileRedirect: PropTypes.string,
179+
};

src/components/UserProfile/UserProfile.jsx

+34-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ import React, {useEffect, useState} from 'react';
22
import {useEasyauth} from '../../hooks/useEasyauth/useEasyauth.jsx';
33
import PropTypes from 'prop-types';
44
import {getProfile} from '../../api/api.js';
5+
import {
6+
Box,
7+
Chip,
8+
Divider,
9+
PopoverPaper,
10+
Typography,
11+
} from '@mui/material';
512

613
export const UserProfile = ({loader}) => {
714
const auth = useEasyauth();
@@ -19,12 +26,33 @@ export const UserProfile = ({loader}) => {
1926
return loader||'Lodaing...';
2027
} else {
2128
return (
22-
<ul>
23-
<li>Email: {profile.email}</li>
24-
<li>Email verified: {JSON.stringify(profile.emailVerified)}</li>
25-
<li>Phone: {profile.phone}</li>
26-
<li>Phone verified: {JSON.stringify(profile.phoneVerified)}</li>
27-
</ul>
29+
<PopoverPaper sx={{m: 2, p: 2, width: 300}}>
30+
<Box sx={{display: 'flex', alignItems: 'center', marginBottom: 2}}>
31+
<Typography variant="h6" sx={{flexGrow: 1}}>
32+
Profile
33+
</Typography>
34+
<Divider />
35+
</Box>
36+
<Typography variant="button">Email</Typography>
37+
<Divider />
38+
{profile.email}{' '}
39+
<Chip
40+
41+
size="small"
42+
color={profile.emailVerified ? 'success' : 'error'}
43+
label={profile.emailVerified ? 'Verified' : 'Not Verified'}
44+
/>
45+
<ul />
46+
<Typography variant="button">Phone </Typography>
47+
<Divider />
48+
{profile.phone}{' '}
49+
<Chip
50+
size="small"
51+
color={profile.phoneVerified ? 'success' : 'error'}
52+
label={profile.phoneVerified ? 'Verified' : 'Not Verified'}
53+
/>
54+
55+
</PopoverPaper>
2856
);
2957
}
3058
} else {

src/components/uiComponents/iconUser.js

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export * from './components/SignedInAndSignedOut/SignedIn.jsx';
55
export * from './components/SignedInAndSignedOut/SignedOut.jsx';
66
export * from './hooks/useUser/useUser.jsx';
77
export * from './hooks/useStripe/useStripe.jsx';
8+
export * from './components/UserButton/UserButton.jsx';

0 commit comments

Comments
 (0)