|
@@ -1,8 +1,10 @@ |
|
|
import React, { |
|
|
import React, { |
|
|
// useEffect, |
|
|
|
|
|
|
|
|
useEffect, |
|
|
useState} from 'react'; |
|
|
useState} from 'react'; |
|
|
import { Link as RouterLink } from 'react-router-dom'; |
|
|
import { Link as RouterLink } from 'react-router-dom'; |
|
|
import {useNavigate} from 'react-router-dom'; |
|
|
import {useNavigate} from 'react-router-dom'; |
|
|
|
|
|
import {useForm,} from 'react-hook-form' |
|
|
|
|
|
|
|
|
// material-ui |
|
|
// material-ui |
|
|
import { |
|
|
import { |
|
|
Button, |
|
|
Button, |
|
@@ -21,8 +23,8 @@ import { |
|
|
} from '@mui/material'; |
|
|
} from '@mui/material'; |
|
|
|
|
|
|
|
|
// third party |
|
|
// third party |
|
|
import * as Yup from 'yup'; |
|
|
|
|
|
import { Formik } from 'formik'; |
|
|
|
|
|
|
|
|
import * as yup from 'yup'; |
|
|
|
|
|
import { useFormik,FormikProvider } from 'formik'; |
|
|
|
|
|
|
|
|
// project import |
|
|
// project import |
|
|
//import FirebaseSocial from './FirebaseSocial'; |
|
|
//import FirebaseSocial from './FirebaseSocial'; |
|
@@ -48,8 +50,9 @@ const AuthLoginCustom = () => { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// let [posts, setPosts] = useState([]); |
|
|
// let [posts, setPosts] = useState([]); |
|
|
let [userName, setUserName] = useState(null); |
|
|
|
|
|
let [userPassword, setUserPassword] = useState(null); |
|
|
|
|
|
|
|
|
const [isValid, setisValid] = useState(false); |
|
|
|
|
|
const [isSuccess, setSuccess] = useState(); |
|
|
|
|
|
const [isSumitting, setSumitting] = useState(); |
|
|
|
|
|
|
|
|
// useEffect(() => { |
|
|
// useEffect(() => { |
|
|
// // console.log("POST: " + posts.accessToken); |
|
|
// // console.log("POST: " + posts.accessToken); |
|
@@ -60,160 +63,205 @@ const AuthLoginCustom = () => { |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const tryLogin = () => { |
|
|
const tryLogin = () => { |
|
|
useJwt |
|
|
|
|
|
.login({username: userName, password: userPassword}) |
|
|
|
|
|
.then((response) => { |
|
|
|
|
|
const userData = { |
|
|
|
|
|
id: response.data.id, |
|
|
|
|
|
fullName: response.data.name, |
|
|
|
|
|
email: response.data.email, |
|
|
|
|
|
role: response.data.role, |
|
|
|
|
|
abilities: response.data.abilities, |
|
|
|
|
|
//avatar: require('src/assets/images/users/avatar-3.png').default, |
|
|
|
|
|
} |
|
|
|
|
|
const data = {...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken} |
|
|
|
|
|
dispatch(handleLogin(data)) |
|
|
|
|
|
//const abilities = response.data.abilities |
|
|
|
|
|
//ability.update(abilities) |
|
|
|
|
|
navigate('/dashboard'); |
|
|
|
|
|
}) |
|
|
|
|
|
.catch((error) => { |
|
|
|
|
|
console.error(error) |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if(isValid){ |
|
|
|
|
|
setSumitting(true) |
|
|
|
|
|
useJwt |
|
|
|
|
|
.login({username: values.username, password: values.password}) |
|
|
|
|
|
.then((response) => { |
|
|
|
|
|
const userData = { |
|
|
|
|
|
id: response.data.id, |
|
|
|
|
|
fullName: response.data.name, |
|
|
|
|
|
email: response.data.email, |
|
|
|
|
|
role: response.data.role, |
|
|
|
|
|
abilities: response.data.abilities, |
|
|
|
|
|
//avatar: require('src/assets/images/users/avatar-3.png').default, |
|
|
|
|
|
} |
|
|
|
|
|
const data = {...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken} |
|
|
|
|
|
setSuccess(true) |
|
|
|
|
|
dispatch(handleLogin(data)) |
|
|
|
|
|
navigate('/dashboard'); |
|
|
|
|
|
setSumitting(false) |
|
|
|
|
|
console.log(isSuccess) |
|
|
|
|
|
}) |
|
|
|
|
|
.catch((error) => { |
|
|
|
|
|
setSuccess(false) |
|
|
|
|
|
console.error(error) |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const formik = useFormik({ |
|
|
|
|
|
initialValues:({ |
|
|
|
|
|
username: '', |
|
|
|
|
|
password: '', |
|
|
|
|
|
submit: null |
|
|
|
|
|
}), |
|
|
|
|
|
validationSchema:yup.object().shape({ |
|
|
|
|
|
username: yup.string().min(8,'用戶名稱最少8位').required('請輸入用戶名稱'), |
|
|
|
|
|
password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') |
|
|
|
|
|
.matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') |
|
|
|
|
|
.matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') |
|
|
|
|
|
.matches(/^(?=.*[0-9])/, '請包括最少1個數字') |
|
|
|
|
|
.matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), |
|
|
|
|
|
}), |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const checkDataField = (data)=> { |
|
|
|
|
|
if (data.username !==""&& |
|
|
|
|
|
data.password !==""&& |
|
|
|
|
|
handlePassword(data.password)&& |
|
|
|
|
|
handle8Digi(data.username) |
|
|
|
|
|
) |
|
|
|
|
|
{ |
|
|
|
|
|
setisValid(true) |
|
|
|
|
|
return isValid |
|
|
|
|
|
}else{ |
|
|
|
|
|
setisValid(false) |
|
|
|
|
|
return isValid |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
const onUserNameChange = (event) => { |
|
|
|
|
|
setUserName(event.target.value); |
|
|
|
|
|
|
|
|
function handlePassword(password) { |
|
|
|
|
|
let new_pass = password; |
|
|
|
|
|
// regular expressions to validate password |
|
|
|
|
|
var lowerCase = /[a-z]/g; |
|
|
|
|
|
var upperCase = /[A-Z]/g; |
|
|
|
|
|
var numbers = /[0-9]/g; |
|
|
|
|
|
if (!new_pass.match(lowerCase)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} else if (!new_pass.match(upperCase)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} else if (!new_pass.match(numbers)) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} else if (new_pass.length < 8) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} else { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const onPasswordChange = (event) => { |
|
|
|
|
|
setUserPassword(event.target.value); |
|
|
|
|
|
|
|
|
function handle8Digi(value) { |
|
|
|
|
|
if (value.length < 8) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} else { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const { values } = formik |
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
checkDataField(values) |
|
|
|
|
|
}, [values]) |
|
|
|
|
|
|
|
|
|
|
|
const {handleSubmit} = useForm({}) |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<Formik |
|
|
|
|
|
initialValues={{ |
|
|
|
|
|
username: '', |
|
|
|
|
|
password: '', |
|
|
|
|
|
submit: null |
|
|
|
|
|
}} |
|
|
|
|
|
validationSchema={Yup.object().shape({ |
|
|
|
|
|
username: Yup.string().max(255).required('請輸入用戶名稱'), |
|
|
|
|
|
password: Yup.string().max(255).required('請輸入密碼'), |
|
|
|
|
|
})} |
|
|
|
|
|
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => { |
|
|
|
|
|
try { |
|
|
|
|
|
setStatus({ success: false }); |
|
|
|
|
|
setSubmitting(false); |
|
|
|
|
|
} catch (err) { |
|
|
|
|
|
setStatus({ success: false }); |
|
|
|
|
|
setErrors({ submit: err.message }); |
|
|
|
|
|
setSubmitting(false); |
|
|
|
|
|
} |
|
|
|
|
|
}} |
|
|
|
|
|
> |
|
|
|
|
|
{({ errors, handleBlur, handleSubmit, isSubmitting, touched }) => ( |
|
|
|
|
|
<form noValidate onSubmit={handleSubmit}> |
|
|
|
|
|
<Grid container spacing={3}> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack spacing={1}> |
|
|
|
|
|
<InputLabel htmlFor="email-login">用戶帳號或別名</InputLabel> |
|
|
|
|
|
<OutlinedInput |
|
|
|
|
|
id="username" |
|
|
|
|
|
name="username" |
|
|
|
|
|
onBlur={handleBlur} |
|
|
|
|
|
onChange={onUserNameChange} |
|
|
|
|
|
placeholder="" |
|
|
|
|
|
fullWidth |
|
|
|
|
|
error={Boolean(touched.email && errors.email)} |
|
|
|
|
|
/> |
|
|
|
|
|
{touched.email && errors.email && ( |
|
|
|
|
|
<FormHelperText error id="standard-weight-helper-text-email-login"> |
|
|
|
|
|
{errors.email} |
|
|
|
|
|
</FormHelperText> |
|
|
|
|
|
)} |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack spacing={1}> |
|
|
|
|
|
<InputLabel htmlFor="password-login">密碼</InputLabel> |
|
|
|
|
|
<OutlinedInput |
|
|
|
|
|
fullWidth |
|
|
|
|
|
// error={Boolean(touched.password && errors.password)} |
|
|
|
|
|
id="password-login" |
|
|
|
|
|
type={showPassword ? 'text' : 'password'} |
|
|
|
|
|
name="password" |
|
|
|
|
|
// onBlur={handleBlur} |
|
|
|
|
|
onChange={onPasswordChange} |
|
|
|
|
|
endAdornment={ |
|
|
|
|
|
<InputAdornment position="end"> |
|
|
|
|
|
<IconButton |
|
|
|
|
|
aria-label="toggle password visibility" |
|
|
|
|
|
onClick={handleClickShowPassword} |
|
|
|
|
|
onMouseDown={handleMouseDownPassword} |
|
|
|
|
|
edge="end" |
|
|
|
|
|
size="large" |
|
|
|
|
|
> |
|
|
|
|
|
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />} |
|
|
|
|
|
</IconButton> |
|
|
|
|
|
</InputAdornment> |
|
|
|
|
|
} |
|
|
|
|
|
placeholder="" |
|
|
|
|
|
/> |
|
|
|
|
|
{/* {touched.password && errors.password && ( |
|
|
|
|
|
<FormHelperText error id="standard-weight-helper-text-password-login"> |
|
|
|
|
|
{errors.password} |
|
|
|
|
|
</FormHelperText> |
|
|
|
|
|
)} */} |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
|
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<AnimateButton> |
|
|
|
|
|
<Button disableElevation onClick={tryLogin} |
|
|
|
|
|
disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary"> |
|
|
|
|
|
登錄 |
|
|
|
|
|
</Button> |
|
|
|
|
|
</AnimateButton> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Link variant="h6" component={RouterLink} to="" color="text.primary"> |
|
|
|
|
|
<Typography align="center"> |
|
|
|
|
|
忘記密碼? |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Link> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Button fullWidth size="large" variant="outlined" startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}>智方便登入</Button> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Link href="#">了解更多智方便</Link> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Button fullWidth size="large" variant="outlined" href="/register" >建立/重新啟動帳戶</Button> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
{/* <Grid item xs={12}>*/} |
|
|
|
|
|
{/* <Divider>*/} |
|
|
|
|
|
{/* <Typography variant="caption"> Login with</Typography>*/} |
|
|
|
|
|
{/* </Divider>*/} |
|
|
|
|
|
{/*</Grid>*/} |
|
|
|
|
|
{/*<Grid item xs={12}>*/} |
|
|
|
|
|
{/* <FirebaseSocial />*/} |
|
|
|
|
|
{/*</Grid> */} |
|
|
|
|
|
|
|
|
<FormikProvider value={formik}> |
|
|
|
|
|
<form onSubmit={handleSubmit(tryLogin)}> |
|
|
|
|
|
<Grid container spacing={3}> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack spacing={1}> |
|
|
|
|
|
{!isSuccess && isSumitting && ( |
|
|
|
|
|
<FormHelperText error id="standard-weight-helper-text-username-login"> |
|
|
|
|
|
用戶登入名稱或密碼錯誤 |
|
|
|
|
|
</FormHelperText> |
|
|
|
|
|
)} |
|
|
|
|
|
<InputLabel htmlFor="email-login">用戶登入名稱</InputLabel> |
|
|
|
|
|
<OutlinedInput |
|
|
|
|
|
id="username" |
|
|
|
|
|
name="username" |
|
|
|
|
|
onChange={formik.handleChange} |
|
|
|
|
|
placeholder="" |
|
|
|
|
|
fullWidth |
|
|
|
|
|
value={formik.values.username} |
|
|
|
|
|
error={Boolean(formik.touched.username && formik.errors.username)} |
|
|
|
|
|
onBlur={formik.handleBlur} |
|
|
|
|
|
/> |
|
|
|
|
|
{formik.touched.username && formik.errors.username && ( |
|
|
|
|
|
<FormHelperText error id="standard-weight-helper-text-username-login"> |
|
|
|
|
|
{formik.errors.username} |
|
|
|
|
|
</FormHelperText> |
|
|
|
|
|
)} |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack spacing={1}> |
|
|
|
|
|
<InputLabel htmlFor="password-login">密碼</InputLabel> |
|
|
|
|
|
<OutlinedInput |
|
|
|
|
|
fullWidth |
|
|
|
|
|
id="password-login" |
|
|
|
|
|
type={showPassword ? 'text' : 'password'} |
|
|
|
|
|
name="password" |
|
|
|
|
|
value={formik.values.password} |
|
|
|
|
|
onChange={formik.handleChange} |
|
|
|
|
|
onBlur={formik.handleBlur} |
|
|
|
|
|
error={Boolean(formik.touched.password && formik.errors.password)} |
|
|
|
|
|
endAdornment={ |
|
|
|
|
|
<InputAdornment position="end"> |
|
|
|
|
|
<IconButton |
|
|
|
|
|
aria-label="toggle password visibility" |
|
|
|
|
|
onClick={handleClickShowPassword} |
|
|
|
|
|
onMouseDown={handleMouseDownPassword} |
|
|
|
|
|
edge="end" |
|
|
|
|
|
size="large" |
|
|
|
|
|
> |
|
|
|
|
|
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />} |
|
|
|
|
|
</IconButton> |
|
|
|
|
|
</InputAdornment> |
|
|
|
|
|
} |
|
|
|
|
|
placeholder="" |
|
|
|
|
|
/> |
|
|
|
|
|
{formik.touched.password && formik.errors.password && ( |
|
|
|
|
|
<FormHelperText error id="standard-weight-helper-text-password-login"> |
|
|
|
|
|
{formik.errors.password} |
|
|
|
|
|
</FormHelperText> |
|
|
|
|
|
)} |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
|
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<AnimateButton> |
|
|
|
|
|
<Button disableElevation onClick={tryLogin} |
|
|
|
|
|
fullWidth size="large" type="submit" variant="contained" color="primary"> |
|
|
|
|
|
登錄 |
|
|
|
|
|
</Button> |
|
|
|
|
|
</AnimateButton> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Link variant="h6" component={RouterLink} to="" color="text.primary"> |
|
|
|
|
|
<Typography align="center"> |
|
|
|
|
|
忘記密碼? |
|
|
|
|
|
</Typography> |
|
|
|
|
|
</Link> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Button fullWidth size="large" variant="outlined" startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}>智方便登入</Button> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Link href="#">了解更多智方便</Link> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
<Grid item xs={12}> |
|
|
|
|
|
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> |
|
|
|
|
|
<Button fullWidth size="large" variant="outlined" href="/register" >建立/重新啟動帳戶</Button> |
|
|
|
|
|
</Stack> |
|
|
</Grid> |
|
|
</Grid> |
|
|
</form> |
|
|
|
|
|
)} |
|
|
|
|
|
</Formik> |
|
|
|
|
|
|
|
|
{/* <Grid item xs={12}>*/} |
|
|
|
|
|
{/* <Divider>*/} |
|
|
|
|
|
{/* <Typography variant="caption"> Login with</Typography>*/} |
|
|
|
|
|
{/* </Divider>*/} |
|
|
|
|
|
{/*</Grid>*/} |
|
|
|
|
|
{/*<Grid item xs={12}>*/} |
|
|
|
|
|
{/* <FirebaseSocial />*/} |
|
|
|
|
|
{/*</Grid> */} |
|
|
|
|
|
</Grid> |
|
|
|
|
|
</form> |
|
|
|
|
|
</FormikProvider> |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|