Skip to content

Commit 7e82ae7

Browse files
committed
user profile page config
1 parent 09fe567 commit 7e82ae7

File tree

9 files changed

+338
-3
lines changed

9 files changed

+338
-3
lines changed

backend/core/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from django.urls import path
22

33
from core.views import (MyTokenObtainPairView, getProduct, getProducts,
4-
getUserProfile, getUsers, registerUser)
4+
getUserProfile, getUsers, registerUser,
5+
updateUserProfile)
56

67
APP_NAME = 'core'
78

@@ -10,6 +11,7 @@
1011
path('users/login/', MyTokenObtainPairView.as_view(), name="token_obtain_pair"),
1112
path('users/register/', registerUser, name="user-register"),
1213
path('users/profile/', getUserProfile, name="user-profile"),
14+
path('users/profile/update/', updateUserProfile, name="user-profile-update"),
1315
path('users/', getUsers, name="users"),
1416

1517
# products urls

backend/core/views.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ class MyTokenObtainPairView(TokenObtainPairView):
1616
serializer_class = MyTokenObtainPairSerializer
1717

1818

19+
@api_view(['PUT'])
20+
@permission_classes([IsAuthenticated])
21+
def updateUserProfile(request):
22+
user = request.user
23+
serializer = UserSerializerWithToken(user, many=False)
24+
data = request.data
25+
user.first_name = data.get('name')
26+
user.email = data.get('email')
27+
if data.get('password') != '':
28+
user.set_password(data.get('password'))
29+
user.save()
30+
return Response(serializer.data)
31+
32+
1933
@api_view(['GET'])
2034
@permission_classes([IsAuthenticated])
2135
def getUserProfile(request):

frontend/src/App.jsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import LoginPage from "./Pages/LoginPage";
77
import CartPage from "./Pages/CartPage";
88
import Footer from "./components/Footer";
99
import Header from "./components/Header";
10+
import RegisterPage from "./Pages/RegisterPage";
11+
import UserProfilePage from "./Pages/UserProfilePage";
1012

1113
function App() {
1214
return (
@@ -16,9 +18,11 @@ function App() {
1618
<Container>
1719
<Switch>
1820
<Route path="/" component={HomePage} exact />
21+
<Route path="/login" component={LoginPage} />
22+
<Route path="/register" component={RegisterPage} />
23+
<Route path="/profile" component={UserProfilePage} />
1924
<Route path="/product/:id" component={ProductPage} />
2025
<Route path="/cart/:id?" component={CartPage} />
21-
<Route path="/login" component={LoginPage} />
2226
</Switch>
2327
</Container>
2428
</main>

frontend/src/Pages/RegisterPage.jsx

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import React, { useState, useEffect } from "react";
2+
import { useDispatch, useSelector } from "react-redux";
3+
import { Link } from "react-router-dom";
4+
import { Form, Button, Row, Col } from "react-bootstrap";
5+
import Loader from "../components/Loader";
6+
import Message from "../components/Message";
7+
import FormContainer from "../components/FormContainer";
8+
import { register } from "../actions/userActions";
9+
10+
function RegisterPage({ location, history }) {
11+
const [name, setName] = useState("");
12+
const [email, setEmail] = useState("");
13+
const [password, setPassword] = useState("");
14+
const [confirmPassword, setConfirmPassword] = useState("");
15+
const [message, setMessage] = useState("");
16+
17+
const dispatch = useDispatch();
18+
const redirect = location.search ? location.search.split("=")[1] : "/";
19+
20+
const { loading, userInfo, error } = useSelector(
21+
(state) => state.userRegister
22+
);
23+
24+
useEffect(() => {
25+
if (userInfo) {
26+
history.push(redirect);
27+
}
28+
}, [history, userInfo, redirect]);
29+
30+
const submitHandler = (e) => {
31+
e.preventDefault();
32+
if (password !== confirmPassword) {
33+
setMessage("Passwords Don't Match");
34+
} else {
35+
dispatch(register(name, email, password));
36+
}
37+
};
38+
39+
return (
40+
<FormContainer>
41+
<h1>Sign In</h1>
42+
{message && <Message variant="danger">{message}</Message>}
43+
{error && <Message variant="danger">{error}</Message>}
44+
{loading && <Loader />}
45+
<Form onSubmit={submitHandler}>
46+
<Form.Group controlId="name">
47+
<Form.Label>Enter Name</Form.Label>
48+
<Form.Control
49+
required
50+
type="text"
51+
placeholder="Enter Name"
52+
value={name}
53+
onChange={(e) => setName(e.target.value)}
54+
></Form.Control>
55+
</Form.Group>
56+
57+
<Form.Group controlId="email">
58+
<Form.Label>Enter Email</Form.Label>
59+
<Form.Control
60+
required
61+
type="email"
62+
placeholder="Enter Email"
63+
value={email}
64+
onChange={(e) => setEmail(e.target.value)}
65+
></Form.Control>
66+
</Form.Group>
67+
68+
<Form.Group controlId="password">
69+
<Form.Label>Enter Password</Form.Label>
70+
<Form.Control
71+
required
72+
type="password"
73+
placeholder="Enter Password"
74+
value={password}
75+
onChange={(e) => setPassword(e.target.value)}
76+
></Form.Control>
77+
</Form.Group>
78+
79+
<Form.Group controlId="confirmpassword">
80+
<Form.Label>Enter Confirm Password</Form.Label>
81+
<Form.Control
82+
required
83+
type="password"
84+
placeholder="Enter Confirm Password"
85+
value={confirmPassword}
86+
onChange={(e) => setConfirmPassword(e.target.value)}
87+
></Form.Control>
88+
</Form.Group>
89+
90+
<Button type="submit" variant="primary">
91+
Register
92+
</Button>
93+
</Form>
94+
<Row className="py-3">
95+
<Col>
96+
Already Customer?{" "}
97+
<Link to={redirect ? `/login?redirect=${redirect}` : "/login"}>
98+
Login
99+
</Link>
100+
</Col>
101+
</Row>
102+
</FormContainer>
103+
);
104+
}
105+
106+
export default RegisterPage;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import React, { useState, useEffect } from "react";
2+
import { useDispatch, useSelector } from "react-redux";
3+
import { Form, Button, Row, Col } from "react-bootstrap";
4+
import Loader from "../components/Loader";
5+
import Message from "../components/Message";
6+
import { getUserDetails } from "../actions/userActions";
7+
8+
function UserProfilePage({ history }) {
9+
const [name, setName] = useState("");
10+
const [email, setEmail] = useState("");
11+
const [password, setPassword] = useState("");
12+
const [confirmPassword, setConfirmPassword] = useState("");
13+
const [message, setMessage] = useState("");
14+
15+
const dispatch = useDispatch();
16+
17+
const { loading, user, error } = useSelector((state) => state.userDetails);
18+
19+
const { userInfo } = useSelector((state) => state.userLogin);
20+
21+
useEffect(() => {
22+
if (!userInfo) {
23+
history.push("/login");
24+
} else {
25+
if (!user || !user.name) {
26+
dispatch(getUserDetails("profile"));
27+
} else {
28+
setName(user.name);
29+
setEmail(user.email);
30+
}
31+
}
32+
}, [dispatch, userInfo, history, user]);
33+
34+
const submitHandler = (e) => {
35+
e.preventDefault();
36+
if (password !== confirmPassword) {
37+
setMessage("Passwords Don't Match");
38+
} else {
39+
console.log("Updating Profile...");
40+
}
41+
};
42+
43+
return (
44+
<Row>
45+
<Col md={3}>
46+
<h2>User Profile</h2>
47+
48+
{message && <Message variant="danger">{message}</Message>}
49+
{error && <Message variant="danger">{error}</Message>}
50+
{loading && <Loader />}
51+
<Form onSubmit={submitHandler}>
52+
<Form.Group controlId="name">
53+
<Form.Label>Enter Name</Form.Label>
54+
<Form.Control
55+
type="text"
56+
placeholder="Enter Name"
57+
value={name}
58+
onChange={(e) => setName(e.target.value)}
59+
></Form.Control>
60+
</Form.Group>
61+
62+
<Form.Group controlId="email">
63+
<Form.Label>Enter Email</Form.Label>
64+
<Form.Control
65+
type="email"
66+
placeholder="Enter Email"
67+
value={email}
68+
onChange={(e) => setEmail(e.target.value)}
69+
></Form.Control>
70+
</Form.Group>
71+
72+
<Form.Group controlId="password">
73+
<Form.Label>Enter Password</Form.Label>
74+
<Form.Control
75+
type="password"
76+
placeholder="Enter Password"
77+
value={password}
78+
onChange={(e) => setPassword(e.target.value)}
79+
></Form.Control>
80+
</Form.Group>
81+
82+
<Form.Group controlId="confirmpassword">
83+
<Form.Label>Enter Confirm Password</Form.Label>
84+
<Form.Control
85+
type="password"
86+
placeholder="Enter Confirm Password"
87+
value={confirmPassword}
88+
onChange={(e) => setConfirmPassword(e.target.value)}
89+
></Form.Control>
90+
</Form.Group>
91+
92+
<Button type="submit" variant="primary">
93+
Update
94+
</Button>
95+
</Form>
96+
</Col>
97+
<Col md={9}>
98+
<h2>My Orders</h2>
99+
</Col>
100+
</Row>
101+
);
102+
}
103+
104+
export default UserProfilePage;

frontend/src/actions/userActions.jsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import {
33
USER_LOGIN_SUCCESS,
44
USER_LOGIN_FAIL,
55
USER_LOGOUT,
6+
USER_REGISTER_REQUEST,
7+
USER_REGISTER_SUCCESS,
8+
USER_REGISTER_FAIL,
9+
USER_DETAILS_REQUEST,
10+
USER_DETAILS_SUCCESS,
11+
USER_DETAILS_FAIL,
612
} from "../constants/userConstants.jsx";
713

814
import axios from "axios";
@@ -38,3 +44,55 @@ export const logout = () => (dispatch) => {
3844
localStorage.removeItem("userInfo");
3945
dispatch({ type: USER_LOGOUT });
4046
};
47+
48+
export const register = (name, email, password) => async (dispatch) => {
49+
try {
50+
dispatch({ type: USER_REGISTER_REQUEST });
51+
const config = {
52+
"Content-type": "application/json",
53+
};
54+
const { data } = await axios.post(
55+
"/api/users/register/",
56+
{
57+
email: email,
58+
name: name,
59+
password: password,
60+
},
61+
config
62+
);
63+
dispatch({ type: USER_REGISTER_SUCCESS, payload: data });
64+
dispatch({ type: USER_LOGIN_SUCCESS });
65+
localStorage.setItem("userInfo", JSON.stringify(data));
66+
} catch (err) {
67+
dispatch({
68+
type: USER_REGISTER_FAIL,
69+
payload:
70+
err.response && err.response.data.detail
71+
? err.response.data.detail
72+
: err.message,
73+
});
74+
}
75+
};
76+
77+
export const getUserDetails = (id) => async (dispatch, getState) => {
78+
try {
79+
dispatch({ type: USER_DETAILS_REQUEST });
80+
const {
81+
userLogin: { userInfo },
82+
} = getState();
83+
const config = {
84+
"Content-type": "application/json",
85+
Authorization: `Bearer ${userInfo.token}`,
86+
};
87+
const { data } = await axios.get(`/api/users/${id}/`, config);
88+
dispatch({ type: USER_DETAILS_SUCCESS, payload: data });
89+
} catch (err) {
90+
dispatch({
91+
type: USER_DETAILS_FAIL,
92+
payload:
93+
err.response && err.response.data.detail
94+
? err.response.data.detail
95+
: err.message,
96+
});
97+
}
98+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
export const USER_LOGIN_REQUEST = "USER_LOGIN_REQUEST";
22
export const USER_LOGIN_SUCCESS = "USER_LOGIN_SUCCESS";
33
export const USER_LOGIN_FAIL = "USER_LOGIN_FAIL";
4+
45
export const USER_LOGOUT = "USER_LOGOUT";
6+
7+
export const USER_REGISTER_REQUEST = "USER_REGISTER_REQUEST";
8+
export const USER_REGISTER_SUCCESS = "USER_REGISTER_SUCCESS";
9+
export const USER_REGISTER_FAIL = "USER_REGISTER_FAIL";
10+
11+
export const USER_DETAILS_REQUEST = "USER_DETAILS_REQUEST";
12+
export const USER_DETAILS_SUCCESS = "USER_DETAILS_SUCCESS";
13+
export const USER_DETAILS_FAIL = "USER_DETAILS_FAIL";

frontend/src/reducers/userReducer.jsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import {
33
USER_LOGIN_SUCCESS,
44
USER_LOGIN_FAIL,
55
USER_LOGOUT,
6+
USER_REGISTER_REQUEST,
7+
USER_REGISTER_SUCCESS,
8+
USER_REGISTER_FAIL,
9+
USER_DETAILS_REQUEST,
10+
USER_DETAILS_SUCCESS,
11+
USER_DETAILS_FAIL,
612
} from "../constants/userConstants.jsx";
713

814
export const userReducer = (state = {}, action) => {
@@ -19,3 +25,29 @@ export const userReducer = (state = {}, action) => {
1925
return state;
2026
}
2127
};
28+
29+
export const userRegisterReducer = (state = {}, action) => {
30+
switch (action.type) {
31+
case USER_REGISTER_REQUEST:
32+
return { loading: true };
33+
case USER_REGISTER_SUCCESS:
34+
return { loading: false, userInfo: action.payload };
35+
case USER_REGISTER_FAIL:
36+
return { loading: false, error: action.payload };
37+
default:
38+
return state;
39+
}
40+
};
41+
42+
export const userDetailsReducer = (state = { user: {} }, action) => {
43+
switch (action.type) {
44+
case USER_DETAILS_REQUEST:
45+
return { ...state, loading: true };
46+
case USER_DETAILS_SUCCESS:
47+
return { loading: false, user: action.payload };
48+
case USER_DETAILS_FAIL:
49+
return { loading: false, error: action.payload };
50+
default:
51+
return state;
52+
}
53+
};

0 commit comments

Comments
 (0)