Last active
October 18, 2020 08:00
-
-
Save jhidajat/06ccccd4f38a2c5d5046dbc8e4016fb6 to your computer and use it in GitHub Desktop.
Sign In / Sign Up Template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as firebase from 'firebase/app' | |
import 'firebase/auth' | |
import { | |
FIREBASE_APIKEY, | |
FIREBASE_APPID, | |
FIREBASE_AUTHDOMAIN, | |
FIREBASE_DATABASEURL, | |
FIREBASE_MEASUREMENTID, | |
FIREBASE_MESSAGINGSENDERID, | |
FIREBASE_PROJECTID, | |
FIREBASE_STORAGEBUCKET, | |
} from '../constants' | |
const firebaseConfig = { | |
apiKey: FIREBASE_APIKEY, | |
authDomain: FIREBASE_AUTHDOMAIN, | |
databaseURL: FIREBASE_DATABASEURL, | |
projectId: FIREBASE_PROJECTID, | |
storageBucket: FIREBASE_STORAGEBUCKET, | |
messagingSenderId: FIREBASE_MESSAGINGSENDERID, | |
appId: FIREBASE_APPID, | |
measurementId: FIREBASE_MEASUREMENTID, | |
} | |
firebase.initializeApp(firebaseConfig) | |
export default firebase |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useCallback, useEffect, useState } from 'react'; | |
import { useHistory, withRouter } from "react-router-dom"; | |
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 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'; | |
import { FacebookLoginButton } from "react-social-login-buttons"; | |
import firebase from "../utils/firebase"; | |
import Routes from "../constants/routes"; | |
import api from "../api" | |
const useStyles = makeStyles(theme => ({ | |
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(3), | |
}, | |
submit: { | |
margin: theme.spacing(3, 0, 2), | |
}, | |
or: { | |
width: '100%', | |
display: 'flex', | |
justifyContent: 'center', | |
alignItems: 'center', | |
marginBottom: 12, | |
}, | |
github: { | |
width: '100% !important', | |
margin: '0 !important', | |
}, | |
githubText: { | |
fontSize: '14px !important', | |
fontWeight: 'bold', | |
justifyContent: 'center', | |
} | |
})); | |
const SignIn = () => { | |
const classes = useStyles(); | |
const history = useHistory(); | |
const [userCredential, setUserCredential] = useState({ | |
email: '', | |
password: '', | |
}) | |
useEffect(() => { | |
firebase.auth().onAuthStateChanged(user => { | |
if (user) { | |
// user signed in | |
} else { | |
// user not signed in | |
} | |
}) | |
}, []) | |
const handleChange = useCallback(e => { | |
const name = e.target.name; | |
const value = e.target.value; | |
setUserCredential(cred => ({ ...cred, [name]: value })) | |
}, []) | |
const setAPIToToken = useCallback( | |
async fb => { | |
const idToken = await fb.user.getIdToken() | |
if (!idToken) { | |
console.warn('[Firebase error]: idToken is not provided') | |
return | |
} | |
api.setToken(idToken) | |
}, | |
[], | |
) | |
const handleSignUpWithFacebook = useCallback(async () => { | |
const provider = new firebase.auth.FacebookAuthProvider() | |
try { | |
const currentUser = await firebase.auth().currentUser | |
const res = currentUser | |
? await currentUser.linkWithPopup(provider) | |
: await firebase.auth().signInWithPopup(provider) | |
await setAPIToToken(res) | |
if (!currentUser) { | |
const firebaseUser = res.user | |
console.log('firebaseUser: ', firebaseUser) | |
} else { | |
// maybe get user through API | |
} | |
} catch (err) { | |
// error handling | |
console.error(err) | |
} | |
}, [setAPIToToken]) | |
const handleSubmit = useCallback( | |
async e => { | |
e.preventDefault() | |
const { email, password } = userCredential | |
try { | |
const res = await firebase | |
.auth() | |
.signInWithEmailAndPassword(email, password) | |
await setAPIToToken(res) | |
history.push("/dashboard"); | |
} catch (e) { | |
// error handling | |
console.error(e) | |
} | |
}, | |
[setAPIToToken, userCredential, history], | |
) | |
return ( | |
<Container component="main" maxWidth="xs"> | |
<CssBaseline /> | |
<div className={classes.paper}> | |
<Avatar className={classes.avatar}> | |
<LockOutlinedIcon /> | |
</Avatar> | |
<Typography component="h1" variant="h5"> | |
Log In | |
</Typography> | |
<form className={classes.form} noValidate autoComplete="off" onSubmit={handleSubmit}> | |
<Grid container spacing={2}> | |
<Grid item xs={12}> | |
<TextField | |
variant="outlined" | |
required | |
fullWidth | |
id="email" | |
label="Email Address" | |
name="email" | |
value={userCredential.email} | |
autoComplete="email" | |
onChange={handleChange} | |
/> | |
</Grid> | |
<Grid item xs={12}> | |
<TextField | |
variant="outlined" | |
required | |
fullWidth | |
name="password" | |
label="Password" | |
type="password" | |
id="password" | |
value={userCredential.password} | |
autoComplete="current-password" | |
onChange={handleChange} | |
/> | |
</Grid> | |
</Grid> | |
<Button | |
type="submit" | |
fullWidth | |
variant="contained" | |
color="primary" | |
className={classes.submit} | |
> | |
Signin | |
</Button> | |
<Grid item xs={12}> | |
<div className={classes.or}>or</div> | |
</Grid> | |
</form> | |
<Grid container spacing={2}> | |
<Grid item xs={12}> | |
<FacebookLoginButton | |
className={classes.github} | |
onClick={handleSignUpWithFacebook}> | |
<span className={classes.githubText}>Sign in with Facebook</span> | |
</FacebookLoginButton> | |
</Grid> | |
<Grid container justify="flex-end"> | |
<Grid item> | |
<Link href={Routes.SIGN_UP} variant="body2"> | |
Don't have an account? Sign up | |
</Link> | |
</Grid> | |
</Grid> | |
</Grid> | |
</div> | |
</Container> | |
); | |
} | |
export default withRouter(SignIn); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useCallback, useEffect, useState } from 'react'; | |
import { withRouter, useHistory } from "react-router-dom"; | |
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 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'; | |
import { FacebookLoginButton } from "react-social-login-buttons"; | |
import firebase from "../utils/firebase"; | |
import Routes from "../constants/routes" | |
import api from "../api" | |
import { API_URL } from "../constants"; | |
const useStyles = makeStyles(theme => ({ | |
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(3), | |
}, | |
submit: { | |
margin: theme.spacing(3, 0, 2), | |
}, | |
or: { | |
width: '100%', | |
display: 'flex', | |
justifyContent: 'center', | |
alignItems: 'center', | |
marginBottom: 12, | |
}, | |
github: { | |
width: '100% !important', | |
margin: '0 !important', | |
}, | |
githubText: { | |
fontSize: '14px !important', | |
fontWeight: 'bold', | |
justifyContent: 'center', | |
} | |
})); | |
const SignUp = () => { | |
const classes = useStyles(); | |
const history = useHistory(); | |
const [state, setState] = useState({ | |
email: '', | |
password: '', | |
}) | |
useEffect(() => { | |
firebase.auth().onAuthStateChanged(user => { | |
if (user) { | |
// user signed in | |
} else { | |
// user not signed in | |
} | |
}) | |
}, []) | |
const handleChange = useCallback(e => { | |
const name = e.target.name; | |
const value = e.target.value; | |
setState(s => ({ ...s, [name]: value })) | |
}, []) | |
const createUser = useCallback( | |
async params => { | |
return await api.post(`${API_URL}/api/users`, params) | |
}, | |
[], | |
) | |
const setAPIToToken = useCallback( | |
async fb => { | |
const idToken = await fb.user.getIdToken() | |
if (!idToken) { | |
console.warn('[Firebase error]: idToken is not provided') | |
return | |
} | |
api.setToken(idToken) | |
}, | |
[], | |
) | |
const handleSignUpWithFacebook = useCallback(async () => { | |
const provider = new firebase.auth.FacebookAuthProvider() | |
try { | |
const currentUser = await firebase.auth().currentUser | |
const res = currentUser | |
? await currentUser.linkWithPopup(provider) | |
: await firebase.auth().signInWithPopup(provider) | |
await setAPIToToken(res) | |
if (!currentUser) { | |
const firebaseUser = res.user | |
const user = await createUser({ | |
email: firebaseUser.email, | |
uuid: firebaseUser.uid, | |
}) | |
console.log(user); | |
} else { | |
// maybe get user through API | |
} | |
} catch (err) { | |
// error handling | |
console.error(err) | |
} | |
}, [createUser, setAPIToToken]) | |
const handleSubmit = useCallback( | |
async e => { | |
e.preventDefault() | |
const { email, password } = state | |
try { | |
const res = await firebase | |
.auth() | |
.createUserWithEmailAndPassword(email, password) | |
await setAPIToToken(res) | |
const firebaseUser = res.user | |
const user = await createUser({ | |
email: firebaseUser.email, | |
uuid: firebaseUser.uid, | |
}) | |
console.log(user); | |
history.push(Routes.ONBOARDING); | |
} catch (e) { | |
// error handling | |
console.error(e) | |
} | |
}, | |
[createUser, setAPIToToken, state, history], | |
) | |
return ( | |
<Container component="main" maxWidth="xs"> | |
<CssBaseline /> | |
<div className={classes.paper}> | |
<Avatar className={classes.avatar}> | |
<LockOutlinedIcon /> | |
</Avatar> | |
<Typography component="h1" variant="h5"> | |
Sign up | |
</Typography> | |
<form className={classes.form} noValidate autoComplete="off" onSubmit={handleSubmit}> | |
<Grid container spacing={2}> | |
<Grid item xs={12}> | |
<TextField | |
variant="outlined" | |
required | |
fullWidth | |
id="email" | |
label="Email Address" | |
name="email" | |
value={state.email} | |
autoComplete="email" | |
onChange={handleChange} | |
/> | |
</Grid> | |
<Grid item xs={12}> | |
<TextField | |
variant="outlined" | |
required | |
fullWidth | |
name="password" | |
label="Password" | |
type="password" | |
id="password" | |
value={state.password} | |
autoComplete="current-password" | |
onChange={handleChange} | |
/> | |
</Grid> | |
</Grid> | |
<Button | |
type="submit" | |
fullWidth | |
variant="contained" | |
color="primary" | |
className={classes.submit} | |
> | |
Sign Up | |
</Button> | |
<Grid item xs={12}> | |
<div className={classes.or}>or</div> | |
</Grid> | |
</form> | |
<Grid container spacing={2}> | |
<Grid item xs={12}> | |
<FacebookLoginButton | |
className={classes.github} | |
onClick={handleSignUpWithFacebook}> | |
<span className={classes.githubText}>Sign up with Facebook</span> | |
</FacebookLoginButton> | |
</Grid> | |
<Grid container justify="flex-end"> | |
<Grid item> | |
<Link href={Routes.SIGN_IN} variant="body2"> | |
Already have an account? Sign in | |
</Link> | |
</Grid> | |
</Grid> | |
</Grid> | |
</div> | |
</Container> | |
); | |
} | |
export default withRouter(SignUp); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment