Update Login / Register Pages
This commit is contained in:
28632
frontend/package-lock.json
generated
28632
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
"react-dom": "^17.0.2",
|
||||
"react-router": "^5.2.1",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"react-scripts": "^5.0.1",
|
||||
"save": "^2.4.0",
|
||||
"typescript": "^4.4.3",
|
||||
"web-vitals": "^1.1.2"
|
||||
@@ -47,5 +47,8 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-error-overlay": "^6.0.9"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import NavigationBar from './components/NavigationBar';
|
||||
import useToken from "./UseToken";
|
||||
import React from "react";
|
||||
import Login from "./pages/Login";
|
||||
import Register from "./pages/Register";
|
||||
|
||||
|
||||
const App: React.FC = () => {
|
||||
@@ -29,6 +30,11 @@ const App: React.FC = () => {
|
||||
<Login setToken={setToken}/>
|
||||
</Route>
|
||||
}
|
||||
{!token &&
|
||||
<Route exact path="/register" key="/register">
|
||||
<Register setToken={setToken}/>
|
||||
</Route>
|
||||
}
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
|
||||
30
frontend/src/api/register.tsx
Normal file
30
frontend/src/api/register.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import axios from "axios";
|
||||
|
||||
export function register(username: string | undefined, password: string | undefined) {
|
||||
|
||||
const address = `${process.env.REACT_APP_BACKEND_URL}/api/register`;
|
||||
console.log(address);
|
||||
let credentials = {
|
||||
username,
|
||||
password
|
||||
};
|
||||
|
||||
return axios.create({
|
||||
timeout: 45000,
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
responseType: "json"
|
||||
}).post(address, credentials).then(
|
||||
({ data, status }) => {
|
||||
if (status !== 201) {
|
||||
throw new Error("Server exception");
|
||||
}
|
||||
return data;
|
||||
},
|
||||
err => {
|
||||
throw err;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -107,6 +107,13 @@ const NavigationBar: React.FC = (props: any) => {
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
}
|
||||
{!token &&
|
||||
<NavLink to="/register" style={{textDecoration: 'none'}} key="/register">
|
||||
<MenuItem selected={activeRoute("/register")}>
|
||||
<ListItemText primary="Register"/>
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
}
|
||||
</MenuList>
|
||||
</div>
|
||||
</Drawer>
|
||||
|
||||
@@ -2,41 +2,108 @@ import React, {useState} from 'react';
|
||||
import './Login.css';
|
||||
import PropTypes from 'prop-types';
|
||||
import {login} from "../api/login";
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Container from '@material-ui/core/Container';
|
||||
import { createTheme, ThemeProvider } from '@material-ui/core/styles';
|
||||
|
||||
export default function Login({setToken}: { setToken: any }) {
|
||||
//const Login: React.FC = (props: any) => {
|
||||
// function Copyright(props: any) {
|
||||
// return (
|
||||
// <Typography variant="body2" color="inherit" align="center" {...props}>
|
||||
// {'Copyright © '}
|
||||
// <Link color="inherit" href="https://mui.com/">
|
||||
// Stephen Sampson
|
||||
// </Link>{' '}
|
||||
// {new Date().getFullYear()}
|
||||
// {'.'}
|
||||
// </Typography>
|
||||
// );
|
||||
// }
|
||||
|
||||
const theme = createTheme();
|
||||
|
||||
export default function Register({setToken}: { setToken: any }) {
|
||||
|
||||
const [username, setUserName] = useState<string>();
|
||||
const [password, setPassword] = useState<string>();
|
||||
|
||||
const handleSubmit = async (e: { preventDefault: () => void; }) => {
|
||||
e.preventDefault();
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const token = await login(username, password);
|
||||
setToken(token);
|
||||
window.location.href = "/dashboard";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="login-wrapper">
|
||||
<h1>Please Log In</h1>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<label>
|
||||
<p>Username</p>
|
||||
<input type="text" onChange={e => setUserName(e.target.value)}/>
|
||||
</label>
|
||||
<label>
|
||||
<p>Password</p>
|
||||
<input type="password" onChange={e => setPassword(e.target.value)}/>
|
||||
</label>
|
||||
<div>
|
||||
<br/>
|
||||
<button type="submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
<ThemeProvider theme={theme}>
|
||||
<Container component="main" maxWidth="xs">
|
||||
<CssBaseline />
|
||||
<Box
|
||||
sx={{
|
||||
marginTop: 8,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Avatar>
|
||||
<LockOutlinedIcon/>
|
||||
</Avatar>
|
||||
<Typography component="h1" variant="h5">
|
||||
Sign In
|
||||
</Typography>
|
||||
<Box component="form" onSubmit={handleSubmit} sx={{ mt: 3 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id="username"
|
||||
label="Username"
|
||||
name="username"
|
||||
onChange={e => setUserName(e.target.value)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
name="password"
|
||||
label="Password"
|
||||
type="password"
|
||||
id="password"
|
||||
autoComplete="new-password"
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<br/>
|
||||
<Button
|
||||
style={{
|
||||
// backgroundColor: "",
|
||||
// colorScheme: "",
|
||||
// color: "black"
|
||||
}}
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
{/*<Copyright sx={{ mt: 5 }} />*/}
|
||||
</Container>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Login.propTypes = {
|
||||
Register.propTypes = {
|
||||
setToken: PropTypes.func.isRequired
|
||||
};
|
||||
5
frontend/src/pages/Register.css
Normal file
5
frontend/src/pages/Register.css
Normal file
@@ -0,0 +1,5 @@
|
||||
.register-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
151
frontend/src/pages/Register.tsx
Normal file
151
frontend/src/pages/Register.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import React, {useState} from 'react';
|
||||
import './Register.css';
|
||||
import PropTypes from 'prop-types';
|
||||
import {register} from "../api/register";
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import CssBaseline from '@material-ui/core/CssBaseline';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import LockOutlinedIcon from '@material-ui/icons/LockOutlined';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import Container from '@material-ui/core/Container';
|
||||
import { createTheme, ThemeProvider } from '@material-ui/core/styles';
|
||||
// import Link from '@material-ui/core/Link';
|
||||
|
||||
|
||||
// function Copyright(props: any) {
|
||||
// return (
|
||||
// <Typography variant="body2" color="inherit" align="center" {...props}>
|
||||
// {'Copyright © '}
|
||||
// <Link color="inherit" href="https://mui.com/">
|
||||
// Stephen Sampson
|
||||
// </Link>{' '}
|
||||
// {new Date().getFullYear()}
|
||||
// {'.'}
|
||||
// </Typography>
|
||||
// );
|
||||
// }
|
||||
|
||||
const theme = createTheme();
|
||||
|
||||
export default function Register({setToken}: { setToken: any }) {
|
||||
|
||||
const [username, setUserName] = useState<string>();
|
||||
const [password, setPassword] = useState<string>();
|
||||
|
||||
// const handleSubmit = async (e: { preventDefault: () => void; }) => {
|
||||
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
// const data = new FormData(event.currentTarget);
|
||||
// console.log({
|
||||
// email: data.get('email'),
|
||||
// password: data.get('password'),
|
||||
// });
|
||||
const token = await register(username, password);
|
||||
setToken(token);
|
||||
window.location.href = "/dashboard";
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<Container component="main" maxWidth="xs">
|
||||
<CssBaseline />
|
||||
<Box
|
||||
sx={{
|
||||
marginTop: 8,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Avatar>
|
||||
<LockOutlinedIcon />
|
||||
</Avatar>
|
||||
<Typography component="h1" variant="h5">
|
||||
Sign up
|
||||
</Typography>
|
||||
<Box component="form" onSubmit={handleSubmit} sx={{ mt: 3 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
autoComplete="given-name"
|
||||
name="firstName"
|
||||
required
|
||||
fullWidth
|
||||
id="firstName"
|
||||
label="First Name"
|
||||
autoFocus
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id="lastName"
|
||||
label="Last Name"
|
||||
name="lastName"
|
||||
autoComplete="family-name"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id="username"
|
||||
label="Username"
|
||||
name="username"
|
||||
onChange={e => setUserName(e.target.value)}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
id="email"
|
||||
label="Email Address"
|
||||
name="email"
|
||||
autoComplete="email"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<TextField
|
||||
required
|
||||
fullWidth
|
||||
name="password"
|
||||
label="Password"
|
||||
type="password"
|
||||
id="password"
|
||||
autoComplete="new-password"
|
||||
onChange={e => setPassword(e.target.value)}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<br/>
|
||||
<Button
|
||||
type="submit"
|
||||
fullWidth
|
||||
variant="contained"
|
||||
// sx={{ mt: 3, mb: 2 }}
|
||||
>
|
||||
Sign Up
|
||||
</Button>
|
||||
{/*<Grid container justifyContent="flex-end">*/}
|
||||
{/* <Grid item>*/}
|
||||
{/* <Link href="login" variant="body2">*/}
|
||||
{/* Already have an account? Sign in*/}
|
||||
{/* </Link>*/}
|
||||
{/* </Grid>*/}
|
||||
{/*</Grid>*/}
|
||||
</Box>
|
||||
</Box>
|
||||
{/*<Copyright sx={{ mt: 5 }} />*/}
|
||||
</Container>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
Register.propTypes = {
|
||||
setToken: PropTypes.func.isRequired
|
||||
};
|
||||
9676
frontend/yarn.lock
9676
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user