2021-04-29 21:55:48 +02:00
|
|
|
import React, { useState } from 'react';
|
|
|
|
import classnames from 'classnames';
|
|
|
|
import PropTypes from 'prop-types';
|
2021-12-30 10:57:35 +01:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
Grid,
|
|
|
|
TextField,
|
|
|
|
Typography,
|
|
|
|
InputAdornment,
|
|
|
|
IconButton,
|
|
|
|
} from '@material-ui/core';
|
|
|
|
import { Visibility, VisibilityOff } from '@material-ui/icons';
|
2021-04-29 21:55:48 +02:00
|
|
|
import { useHistory } from 'react-router';
|
|
|
|
import { useCommonStyles } from '../../../common.styles';
|
|
|
|
import { useStyles } from './HostedAuth.styles';
|
2021-05-08 18:46:05 +02:00
|
|
|
import useQueryParams from '../../../hooks/useQueryParams';
|
2021-05-18 12:59:48 +02:00
|
|
|
import AuthOptions from '../common/AuthOptions/AuthOptions';
|
2021-05-21 14:01:28 +02:00
|
|
|
import DividerText from '../../common/DividerText/DividerText';
|
|
|
|
import ConditionallyRender from '../../common/ConditionallyRender';
|
2021-11-29 14:03:52 +01:00
|
|
|
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
2021-04-29 21:55:48 +02:00
|
|
|
|
2021-05-21 14:01:28 +02:00
|
|
|
const HostedAuth = ({ authDetails, passwordLogin }) => {
|
2021-04-29 21:55:48 +02:00
|
|
|
const commonStyles = useCommonStyles();
|
|
|
|
const styles = useStyles();
|
2021-11-29 14:03:52 +01:00
|
|
|
const { refetch } = useUser();
|
2021-04-29 21:55:48 +02:00
|
|
|
const history = useHistory();
|
2021-05-08 18:46:05 +02:00
|
|
|
const params = useQueryParams();
|
|
|
|
const [username, setUsername] = useState(params.get('email') || '');
|
2021-04-29 21:55:48 +02:00
|
|
|
const [password, setPassword] = useState('');
|
2021-12-30 10:57:35 +01:00
|
|
|
const [showPassword, setShowPassword] = useState(false);
|
2021-04-29 21:55:48 +02:00
|
|
|
const [errors, setErrors] = useState({
|
|
|
|
usernameError: '',
|
|
|
|
passwordError: '',
|
|
|
|
});
|
|
|
|
|
2021-12-30 10:57:35 +01:00
|
|
|
const handleClickShowPassword = () => {
|
|
|
|
setShowPassword(!showPassword);
|
|
|
|
};
|
|
|
|
|
|
|
|
const handleMouseDownPassword = e => {
|
|
|
|
e.preventDefault();
|
|
|
|
};
|
|
|
|
|
2021-04-29 21:55:48 +02:00
|
|
|
const handleSubmit = async evt => {
|
|
|
|
evt.preventDefault();
|
|
|
|
|
|
|
|
if (!username) {
|
|
|
|
setErrors(prev => ({
|
|
|
|
...prev,
|
|
|
|
usernameError: 'This is a required field',
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
if (!password) {
|
|
|
|
setErrors(prev => ({
|
|
|
|
...prev,
|
|
|
|
passwordError: 'This is a required field',
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!password || !username) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const user = { username, password };
|
|
|
|
const path = evt.target.action;
|
|
|
|
|
|
|
|
try {
|
|
|
|
await passwordLogin(path, user);
|
2021-11-29 14:03:52 +01:00
|
|
|
refetch();
|
2021-04-29 21:55:48 +02:00
|
|
|
history.push(`/`);
|
|
|
|
} catch (error) {
|
|
|
|
if (error.statusCode === 404 || error.statusCode === 400) {
|
|
|
|
setErrors(prev => ({
|
|
|
|
...prev,
|
|
|
|
apiError: 'Invalid login details',
|
|
|
|
}));
|
|
|
|
setPassword('');
|
|
|
|
setUsername('');
|
|
|
|
} else {
|
|
|
|
setErrors({
|
|
|
|
apiError: 'Unknown error while trying to authenticate.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const { usernameError, passwordError, apiError } = errors;
|
|
|
|
const { options = [] } = authDetails;
|
|
|
|
|
|
|
|
return (
|
2021-05-21 14:01:28 +02:00
|
|
|
<>
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={options.length > 0}
|
|
|
|
show={
|
|
|
|
<>
|
|
|
|
<AuthOptions options={options} />
|
|
|
|
<DividerText text="or signin with username" />
|
|
|
|
</>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
|
2021-10-19 13:08:25 +02:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={!authDetails.disableDefault}
|
|
|
|
show={
|
|
|
|
<form onSubmit={handleSubmit} action={authDetails.path}>
|
|
|
|
<Typography
|
|
|
|
variant="subtitle2"
|
|
|
|
className={styles.apiError}
|
|
|
|
>
|
|
|
|
{apiError}
|
|
|
|
</Typography>
|
|
|
|
<div
|
|
|
|
className={classnames(
|
|
|
|
styles.contentContainer,
|
|
|
|
commonStyles.contentSpacingY
|
|
|
|
)}
|
2021-05-21 14:01:28 +02:00
|
|
|
>
|
2021-10-19 13:08:25 +02:00
|
|
|
<TextField
|
|
|
|
label="Username or email"
|
|
|
|
name="username"
|
|
|
|
type="string"
|
|
|
|
onChange={evt => setUsername(evt.target.value)}
|
|
|
|
value={username}
|
|
|
|
error={!!usernameError}
|
|
|
|
helperText={usernameError}
|
|
|
|
variant="outlined"
|
|
|
|
size="small"
|
|
|
|
/>
|
|
|
|
<TextField
|
|
|
|
label="Password"
|
|
|
|
onChange={evt => setPassword(evt.target.value)}
|
|
|
|
name="password"
|
2021-12-30 10:57:35 +01:00
|
|
|
type={showPassword ? 'text' : 'password'}
|
2021-10-19 13:08:25 +02:00
|
|
|
value={password}
|
|
|
|
error={!!passwordError}
|
|
|
|
helperText={passwordError}
|
|
|
|
variant="outlined"
|
|
|
|
size="small"
|
2021-12-30 10:57:35 +01:00
|
|
|
InputProps={{
|
|
|
|
style:{
|
|
|
|
paddingRight: 0
|
|
|
|
},
|
|
|
|
endAdornment: (
|
|
|
|
<InputAdornment position="end">
|
|
|
|
<IconButton
|
|
|
|
aria-label="toggle password visibility"
|
|
|
|
onClick={
|
|
|
|
handleClickShowPassword
|
|
|
|
}
|
|
|
|
onMouseDown={
|
|
|
|
handleMouseDownPassword
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{showPassword ? (
|
|
|
|
<Visibility />
|
|
|
|
) : (
|
|
|
|
<VisibilityOff />
|
|
|
|
)}
|
|
|
|
</IconButton>
|
|
|
|
</InputAdornment>
|
|
|
|
),
|
|
|
|
}}
|
2021-10-19 13:08:25 +02:00
|
|
|
/>
|
|
|
|
<Grid container>
|
|
|
|
<Button
|
|
|
|
variant="contained"
|
|
|
|
color="primary"
|
|
|
|
type="submit"
|
|
|
|
className={styles.button}
|
|
|
|
>
|
|
|
|
Sign in
|
|
|
|
</Button>
|
|
|
|
</Grid>
|
|
|
|
</div>
|
|
|
|
</form>
|
|
|
|
}
|
|
|
|
/>
|
2021-05-21 14:01:28 +02:00
|
|
|
</>
|
2021-04-29 21:55:48 +02:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-05-21 14:01:28 +02:00
|
|
|
HostedAuth.propTypes = {
|
2021-04-29 21:55:48 +02:00
|
|
|
authDetails: PropTypes.object.isRequired,
|
|
|
|
passwordLogin: PropTypes.func.isRequired,
|
|
|
|
history: PropTypes.object.isRequired,
|
|
|
|
};
|
|
|
|
|
2021-05-21 14:01:28 +02:00
|
|
|
export default HostedAuth;
|