Skip to content

Commit d55228d

Browse files
Merge pull request #20 from CS3219-AY2425S1/login-frontend
Create Login frontend Features to fix: - We need to protect the home route from direct access - (nice-to-have) have password strength requirements
2 parents 021ea95 + c34e6f0 commit d55228d

File tree

8 files changed

+118
-46
lines changed

8 files changed

+118
-46
lines changed

Frontend/src/App.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ function App() {
2323

2424
{/* Home page route */}
2525
<Route path='/home' element={<Home />} />
26-
27-
{/* Create and Edit question routes */}
28-
<Route path='/create' element={<CreateQn />} />
29-
<Route path='/update/:question_db_id' element={<EditQn />} />
3026
</Routes>
3127
</BrowserRouter>
3228
</div>

Frontend/src/components/NavigationBar.jsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
import Container from 'react-bootstrap/Container';
22
import Navbar from 'react-bootstrap/Navbar';
3+
import Button from 'react-bootstrap/esm/Button';
4+
import { useNavigate } from 'react-router-dom';
35

46
function NavigationBar() {
7+
const navigate = useNavigate();
8+
9+
// Add log out functionality
10+
const handleLogout = () => {
11+
navigate("/login");
12+
}
13+
514
return (
615
<Navbar className='bg-light' sticky="top">
716
<Container>
817
<Navbar.Brand>PeerPrep</Navbar.Brand>
18+
<Button className="ms-auto" variant="danger" onClick={handleLogout}>
19+
Logout
20+
</Button>
921
</Container>
1022
</Navbar>
1123
);

Frontend/src/components/auth/InputField.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React from 'react';
22
import '../../css/InputField.css'; // Import the CSS file for styling
33

4-
const InputField = ({ label, type = "text", placeholder, value, onChange }) => {
4+
const InputField = ({ label, type = "text", placeholder, value, onChange, error }) => {
55
return (
66
<div className="input-container">
77
<div className="input-title">{label}</div>
88
<input
9-
className="input-element"
9+
className={`input-element ${error ? 'input-error' : ''}`} // to change border color when input missing/wrong
1010
type={type}
1111
placeholder={placeholder}
1212
value={value}

Frontend/src/components/auth/Login.jsx

Lines changed: 65 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,55 @@
1-
// import React from 'react';
2-
// import { useNavigate } from 'react-router-dom';
3-
// import { Button, Container, Row, Col } from 'react-bootstrap';
4-
5-
// function Login() {
6-
// const navigate = useNavigate();
7-
8-
// const goToSignUp = () => {
9-
// navigate('/signup'); // Redirects to the sign-up page
10-
// };
11-
12-
// return (
13-
// <Container className="d-flex align-items-center justify-content-center" style={{ height: '100vh' }}>
14-
// <Row>
15-
// <Col md={6} className="text-center">
16-
// <h2>Login Page</h2>
17-
// <p>If you don't have an account, click the button below to sign up!</p>
18-
// <Button variant="primary" onClick={goToSignUp}>
19-
// Go to Sign Up
20-
// </Button>
21-
// </Col>
22-
// </Row>
23-
// </Container>
24-
// );
25-
// }
26-
27-
// export default Login;
28-
291
import React, { useState } from 'react';
30-
import { Link } from 'react-router-dom'; // Import Link for navigation
2+
import { Link, useNavigate } from 'react-router-dom'; // Import Link for navigation
313
import '../../css/Login.css'; // Import the CSS for styling
324
import InputField from './InputField';
5+
import userService from '../../services/users';
336

347
const Login = () => {
358
const [email, setEmail] = useState('');
369
const [password, setPassword] = useState('');
10+
const [error, setError] = useState('');
11+
const [emailError, setEmailError] = useState(false);
12+
const [passwordError, setPasswordError] = useState(false);
13+
const navigate = useNavigate();
3714

3815
const handleLogin = (e) => {
3916
e.preventDefault();
40-
// Add your login logic here
17+
18+
const userCredentials = {email, password};
4119
console.log('Logging in with:', { email, password });
20+
21+
// call the login user API
22+
userService.loginUser(userCredentials)
23+
.then(result => {
24+
// navigate to home page if successful
25+
console.log(result);
26+
navigate('/home')
27+
})
28+
.catch(e => {
29+
// handle errors here
30+
if (e.response) {
31+
switch (e.response.status) {
32+
case 400:
33+
setError(e.response.data.message); // Missing email and/or password
34+
setEmailError(true);
35+
setPasswordError(true);
36+
break;
37+
case 401:
38+
setError(e.response.data.message); // Wrong email and/or password
39+
setEmailError(true);
40+
setPasswordError(true);
41+
break;
42+
case 500:
43+
setError(e.response.data.message); // Database or server error
44+
break;
45+
default:
46+
setError("An unexpected error occurred.");
47+
break;
48+
}
49+
} else {
50+
setError("Network error. Please check your connection.");
51+
}
52+
})
4253
};
4354

4455
return (
@@ -51,14 +62,36 @@ const Login = () => {
5162
<div className="input-container">
5263
<form onSubmit={handleLogin}>
5364
<div>
54-
<InputField label="Email" type="email" placeholder="Enter your email" />
55-
<InputField label="Password" type="password" placeholder="Enter your password" />
65+
<InputField
66+
label="Email"
67+
type="email"
68+
placeholder="Enter your email"
69+
onChange={(e) => {
70+
setEmail(e.target.value)
71+
setEmailError(false);
72+
}}
73+
error={emailError}
74+
required
75+
/>
76+
<InputField label="Password"
77+
type="password"
78+
placeholder="Enter your password"
79+
onChange={(e) => {
80+
setPassword(e.target.value)
81+
setPasswordError(false)
82+
}}
83+
error={passwordError}
84+
required
85+
/>
5686
</div>
5787
<div className="button-container">
5888
<Link to="/signup" className="create-account-link">Create Account</Link>
5989
<button type="submit" className="login-button">Sign In</button>
6090
</div>
6191
</form>
92+
<div className='notification'>
93+
{error && <p className="text-danger mt-3">{error}</p>}
94+
</div>
6295
</div>
6396
</div>
6497
</div>

Frontend/src/components/auth/SignUp.jsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ function SignUp() {
1010
const [password, setPassword] = useState('');
1111
const [errorMessage, setErrorMessage] = useState('');
1212
const [successMessage, setSuccessMessage] = useState('');
13+
const [usernameError, setUsernameError] = useState(false);
14+
const [emailError, setEmailError] = useState(false);
15+
const [passwordError, setPasswordError] = useState(false);
1316

1417
const navigate = useNavigate(); // Initialize useNavigate
1518

@@ -42,9 +45,14 @@ function SignUp() {
4245
switch (error.response.status) {
4346
case 400:
4447
setErrorMessage('Please fill in all required fields.');
48+
setUsernameError(true);
49+
setEmailError(true);
50+
setPasswordError(true);
4551
break;
4652
case 409:
4753
setErrorMessage('Username or email already exists.');
54+
setUsernameError(true);
55+
setEmailError(true);
4856
break;
4957
case 500:
5058
setErrorMessage('Server error. Please try again later.');
@@ -73,23 +81,35 @@ function SignUp() {
7381
type="text"
7482
placeholder="Enter your username"
7583
value={username}
76-
onChange={(e) => setUsername(e.target.value)}
84+
onChange={(e) => {
85+
setUsername(e.target.value)
86+
setUsernameError(false);
87+
}}
88+
error={usernameError}
7789
required
7890
/>
7991
<InputField
8092
label="Email"
8193
type="email"
8294
placeholder="Enter your email"
8395
value={email}
84-
onChange={(e) => setEmail(e.target.value)}
96+
onChange={(e) => {
97+
setEmail(e.target.value)
98+
setEmailError(false);
99+
}}
100+
error={emailError}
85101
required
86102
/>
87103
<InputField
88104
label="Password"
89105
type="password"
90106
placeholder="Enter your password"
91107
value={password}
92-
onChange={(e) => setPassword(e.target.value)}
108+
onChange={(e) => {
109+
setPassword(e.target.value)
110+
setPasswordError(false);
111+
}}
112+
error={passwordError}
93113
required
94114
/>
95115
<div className='button-container'>

Frontend/src/components/question/CreateQn.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function CreateQn({handleClose, addQuestion}) {
2121
console.log(result.data)
2222
addQuestion(result.data)
2323
handleClose()
24-
navigate('/')
24+
navigate("/home")
2525
}
2626
)
2727
.catch(e => {

Frontend/src/css/InputField.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,7 @@
2626
.input-element:focus {
2727
border-color: #004b9b; /* Change border color on focus */
2828
}
29+
30+
.input-error {
31+
border-color: #ff0000; /* Change border color on wrong input */
32+
}

Frontend/src/services/users.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import axios from 'axios';
22

3-
const baseUrl = 'http://localhost:3002/users';
3+
const baseUrl = 'http://localhost:3002';
4+
const auth = "auth"
5+
const user = "users"
46

57
const createUser = async (newUser) => {
6-
const response = await axios.post(`${baseUrl}`, newUser);
8+
const response = await axios.post(`${baseUrl}/${user}`, newUser);
79
return response;
810
};
911

1012
const getUser = async (id) => {
11-
const response = await axios.get(`${baseUrl}/${id}`);
13+
const response = await axios.get(`${baseUrl}/${user}/${id}`);
1214
return response;
1315
};
1416

15-
export default { createUser, getUser };
17+
const loginUser = async (userCredentials) => {
18+
const response = await axios.post(`${baseUrl}/${auth}/login`, userCredentials);
19+
return response;
20+
}
21+
22+
export default { createUser, getUser, loginUser };

0 commit comments

Comments
 (0)