You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

131 lines
4.8 KiB

import React, { useReducer } from 'react';
import { WindowState } from "../Windows";
import { Box, Paper, Typography, TextField, Button } from "@material-ui/core";
import { useHistory, useLocation } from 'react-router';
import { useAuth, Auth } from '../../../lib/useAuth';
import Alert from '@material-ui/lab/Alert';
export enum LoginStatus {
NoneSubmitted = 0,
Unsuccessful,
// Note: no "successful" status because that would lead to a redirect.
}
export interface LoginWindowState extends WindowState {
email: string,
password: string,
status: LoginStatus,
}
export enum LoginWindowStateActions {
SetEmail = "SetEmail",
SetPassword = "SetPassword",
SetStatus = "SetStatus",
}
export function LoginWindowReducer(state: LoginWindowState, action: any) {
switch (action.type) {
case LoginWindowStateActions.SetEmail:
return { ...state, email: action.value }
case LoginWindowStateActions.SetPassword:
return { ...state, password: action.value }
case LoginWindowStateActions.SetStatus:
return { ...state, status: action.value }
default:
throw new Error("Unimplemented LoginWindow state update.")
}
}
export default function LoginWindow(props: {}) {
const [state, dispatch] = useReducer(LoginWindowReducer, {
email: "",
password: "",
status: LoginStatus.NoneSubmitted,
});
return <LoginWindowControlled state={state} dispatch={dispatch} />
}
export function LoginWindowControlled(props: {
state: LoginWindowState,
dispatch: (action: any) => void,
}) {
let history: any = useHistory();
let location: any = useLocation();
let auth: Auth = useAuth();
let { from } = location.state || { from: { pathname: "/" } };
const onSubmit = (event: any) => {
event.preventDefault();
auth.signin(props.state.email, props.state.password)
.then(() => {
history.replace(from);
}).catch((e: any) => {
props.dispatch({
type: LoginWindowStateActions.SetStatus,
value: LoginStatus.Unsuccessful,
})
})
}
return <Box width="100%" justifyContent="center" display="flex" flexWrap="wrap">
<Box
m={1}
mt={4}
width="500px"
>
<Paper>
<Box p={3}>
<Typography variant="h5">Sign in</Typography>
<form noValidate onSubmit={onSubmit}>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="email"
label="Email"
name="email"
autoFocus
onInput={(e: any) => props.dispatch({
type: LoginWindowStateActions.SetEmail,
value: e.target.value
})}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="password"
label="Password"
name="password"
type="password"
onInput={(e: any) => props.dispatch({
type: LoginWindowStateActions.SetPassword,
value: e.target.value
})}
/>
{props.state.status === LoginStatus.Unsuccessful && <Alert severity="error">
Login failed - Please check your credentials.
</Alert>
}
<Button
type="submit"
fullWidth
variant="outlined"
color="primary"
>Sign in</Button>
<Box display="flex" alignItems="center" mt={2}>
<Typography>Need an account?</Typography>
<Box flexGrow={1} ml={2}><Button
onClick={() => history.replace("/register")}
fullWidth
variant="outlined"
color="primary"
>Sign up</Button></Box>
</Box>
</form>
</Box>
</Paper>
</Box>
</Box>
}