Showing
7 changed files
with
265 additions
and
11 deletions
1 | +import { useState, useEffect } from "react"; | ||
2 | +import { useNavigate } from "react-router-dom"; | ||
3 | +import authService from "../service/auth"; | ||
1 | // components | 4 | // components |
2 | -import Bottombar from "../components/Bottombar"; | ||
3 | import Topbar from "../components/Topbar"; | 5 | import Topbar from "../components/Topbar"; |
6 | +import Bottombar from "../components/Bottombar"; | ||
4 | 7 | ||
5 | function Settings() { | 8 | function Settings() { |
9 | + const navigate = useNavigate(); | ||
10 | + const [editSuccess, setEditSuccess] = useState(0); | ||
11 | + const [userinfo, setUserinfo] = useState({ | ||
12 | + username: "", | ||
13 | + country: "", | ||
14 | + city: "", | ||
15 | + email: "", | ||
16 | + }); | ||
17 | + | ||
18 | + // useEffect(() => { | ||
19 | + // navigate("/login", { replace: true }); | ||
20 | + // }, [ navigate]); | ||
21 | + | ||
22 | + const logout = () => { | ||
23 | + return; | ||
24 | + }; | ||
25 | + | ||
26 | + const onChange = (e) => { | ||
27 | + setUserinfo((orgState) => ({ | ||
28 | + ...orgState, | ||
29 | + [e.target.id]: e.target.value, | ||
30 | + })); | ||
31 | + }; | ||
32 | + | ||
33 | + const handleSubmit = async (e) => { | ||
34 | + e.preventDefault(); | ||
35 | + if (userinfo.country.length > 2) { | ||
36 | + alert("Please use alpha-2 country code"); | ||
37 | + return; | ||
38 | + } | ||
39 | + const response = await authService.handleUserEdit(userinfo); | ||
40 | + setEditSuccess(response); | ||
41 | + }; | ||
42 | + | ||
6 | return ( | 43 | return ( |
7 | - <> | 44 | + <div> |
8 | <Topbar /> | 45 | <Topbar /> |
46 | + <h3>Edit Your information</h3> | ||
47 | + <form className="authForm" onSubmit={(e) => handleSubmit(e)}> | ||
48 | + <label htmlFor="username"> | ||
49 | + <input | ||
50 | + placeholder="username" | ||
51 | + onChange={(e) => onChange(e)} | ||
52 | + value={userinfo.username} | ||
53 | + type="text" | ||
54 | + id="username" | ||
55 | + /> | ||
56 | + </label> | ||
57 | + <label htmlFor="country"> | ||
58 | + <input | ||
59 | + placeholder="Please use Alpha-2 Country Code" | ||
60 | + onChange={(e) => onChange(e)} | ||
61 | + value={userinfo.country.toUpperCase()} | ||
62 | + type="text" | ||
63 | + id="country" | ||
64 | + /> | ||
65 | + </label> | ||
66 | + <label htmlFor="city"> | ||
67 | + <input | ||
68 | + placeholder="City Name (lower case)" | ||
69 | + onChange={(e) => onChange(e)} | ||
70 | + value={userinfo.city.toLowerCase()} | ||
71 | + type="text" | ||
72 | + id="city" | ||
73 | + /> | ||
74 | + </label> | ||
75 | + <label htmlFor="email"> | ||
76 | + <input | ||
77 | + placeholder="Change email" | ||
78 | + onChange={(e) => onChange(e)} | ||
79 | + value={userinfo.email} | ||
80 | + type="email" | ||
81 | + id="email" | ||
82 | + /> | ||
83 | + </label> | ||
84 | + <label htmlFor="submit"> | ||
85 | + <input type="submit" id="submit" /> | ||
86 | + </label> | ||
87 | + </form> | ||
88 | + | ||
89 | + <br /> | ||
90 | + | ||
9 | <div> | 91 | <div> |
10 | - <h1>Settings page</h1> | 92 | + Want to logout? <button onClick={() => logout()}>Logout</button> |
11 | - <div>username</div> | ||
12 | - <div>email</div> | ||
13 | - <div>birthday</div> | ||
14 | - <br /> | ||
15 | - <button>notification</button> | ||
16 | </div> | 93 | </div> |
17 | <Bottombar /> | 94 | <Bottombar /> |
18 | - </> | 95 | + </div> |
19 | ); | 96 | ); |
20 | } | 97 | } |
21 | 98 | ... | ... |
1 | +// components | ||
2 | +import Topbar from "../components/Topbar"; | ||
3 | +import Bottombar from "../components/Bottombar"; | ||
4 | + | ||
1 | function Tweet() { | 5 | function Tweet() { |
2 | - return <div>Tweet</div>; | 6 | + return ( |
7 | + <div> | ||
8 | + <Topbar /> | ||
9 | + | ||
10 | + <div>tweet</div> | ||
11 | + | ||
12 | + <Bottombar /> | ||
13 | + </div> | ||
14 | + ); | ||
3 | } | 15 | } |
4 | 16 | ||
5 | export default Tweet; | 17 | export default Tweet; | ... | ... |
... | @@ -33,9 +33,38 @@ const handleLogin = async ({ email, password }) => { | ... | @@ -33,9 +33,38 @@ const handleLogin = async ({ email, password }) => { |
33 | } | 33 | } |
34 | }; | 34 | }; |
35 | 35 | ||
36 | +const handleUserEdit = async ({ username, country, city, email }) => { | ||
37 | + const token = JSON.parse(sessionStorage.getItem("user-token")).token; | ||
38 | + try { | ||
39 | + const response = await axios.put( | ||
40 | + "http://localhost:8080/api/users/edit", | ||
41 | + { | ||
42 | + username, | ||
43 | + country: country.toUpperCase(), | ||
44 | + city: city.toLowerCase(), | ||
45 | + email, | ||
46 | + }, | ||
47 | + { | ||
48 | + headers: { | ||
49 | + Authorization: `Bearer ${token}`, | ||
50 | + }, | ||
51 | + } | ||
52 | + ); | ||
53 | + | ||
54 | + if (response.status === 200) { | ||
55 | + return "success"; | ||
56 | + } else { | ||
57 | + return "fail"; | ||
58 | + } | ||
59 | + } catch (err) { | ||
60 | + console.log(err); | ||
61 | + } | ||
62 | +}; | ||
63 | + | ||
36 | const authService = { | 64 | const authService = { |
37 | handleSignup, | 65 | handleSignup, |
38 | handleLogin, | 66 | handleLogin, |
67 | + handleUserEdit, | ||
39 | }; | 68 | }; |
40 | 69 | ||
41 | export default authService; | 70 | export default authService; | ... | ... |
server/'
0 → 100644
1 | +const bcrypt = require("bcryptjs"); | ||
2 | +// handles "exception" inside of async express routes | ||
3 | +const asyncHandler = require("express-async-handler"); | ||
4 | +const User = require("../models/userModel"); | ||
5 | +const { jwtGenerator } = require("../config/jwt"); | ||
6 | + | ||
7 | +// @desc Signup new user | ||
8 | +// @route POST /api/users | ||
9 | +// @access Public | ||
10 | +const signupUser = asyncHandler(async (req, res) => { | ||
11 | + const { username, country, city, email, password } = req.body; | ||
12 | + if (!username || !country || !city || !email || !password) { | ||
13 | + res.status(400); | ||
14 | + throw new Error("Please fill in all fields"); | ||
15 | + } | ||
16 | + | ||
17 | + // Check if user already exists | ||
18 | + const userExists = await User.findOne({ email }); | ||
19 | + if (userExists) { | ||
20 | + res.status(400); | ||
21 | + throw new Error("User with the email already exists"); | ||
22 | + } | ||
23 | + | ||
24 | + // Hash password (bcrypt) | ||
25 | + const salt = await bcrypt.genSalt(10); | ||
26 | + const hashedPassword = await bcrypt.hash(password, salt); | ||
27 | + | ||
28 | + // Create/Build user | ||
29 | + const user = await User.create({ | ||
30 | + username, | ||
31 | + country, | ||
32 | + city, | ||
33 | + email, | ||
34 | + password: hashedPassword, | ||
35 | + }); | ||
36 | + | ||
37 | + // Send response | ||
38 | + if (user) { | ||
39 | + // 201: Resource successfully created | ||
40 | + res.status(201).json({ | ||
41 | + _id: user.id, | ||
42 | + username: user.username, | ||
43 | + country: user.country, | ||
44 | + city: user.city, | ||
45 | + email: user.email, | ||
46 | + token: jwtGenerator(user._id), | ||
47 | + }); | ||
48 | + } else { | ||
49 | + res.status(400); | ||
50 | + throw new Error("Invalid user data"); | ||
51 | + } | ||
52 | +}); | ||
53 | + | ||
54 | +// @desc Login user | ||
55 | +// @route POST /api/users/login | ||
56 | +// @access Public | ||
57 | +const loginUser = asyncHandler(async (req, res) => { | ||
58 | + const { email, password } = req.body; | ||
59 | + | ||
60 | + // Check email & password | ||
61 | + const userInDB = await User.findOne({ email }); | ||
62 | + const validPassword = await bcrypt.compare(password, userInDB.password); | ||
63 | + if (userInDB && validPassword) { | ||
64 | + res.status(200).json({ | ||
65 | + token: jwtGenerator(userInDB._id), | ||
66 | + }); | ||
67 | + } else { | ||
68 | + res.status(400); | ||
69 | + throw new Error("Invalid credentials"); | ||
70 | + } | ||
71 | +}); | ||
72 | + | ||
73 | +// @desc Get all users | ||
74 | +// @route GET /api/users/all | ||
75 | +// @access Public | ||
76 | +const getAllusers = asyncHandler(async (req, res) => { | ||
77 | + const users = await User.find() | ||
78 | + .select("-password") | ||
79 | + .select("-createdAt") | ||
80 | + .select("-email"); | ||
81 | + | ||
82 | + res.status(200).json(users); | ||
83 | +}); | ||
84 | + | ||
85 | +// @desc Get user | ||
86 | +// @route GET /api/users/self | ||
87 | +// @access Private | ||
88 | +const getSelf = asyncHandler(async (req, res) => { | ||
89 | + res.status(200).json(req.user); | ||
90 | +}); | ||
91 | + | ||
92 | +// @desc Edit user | ||
93 | +// @route PUT /api/users/edit | ||
94 | +// @access Private | ||
95 | +const editUser = asyncHandler(async (req, res) => { | ||
96 | + const {username, country, city, email} = req.body; | ||
97 | + console.log(username); | ||
98 | + res.json({}); | ||
99 | +}); | ||
100 | + | ||
101 | +module.exports = { | ||
102 | + signupUser, | ||
103 | + loginUser, | ||
104 | + getAllusers, | ||
105 | + getSelf, | ||
106 | + editUser, | ||
107 | +}; |
... | @@ -89,9 +89,37 @@ const getSelf = asyncHandler(async (req, res) => { | ... | @@ -89,9 +89,37 @@ const getSelf = asyncHandler(async (req, res) => { |
89 | res.status(200).json(req.user); | 89 | res.status(200).json(req.user); |
90 | }); | 90 | }); |
91 | 91 | ||
92 | +// @desc Edit user | ||
93 | +// @route PUT /api/users/edit | ||
94 | +// @access Private | ||
95 | +const editUser = asyncHandler(async (req, res) => { | ||
96 | + const { username, country, city, email } = req.body; | ||
97 | + const change = {}; | ||
98 | + if (username.length) { | ||
99 | + change["username"] = username; | ||
100 | + } | ||
101 | + if (country.length) { | ||
102 | + change["country"] = country; | ||
103 | + } | ||
104 | + if (city.length) { | ||
105 | + change["city"] = city; | ||
106 | + } | ||
107 | + if (email.length) { | ||
108 | + change["email"] = email; | ||
109 | + } | ||
110 | + try { | ||
111 | + await User.findByIdAndUpdate(req.user._id, change); | ||
112 | + res.send(); | ||
113 | + } catch (err) { | ||
114 | + res.status(400); | ||
115 | + throw new Error("Something went wrong from mongoDB"); | ||
116 | + } | ||
117 | +}); | ||
118 | + | ||
92 | module.exports = { | 119 | module.exports = { |
93 | signupUser, | 120 | signupUser, |
94 | loginUser, | 121 | loginUser, |
95 | getAllusers, | 122 | getAllusers, |
96 | getSelf, | 123 | getSelf, |
124 | + editUser, | ||
97 | }; | 125 | }; | ... | ... |
1 | -const bcrypt = require("bcryptjs"); | ||
2 | const jwt = require("jsonwebtoken"); | 1 | const jwt = require("jsonwebtoken"); |
3 | const axios = require("axios").default; | 2 | const axios = require("axios").default; |
4 | const User = require("../models/userModel"); | 3 | const User = require("../models/userModel"); | ... | ... |
... | @@ -5,6 +5,7 @@ const { | ... | @@ -5,6 +5,7 @@ const { |
5 | loginUser, | 5 | loginUser, |
6 | getAllusers, | 6 | getAllusers, |
7 | getSelf, | 7 | getSelf, |
8 | + editUser, | ||
8 | } = require("../actions/userActions"); | 9 | } = require("../actions/userActions"); |
9 | const { authHandler } = require("../middleware/authMiddleware"); | 10 | const { authHandler } = require("../middleware/authMiddleware"); |
10 | 11 | ||
... | @@ -13,5 +14,6 @@ router.post("/", signupUser); | ... | @@ -13,5 +14,6 @@ router.post("/", signupUser); |
13 | router.post("/login", loginUser); | 14 | router.post("/login", loginUser); |
14 | router.get("/all", authHandler, getAllusers); | 15 | router.get("/all", authHandler, getAllusers); |
15 | router.get("/self", authHandler, getSelf); | 16 | router.get("/self", authHandler, getSelf); |
17 | +router.put("/edit", authHandler, editUser); | ||
16 | 18 | ||
17 | module.exports = router; | 19 | module.exports = router; | ... | ... |
-
Please register or login to post a comment