src/components/SignIn/index.js
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import { compose } from 'recompose';
import { SignUpLink } from '../SignUp';
import { PasswordForgetLink } from '../PasswordForget';
import { withFirebase } from '../Firebase';
import * as ROUTES from '../../constants/routes';
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 FormControlLabel from '@material-ui/core/FormControlLabel';
import Checkbox from '@material-ui/core/Checkbox';
import Link from '@material-ui/core/Link';
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 { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';
const useStyles = makeStyles(theme => ({
'@global': {
body: {
backgroundColor: theme.palette.common.white,
},
},
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
submit: {
margin: theme.spacing(1, 0, 0),
},
}));
const POST_LOGIN_ROUTE = ROUTES.ACCOUNTS;
function Copyright() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
<Link color="inherit" href="https://material-ui.com/">
Jelly Fin
</Link>{' '}
{new Date().getFullYear()}
{'.'}
</Typography>
);
}
const SignInPage = () => {
const classes = useStyles();
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<SignInForm classes={classes} />
<SignInGoogle classes={classes} />
<SignInFacebook classes={classes} />
<SignInTwitter classes={classes} />
<Grid container>
<Grid item xs>
<PasswordForgetLink />
</Grid>
<Grid item>
<SignUpLink />
</Grid>
</Grid>
</div>
<Box mt={8}>
<Copyright />
</Box>
</Container>
);
};
const INITIAL_STATE = {
email: '',
password: '',
error: null,
};
const ERROR_CODE_ACCOUNT_EXISTS =
'auth/account-exists-with-different-credential';
const ERROR_MSG_ACCOUNT_EXISTS = `
An account with an E-Mail address to
this social account already exists. Try to login from
this account instead and associate your social accounts on
your personal account page.
`;
class SignInFormBase extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
}
onSubmit = event => {
const { email, password } = this.state;
this.props.firebase
.doSignInWithEmailAndPassword(email, password)
.then(() => {
this.setState({ ...INITIAL_STATE });
this.props.history.push(POST_LOGIN_ROUTE);
})
.catch(error => {
this.setState({ error });
});
event.preventDefault();
};
onChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
const { email, password } = this.state;
const isInvalid = password === '' || email === '';
const classes = this.props.classes;
return (
<form
className={classes.form}
onSubmit={this.onSubmit}
noValidate
>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
value={email}
onChange={this.onChange}
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
value={password}
onChange={this.onChange}
name="password"
label="Password"
type="password"
id="password"
autoComplete="current-password"
/>
<FormControlLabel
control={<Checkbox value="remember" color="primary" />}
label="Remember me"
/>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled={isInvalid}
>
Sign In
</Button>
</form>
);
}
}
class SignInGoogleBase extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
onSubmit = event => {
this.props.firebase
.doSignInWithGoogle()
.then(socialAuthUser => {
// Create a user in your Firebase Realtime Database too
return this.props.firebase.user(socialAuthUser.user.uid).set(
{
username: socialAuthUser.user.displayName,
email: socialAuthUser.user.email,
roles: {},
},
{ merge: true },
);
})
.then(() => {
this.setState({ error: null });
this.props.history.push(POST_LOGIN_ROUTE);
})
.catch(error => {
if (error.code === ERROR_CODE_ACCOUNT_EXISTS) {
error.message = ERROR_MSG_ACCOUNT_EXISTS;
}
this.setState({ error });
});
event.preventDefault();
};
render() {
const { error } = this.state;
const classes = this.props.classes;
return (
<form onSubmit={this.onSubmit}>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
>
Sign In with Google
</Button>
{error && <p>{error.message}</p>}
</form>
);
}
}
class SignInFacebookBase extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
onSubmit = event => {
this.props.firebase
.doSignInWithFacebook()
.then(socialAuthUser => {
// Create a user in your Firebase Realtime Database too
return this.props.firebase.user(socialAuthUser.user.uid).set(
{
username: socialAuthUser.additionalUserInfo.profile.name,
email: socialAuthUser.additionalUserInfo.profile.email,
roles: {},
},
{ merge: true },
);
})
.then(() => {
this.setState({ error: null });
this.props.history.push(POST_LOGIN_ROUTE);
})
.catch(error => {
if (error.code === ERROR_CODE_ACCOUNT_EXISTS) {
error.message = ERROR_MSG_ACCOUNT_EXISTS;
}
this.setState({ error });
});
event.preventDefault();
};
render() {
const { error } = this.state;
const classes = this.props.classes;
return (
<form onSubmit={this.onSubmit}>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled
>
Sign In with Facebook
</Button>
{error && <p>{error.message}</p>}
</form>
);
}
}
class SignInTwitterBase extends Component {
constructor(props) {
super(props);
this.state = { error: null };
}
onSubmit = event => {
this.props.firebase
.doSignInWithTwitter()
.then(socialAuthUser => {
// Create a user in your Firebase Realtime Database too
return this.props.firebase.user(socialAuthUser.user.uid).set(
{
username: socialAuthUser.additionalUserInfo.profile.name,
email: socialAuthUser.additionalUserInfo.profile.email,
roles: {},
},
{ merge: true },
);
})
.then(() => {
this.setState({ error: null });
this.props.history.push(POST_LOGIN_ROUTE);
})
.catch(error => {
if (error.code === ERROR_CODE_ACCOUNT_EXISTS) {
error.message = ERROR_MSG_ACCOUNT_EXISTS;
}
this.setState({ error });
});
event.preventDefault();
};
render() {
const { error } = this.state;
const classes = this.props.classes;
return (
<form onSubmit={this.onSubmit}>
<Button
type="submit"
fullWidth
variant="contained"
color="primary"
className={classes.submit}
disabled
>
Sign In with Twitter
</Button>
{error && <p>{error.message}</p>}
</form>
);
}
}
const SignInForm = compose(
withRouter,
withFirebase,
)(SignInFormBase);
const SignInGoogle = compose(
withRouter,
withFirebase,
)(SignInGoogleBase);
const SignInFacebook = compose(
withRouter,
withFirebase,
)(SignInFacebookBase);
const SignInTwitter = compose(
withRouter,
withFirebase,
)(SignInTwitterBase);
export default SignInPage;
export { SignInForm, SignInGoogle, SignInFacebook, SignInTwitter };