Created
August 13, 2019 14:14
-
-
Save krnbr/eee5b45275ed53e9657b6041015de30b to your computer and use it in GitHub Desktop.
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, {useEffect, useLayoutEffect, useRef, useState} from 'react'; | |
import {Button,CircularProgress,CssBaseline,TextField,Grid,Container,Theme,makeStyles,Box,FormHelperText,SnackbarContent,Snackbar,Icon,IconButton} from '@material-ui/core'; | |
/*import Link from '@material-ui/core/Link';*/ | |
/*import {makeStyles} from '@material-ui/core/styles';*/ | |
import defaultTheme from '../src/theme'; | |
import {ThemeProvider} from '@material-ui/styles'; | |
import Logo from "../src/components/logo"; | |
import {PasswordDto, RecaptchaDto, SignInDto, UserDto} from "../models/SignInDto"; | |
import {NextPage} from "next"; | |
import '../styles/signin.scss'; | |
import Link from 'next/link'; | |
import ReCAPTCHA from "react-google-recaptcha"; | |
import Router from 'next/router' | |
import clsx from 'clsx'; | |
import CloseIcon from '@material-ui/icons/Close'; | |
const useStyles = makeStyles((theme: Theme) => { | |
return { | |
body: { | |
backgroundImage: "url('/static/images/escheresque.png')", | |
backgroundRepeat:'repeat' | |
}, | |
paper: { | |
marginTop: theme.spacing(8), | |
display: 'flex', | |
flexDirection: 'column', | |
alignItems: 'center', | |
}, | |
avatar: { | |
margin: theme.spacing(1), | |
backgroundColor: defaultTheme.palette.secondary.main ? defaultTheme.palette.secondary.main : theme.palette.secondary.main, | |
}, | |
form: { | |
width: '100%', // Fix IE 11 issue. | |
marginTop: theme.spacing(1), | |
}, | |
submit: { | |
margin: theme.spacing(3, 0, 2), | |
}, | |
icon: { | |
fontSize: 20, | |
}, | |
iconVariant: { | |
opacity: 0.9, | |
marginRight: theme.spacing(1), | |
}, | |
error: { | |
backgroundColor: "#ff6e63", | |
}, | |
message: { | |
display: 'flex', | |
alignItems: 'center', | |
}, | |
}; | |
}); | |
let signInDto: SignInDto = new SignInDto(); | |
let userDto: UserDto = signInDto.username; | |
let passwordDto: PasswordDto = signInDto.password; | |
let recaptcha: RecaptchaDto = signInDto.recaptcha; | |
const useIsomorphicLayoutEffect = | |
typeof window !== 'undefined' ? useLayoutEffect : useEffect; | |
const Login: NextPage = (props:any) => { | |
const usernameInputRef = useRef({value:""}); | |
const passwordInputRef = useRef({value:""}); | |
const recaptchaInputRef:any = useRef({}); | |
const [formData, setFormData] = useState<SignInDto>(signInDto); | |
const [loading, setLoading] = useState(false); | |
const [open, setOpen] = useState(false); | |
useIsomorphicLayoutEffect(()=> { | |
document!.body.classList.add('signin'); | |
console.log('I am about to render signin page!'); | |
setFormData({...signInDto}); | |
},[]); | |
useEffect(() => { | |
return () => { | |
document!.body.classList.remove('signin'); | |
console.log('will unmount signin page!'); | |
} | |
}, []); | |
function handleClose(event, reason) { | |
setOpen(false); | |
} | |
// React.SyntheticEvent | |
const handleSubmit = async (event) => { | |
if (event) event.preventDefault(); | |
usernameValueCheck(usernameInputRef.current!.value); | |
passwordValueCheck(passwordInputRef.current!.value); | |
console.log("recaptchaInputRef.current!.value "+ recaptchaInputRef.current.getValue()); | |
recaptchaValueCheck(recaptchaInputRef.current.getValue()); | |
if(formData.username.valid && formData.password.valid && formData.recaptcha.valid){ | |
setLoading(true); | |
// TODO fetch | |
console.log("requesting "); | |
console.log(recaptchaInputRef.current.getValue()); | |
console.log("requesting ---"); | |
const response = await fetch("/sign-in", { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ | |
username:usernameInputRef.current!.value, | |
password:passwordInputRef.current!.value, | |
recaptchaResponse:recaptchaInputRef.current.getValue(), | |
}) | |
}); | |
if(response.ok) { | |
const json = await response.json(); | |
console.log("response " + JSON.stringify(json)); | |
setLoading(false); | |
// TODO redirect appropriate | |
Router.push('/'); | |
} else { | |
const json = await response.json(); | |
console.log("error response " + JSON.stringify(json)); | |
setLoading(false); | |
setOpen(true); | |
recaptchaInputRef.current.reset(); | |
} | |
} | |
/*setIsSubmitting(true); | |
setErrors(validate(values));*/ | |
}; | |
const onChange = (value) => { | |
console.log("Captcha value:", value); | |
recaptchaValueCheck(value); | |
} | |
const onExpired = () => { | |
console.log("Captcha expired value:", recaptchaInputRef.current.getValue()); | |
recaptchaValueCheck(recaptchaInputRef.current.getValue()); | |
} | |
const handleChange = (event) => { | |
if (event) event.preventDefault(); | |
console.log("val of " + JSON.stringify(event.target.id)); | |
if (event.target.id === formData.username.id) { | |
if (event.target.value.match("^[a-zA-Z0-9]+$")) { | |
console.log('username changed value'); | |
userDto.valid = true; | |
} else { | |
console.log('username changed value and doesnot matches!!'); | |
userDto.valid = false; | |
} | |
userDto.value = event.target.value; | |
setFormData({ | |
...signInDto, | |
username: userDto | |
}); | |
//setFormData(signInDto); | |
} else if (event.target.id === formData.password.id) { | |
passwordValueCheck(event.target.value); | |
} | |
}; | |
const usernameOnFocus = (event) => { | |
usernameValueCheck(event.target.value); | |
} | |
const usernameValueCheck = (value) => { | |
if (value.match("^[a-zA-Z0-9]+$")) { | |
console.log('username changed value'); | |
userDto.valid = true; | |
} else { | |
console.log('username changed value and doesnot matches!!'); | |
userDto.valid = false; | |
} | |
userDto.value = value; | |
setFormData({ | |
...signInDto, | |
username: userDto | |
}); | |
} | |
const passwordOnFocus = (event) => { | |
passwordValueCheck(event.target.value); | |
} | |
const passwordValueCheck = (value) => { | |
if (value && (value !== null || value !== "")) { | |
console.log('password changed value'); | |
passwordDto.valid = true; | |
} else { | |
console.log('password changed value and does not matches!!'); | |
passwordDto.valid = false; | |
} | |
passwordDto.value = value; | |
setFormData({ | |
...signInDto, | |
password: passwordDto | |
}); | |
} | |
const recaptchaValueCheck = (value) => { | |
if (value && (value !== null || value.trim() !== "")) { | |
console.log('recaptcha changed value'); | |
recaptcha.valid = true; | |
} else { | |
console.log('recaptcha changed value and does not matches!!'); | |
recaptcha.valid = false; | |
} | |
recaptcha.value = value; | |
setFormData({ | |
...signInDto, | |
recaptcha: recaptcha | |
}); | |
} | |
const classes = useStyles(props); | |
return ( | |
<React.Fragment> | |
<div id="color-overlay"></div> | |
<Container component="main" maxWidth="xs"> | |
{/*<Logo style={{marginTop: 50, marginBottom: -20, marginLeft: "auto", marginRight: "auto", display: "block"}}/>*/} | |
<Box boxShadow={3} padding="25px" marginTop="15px" height="100%" bgcolor={"#e8e8e8"}> | |
<CssBaseline/> | |
<Logo style={{ | |
marginTop: 20, | |
marginBottom: -45, | |
marginLeft: "auto", | |
marginRight: "auto", | |
display: "block" | |
}}/> | |
{/*<Typography component="h1" variant="h5"> | |
Sign in | |
</Typography>*/} | |
<div className={classes.paper}> | |
<form className={classes.form} noValidate autoComplete="none" onSubmit={e => handleSubmit(e)}> | |
<input autoComplete="false" name="hidden" type="text" style={{display: 'none'}}/> | |
<ThemeProvider theme={defaultTheme}> | |
<TextField | |
margin="normal" | |
required | |
fullWidth | |
id="username" | |
label="Username" | |
name="username" | |
autoComplete="off" | |
autoFocus | |
/*onFocus={e => usernameOnFocus(e)}*/ | |
onChange={e => handleChange(e)} | |
error={!formData.username.valid} | |
helperText={ | |
!formData.username.valid ? | |
formData.username.requiredMessage : '' | |
} | |
inputRef={usernameInputRef} | |
/> | |
<TextField | |
margin="normal" | |
required | |
fullWidth | |
name="password" | |
label="Password" | |
type="password" | |
id="password" | |
autoComplete="current-password" | |
onChange={e => handleChange(e)} | |
onFocus={e => passwordOnFocus(e)} | |
error={!formData.password.valid} | |
helperText={ | |
!formData.password.valid ? | |
formData.password.requiredMessage : '' | |
} | |
inputRef={passwordInputRef} | |
/> | |
{/*not required as not going to support now*/} | |
{/*<FormControlLabel | |
control={<Checkbox value="remember" color="primary"/>} | |
label="Remember me" | |
color="#0099f8" | |
style={{marginTop: 20}} | |
/>*/} | |
<div id={"captchaContainer"} style={ | |
{ | |
display:"table", | |
margin: "0 auto", | |
marginTop:25, | |
marginBottom: 15, | |
position:'relative', | |
} | |
}> | |
<ReCAPTCHA | |
ref={recaptchaInputRef} | |
sitekey={props.recaptchaKey} | |
onChange={ onChange } | |
onExpired={ onExpired } | |
/> | |
{ | |
!formData.recaptcha.valid? | |
<FormHelperText error={true} > {/*style={{display:'contents', position:'absolute'}}*/} | |
Human verification required | |
</FormHelperText>:'' | |
} | |
</div> | |
<div> | |
{/*<Snackbar open={true}> | |
<SnackbarContent color={"red"} message={"Unable to signin with provided credentials!!"}> | |
</SnackbarContent> | |
</Snackbar>*/} | |
{/*<Snackbar | |
open={open} | |
onClose={handleClose} | |
anchorOrigin={{ | |
vertical: 'bottom', | |
horizontal: 'left', | |
}} | |
autoHideDuration={20000} | |
>*/} | |
{ open && | |
<SnackbarContent | |
className={classes.error} | |
aria-describedby="client-snackbar" | |
message={ | |
<span id="client-snackbar" className={classes.message}> | |
<Icon className={clsx(classes.icon, classes.iconVariant)} /> | |
{"Wrong credentials!!"} | |
</span> | |
} | |
action={[ | |
<IconButton key="close" aria-label="close" color="inherit" onClick={(e)=>handleClose(e,'')} > | |
<CloseIcon className={classes.icon} /> | |
</IconButton>, | |
]} | |
/> | |
} | |
{/*</Snackbar>*/} | |
</div> | |
<div style={{position:'relative'}}> | |
<Button | |
type="submit" | |
fullWidth | |
variant="contained" | |
color="secondary" | |
className={classes.submit} | |
style={{marginTop: 30}} | |
disabled={loading} | |
> | |
Sign In | |
</Button> | |
{ loading && <CircularProgress size={24} className="circularProgressButton" color="primary" />} | |
</div> | |
</ThemeProvider> | |
<Grid container> | |
<Grid item xs> | |
{/*<Link href="" variant="body2"> | |
Forgot password? | |
</Link>*/} | |
<Link href="/" as={`/`}> | |
<a className={"anchor"}>Forgot password?</a> | |
</Link> | |
</Grid> | |
<Grid item> | |
{/*<mLink href="" variant="body2"> | |
{"Don't have an account? Sign Up"} | |
</mLink>*/} | |
<Link href={{pathname: '/register', query: {recaptchaKey: props.recaptchaKey}}} as="/register"> | |
<a className={"anchor"}>Don't have an account? Sign Up</a> | |
</Link> | |
</Grid> | |
</Grid> | |
</form> | |
</div> | |
</Box> | |
</Container> | |
</React.Fragment> | |
); | |
}; | |
Login.getInitialProps = async function(context) { | |
const { recaptchaKey } = context.query; | |
return { recaptchaKey }; | |
}; | |
export default Login; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment