Skip to content

Commit 3f2cde4

Browse files
committed
add update profile, forgot password and private route
1 parent 40e1611 commit 3f2cde4

File tree

6 files changed

+330
-3
lines changed

6 files changed

+330
-3
lines changed

frontend/src/App.jsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ import {
1010
import SignIn from './components/signin'
1111
import SignUp from './components/signup'
1212
import Home from './components/Home'
13+
import UpdateProfile from './components/UpdateProfile'
14+
import ForgotPassword from './components/ForgotPassword'
1315

1416
// context
1517
import { AuthProvider } from './context/AuthContext'
1618

19+
// Route
20+
import PrivateRoute from './route/PrivateRoute'
21+
1722
function App() {
1823

1924
return (
@@ -26,9 +31,18 @@ function App() {
2631
<Route path="/signup">
2732
<SignUp />
2833
</Route>
29-
<Route path="/">
30-
<Home/>
34+
<Route path="/forgot-password">
35+
<ForgotPassword />
3136
</Route>
37+
38+
<PrivateRoute>
39+
<Route exact path="/">
40+
<Home/>
41+
</Route>
42+
<Route path="/update-profile">
43+
<UpdateProfile />
44+
</Route>
45+
</PrivateRoute>
3246
</Switch>
3347
</AuthProvider>
3448
</Router>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import React, { useState } from 'react';
2+
import Avatar from '@material-ui/core/Avatar';
3+
import Button from '@material-ui/core/Button';
4+
import CssBaseline from '@material-ui/core/CssBaseline';
5+
import TextField from '@material-ui/core/TextField';
6+
import FormControlLabel from '@material-ui/core/FormControlLabel';
7+
import Checkbox from '@material-ui/core/Checkbox';
8+
import Link from '@material-ui/core/Link';
9+
import Grid from '@material-ui/core/Grid';
10+
import Box from '@material-ui/core/Box';
11+
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
12+
import Typography from '@material-ui/core/Typography';
13+
import { makeStyles } from '@material-ui/core/styles';
14+
import Container from '@material-ui/core/Container';
15+
import { useHistory } from "react-router-dom"
16+
17+
// context
18+
import { useAuth } from '../context/AuthContext'
19+
20+
function Copyright() {
21+
return (
22+
<Typography variant="body2" color="textSecondary" align="center">
23+
{'Copyright © '}
24+
<Link color="inherit" href="https://material-ui.com/">
25+
Your Website
26+
</Link>{' '}
27+
{new Date().getFullYear()}
28+
{'.'}
29+
</Typography>
30+
);
31+
}
32+
33+
const useStyles = makeStyles((theme) => ({
34+
paper: {
35+
marginTop: theme.spacing(8),
36+
display: 'flex',
37+
flexDirection: 'column',
38+
alignItems: 'center',
39+
},
40+
avatar: {
41+
margin: theme.spacing(1),
42+
backgroundColor: theme.palette.secondary.main,
43+
},
44+
form: {
45+
width: '100%', // Fix IE 11 issue.
46+
marginTop: theme.spacing(1),
47+
},
48+
submit: {
49+
margin: theme.spacing(3, 0, 2),
50+
},
51+
}));
52+
53+
export default function SignIn() {
54+
const classes = useStyles();
55+
const { resetPassword } = useAuth()
56+
57+
async function handleSubmit(e) {
58+
e.preventDefault()
59+
60+
const signinFields = {
61+
email: e.target.email.value,
62+
}
63+
64+
try {
65+
await resetPassword(signinFields.email)
66+
} catch {
67+
console.log("Failed to log in")
68+
}
69+
}
70+
71+
return (
72+
<Container component="main" maxWidth="xs">
73+
<CssBaseline />
74+
<div className={classes.paper}>
75+
<Avatar className={classes.avatar}>
76+
<LockOutlinedIcon />
77+
</Avatar>
78+
<Typography component="h1" variant="h5">
79+
Reset Password
80+
</Typography>
81+
<form className={classes.form} onSubmit={handleSubmit} noValidate>
82+
<TextField
83+
variant="outlined"
84+
margin="normal"
85+
required
86+
fullWidth
87+
id="email"
88+
label="Email Address"
89+
name="email"
90+
autoComplete="email"
91+
autoFocus
92+
/>
93+
94+
<Button
95+
type="submit"
96+
fullWidth
97+
variant="contained"
98+
color="primary"
99+
className={classes.submit}
100+
>
101+
Reset Password
102+
</Button>
103+
<Grid container>
104+
<Grid item>
105+
<Link href="/signup" variant="body2">
106+
{"Don't have an account? Sign Up"}
107+
</Link>
108+
</Grid>
109+
</Grid>
110+
</form>
111+
</div>
112+
<Box mt={8}>
113+
<Copyright />
114+
</Box>
115+
</Container>
116+
);
117+
}

frontend/src/components/Home.jsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,14 @@ export default function Home() {
1818
}
1919
},[currentUser])
2020

21+
22+
// handle functions
2123
function handleLogout (e) {
2224
logout()
2325
}
26+
function handleUpdateProfile () {
27+
history.push('/update-profile')
28+
}
2429

2530
return (
2631
<div>
@@ -32,6 +37,10 @@ export default function Home() {
3237
<Button variant="contained" color="primary" onClick={handleLogout}>
3338
Logout
3439
</Button>
40+
<br/>
41+
<Button variant="contained" color="secondary" onClick={handleUpdateProfile}>
42+
Update profile
43+
</Button>
3544
</div>
3645
):
3746
<h1>Loading...</h1>
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import React from 'react';
2+
import Avatar from '@material-ui/core/Avatar';
3+
import Button from '@material-ui/core/Button';
4+
import CssBaseline from '@material-ui/core/CssBaseline';
5+
import TextField from '@material-ui/core/TextField';
6+
import FormControlLabel from '@material-ui/core/FormControlLabel';
7+
import Checkbox from '@material-ui/core/Checkbox';
8+
import Link from '@material-ui/core/Link';
9+
import Grid from '@material-ui/core/Grid';
10+
import Box from '@material-ui/core/Box';
11+
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
12+
import Typography from '@material-ui/core/Typography';
13+
import { makeStyles } from '@material-ui/core/styles';
14+
import Container from '@material-ui/core/Container';
15+
import { useHistory } from 'react-router-dom'
16+
17+
import { useAuth } from "../context/AuthContext"
18+
19+
function Copyright() {
20+
return (
21+
<Typography variant="body2" color="textSecondary" align="center">
22+
{'Copyright © '}
23+
<Link color="inherit" href="https://material-ui.com/">
24+
Your Website
25+
</Link>{' '}
26+
{new Date().getFullYear()}
27+
{'.'}
28+
</Typography>
29+
);
30+
}
31+
32+
const useStyles = makeStyles((theme) => ({
33+
paper: {
34+
marginTop: theme.spacing(8),
35+
display: 'flex',
36+
flexDirection: 'column',
37+
alignItems: 'center',
38+
},
39+
avatar: {
40+
margin: theme.spacing(1),
41+
backgroundColor: theme.palette.secondary.main,
42+
},
43+
form: {
44+
width: '100%', // Fix IE 11 issue.
45+
marginTop: theme.spacing(3),
46+
},
47+
submit: {
48+
margin: theme.spacing(3, 0, 2),
49+
},
50+
}));
51+
52+
export default function SignUp() {
53+
const classes = useStyles();
54+
const { currentUser, updateEmail, updatePassword } = useAuth()
55+
const history = useHistory()
56+
57+
function handleSubmitUpdateProfile(e) {
58+
e.preventDefault()
59+
const signUpFields = {
60+
firstName: e.target.firstName.value,
61+
lastName: e.target.lastName.value,
62+
email: e.target.email.value,
63+
password: e.target.password.value
64+
}
65+
66+
let promises = []
67+
if(signUpFields.email !== currentUser.email) {
68+
promises.push(updateEmail(signUpFields.email))
69+
}
70+
71+
if(signUpFields.password) {
72+
promises.push(updatePassword(signUpFields.password))
73+
}
74+
75+
76+
Promise.all(promises)
77+
.then(()=>{
78+
history.push('/')
79+
})
80+
.catch(error=>{
81+
console.log('error: ', error);
82+
83+
})
84+
}
85+
86+
return (
87+
<Container component="main" maxWidth="xs">
88+
<CssBaseline />
89+
<div className={classes.paper}>
90+
<Avatar className={classes.avatar}>
91+
<LockOutlinedIcon />
92+
</Avatar>
93+
<Typography component="h1" variant="h5">
94+
Update Profile
95+
</Typography>
96+
<form className={classes.form} onSubmit={handleSubmitUpdateProfile} noValidate>
97+
<Grid container spacing={2}>
98+
<Grid item xs={12} sm={6}>
99+
<TextField
100+
autoComplete="fname"
101+
name="firstName"
102+
variant="outlined"
103+
required
104+
fullWidth
105+
id="firstName"
106+
label="First Name"
107+
autoFocus
108+
/>
109+
</Grid>
110+
<Grid item xs={12} sm={6}>
111+
<TextField
112+
variant="outlined"
113+
required
114+
fullWidth
115+
id="lastName"
116+
label="Last Name"
117+
name="lastName"
118+
autoComplete="lname"
119+
/>
120+
</Grid>
121+
<Grid item xs={12}>
122+
<TextField
123+
variant="outlined"
124+
required
125+
fullWidth
126+
id="email"
127+
label="Email Address"
128+
name="email"
129+
autoComplete="email"
130+
/>
131+
</Grid>
132+
<Grid item xs={12}>
133+
<TextField
134+
variant="outlined"
135+
required
136+
fullWidth
137+
name="password"
138+
label="Password"
139+
type="password"
140+
id="password"
141+
autoComplete="current-password"
142+
/>
143+
</Grid>
144+
{/* <Grid item xs={12}>
145+
<FormControlLabel
146+
control={<Checkbox value="allowExtraEmails" color="primary" />}
147+
label="I want to receive inspiration, marketing promotions and updates via email."
148+
/>
149+
</Grid> */}
150+
</Grid>
151+
<Button
152+
type="submit"
153+
fullWidth
154+
variant="contained"
155+
color="primary"
156+
className={classes.submit}
157+
>
158+
Update profile
159+
</Button>
160+
<Grid container justify="flex-end">
161+
<Grid item>
162+
<Link href="/signup" variant="body2">
163+
Already have an account? Sign up
164+
</Link>
165+
</Grid>
166+
</Grid>
167+
</form>
168+
</div>
169+
<Box mt={5}>
170+
<Copyright />
171+
</Box>
172+
</Container>
173+
);
174+
}

frontend/src/components/signin.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export default function SignIn() {
119119
</Button>
120120
<Grid container>
121121
<Grid item xs>
122-
<Link href="#" variant="body2">
122+
<Link href="/forgot-password" variant="body2">
123123
Forgot password?
124124
</Link>
125125
</Grid>

frontend/src/route/PrivateRoute.jsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react'
2+
import { Route, Redirect } from "react-router-dom";
3+
import {useAuth} from '../context/AuthContext'
4+
5+
6+
export default function PrivacteRoute({children}) {
7+
const {currentUser} = useAuth()
8+
return (
9+
<>
10+
{currentUser? children: <Redirect to='/signin' /> }
11+
</>
12+
)
13+
}

0 commit comments

Comments
 (0)