You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

459 lines
26 KiB

  1. import { useFormik } from 'formik';
  2. import * as yup from 'yup';
  3. import * as React from "react";
  4. import * as HttpUtils from "utils/HttpUtils";
  5. import * as UrlUtils from "utils/ApiPathConst";
  6. import { useNavigate } from "react-router-dom";
  7. import { useDispatch } from "react-redux";
  8. import { handleLogoutFunction,
  9. // handleLogin
  10. } from 'auth/index';
  11. import useJwt from "auth/jwt/useJwt";
  12. import {
  13. Grid,
  14. Typography,
  15. Button,
  16. // RadioGroup,
  17. // Dialog, DialogTitle, DialogContent, DialogActions,
  18. Stack,
  19. InputLabel,
  20. // OutlinedInput,
  21. FormHelperText,
  22. TextField,
  23. IconButton, InputAdornment,
  24. // Box,
  25. // FormControl
  26. } from '@mui/material';
  27. import Loadable from 'components/Loadable';
  28. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  29. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  30. // import ForwardIcon from '@mui/icons-material/Forward';
  31. import MainCard from 'components/MainCard';
  32. import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
  33. import {ThemeProvider} from "@emotion/react";
  34. import {FormattedMessage, useIntl} from "react-intl";
  35. import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
  36. import axios from 'axios';
  37. import { useParams,Link } from 'react-router-dom';
  38. import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
  39. // import LocaleContext from "components/I18nProvider";
  40. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  41. const Index = () => {
  42. const dispatch = useDispatch()
  43. const navigate = useNavigate()
  44. const [showPassword, setShowPassword] = React.useState(false);
  45. const [showConfirmPassword, setshowConfirmPassword] = React.useState(false);
  46. const [isLoading, setLoding] = React.useState(true);
  47. const [verifyState, setVerifyState] = React.useState(null)
  48. const [enterUseEffect, setEnterUseEffect] = React.useState(false)
  49. const [username, setUsername] = React.useState("")
  50. // const { setLocale } = React.useContext(LocaleContext);
  51. const params = useParams()
  52. const intl = useIntl();
  53. React.useEffect(() => {
  54. console.log(params);
  55. setEnterUseEffect(true)
  56. }, []);
  57. React.useEffect(() => {
  58. // console.log("if (enterUseEffect) handleVerify()");
  59. if (enterUseEffect){
  60. handleVerify()
  61. }
  62. }, [enterUseEffect])
  63. const handleVerify = async () => {
  64. console.log(params);
  65. await axios.get(UrlUtils.GET_FORGOT_PASSWORD_VERIFY_USER_ACCOUNT, {
  66. params: {
  67. email: decodeURIComponent(params.email),
  68. emailVerifyHash: decodeURIComponent(params.verifyCode)
  69. }
  70. }).then(
  71. (response)=>{
  72. if (response.status === 200 && response.data) {
  73. console.log(response)
  74. setUsername(response.data.username)
  75. setVerifyState(true)
  76. } else {
  77. setVerifyState(false)
  78. }
  79. setLoding(false)
  80. }
  81. ).catch(error => {
  82. console.log(error)
  83. setVerifyState(false)
  84. setLoding(false)
  85. });
  86. }
  87. const goLogin = async (values) =>{
  88. dispatch(handleLogoutFunction());
  89. HttpUtils.post({
  90. url: UrlUtils.POST_FORGOT_PASSWORD_NEW_PASSWORD,
  91. params:{
  92. username: username,
  93. newPassword: values.password
  94. },
  95. onSuccess: () => {
  96. useJwt
  97. .login({ username: username, password: values.password })
  98. .then((
  99. // response
  100. ) => {
  101. // console.log(response)
  102. navigate('/forgot/password/success');
  103. location.reload()
  104. // setSumitting(false)
  105. })
  106. .catch((error) => {
  107. console.error(error)
  108. });
  109. },
  110. onFail: (response)=>{
  111. console.log("Fail");
  112. console.log(response);
  113. // window.location.assign("/iamsmart/loginFail");
  114. },
  115. onError:(error)=>{
  116. console.log(error);
  117. // window.location.assign("/iamsmart/loginFail");
  118. }
  119. });
  120. }
  121. const BackgroundHead = {
  122. backgroundImage: `url(${titleBackgroundImg})`,
  123. width: 'auto',
  124. height: 'auto',
  125. backgroundSize: 'contain',
  126. backgroundRepeat: 'no-repeat',
  127. backgroundColor: '#0C489E',
  128. backgroundPosition: 'right'
  129. }
  130. const handleClickShowPassword = () => {
  131. setShowPassword(!showPassword);
  132. };
  133. const handleClickShowConfirmPassword = () => {
  134. setshowConfirmPassword(!showConfirmPassword);
  135. };
  136. const handleMouseDownPassword = (event) => {
  137. event.preventDefault();
  138. };
  139. const changePassword = (
  140. // value
  141. ) => {
  142. // const temp = strengthIndicator(value);
  143. // setLevel(strengthColorChi(temp));
  144. };
  145. const formik = useFormik({
  146. enableReinitialize: true,
  147. initialValues: {
  148. // username: '',
  149. password: '',
  150. confirmPassword: '',
  151. // emailVerifyHash: '',
  152. },
  153. validationSchema: yup.object().shape({
  154. // emailVerifyHash: yup.string().required(intl.formatMessage({id: 'requireSecurityCode'})),
  155. // username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
  156. password: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  157. .required(intl.formatMessage({id: 'requirePassword'}))
  158. .matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
  159. .matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
  160. .matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
  161. .matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
  162. .matches(/^(?=.*[!@#%&])/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
  163. confirmPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  164. .required(intl.formatMessage({id: 'pleaseConfirmPassword'}))
  165. .oneOf([yup.ref('password'), null], intl.formatMessage({id: 'samePassword'})),
  166. }),
  167. onSubmit: values => {
  168. // console.log(values)
  169. goLogin(values)
  170. }
  171. });
  172. return (
  173. isLoading || verifyState == null ?
  174. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
  175. <Grid item>
  176. <LoadingComponent />
  177. </Grid>
  178. </Grid>
  179. :
  180. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" alignItems="center">
  181. <Grid item xs={12} md={12} width="100%" >
  182. <div style={BackgroundHead}>
  183. <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
  184. <Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
  185. <FormattedMessage id="forgotUserPassword"/>
  186. </Typography>
  187. </Stack>
  188. </div>
  189. </Grid>
  190. {/* <Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
  191. <Button
  192. aria-label={intl.formatMessage({id: 'back'})}
  193. title={intl.formatMessage({id: 'back'})}
  194. sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
  195. >
  196. <ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
  197. </Button>
  198. </Grid> */}
  199. {/* <Grid item xs={12}>
  200. <Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
  201. </Grid> */}
  202. <Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
  203. <MainCard
  204. sx={{
  205. maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
  206. margin: { sm: 0, md: 3 },
  207. '& > *': {
  208. flexGrow: 1,
  209. flexBasis: '50%'
  210. }
  211. }}
  212. content={false}
  213. border={false}
  214. boxShadow
  215. >
  216. <form onSubmit={formik.handleSubmit}>
  217. {verifyState ?
  218. // SUCCESS page
  219. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  220. <Grid container direction="column" alignItems="center">
  221. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
  222. <Typography display="inline" variant="h4">
  223. <FormattedMessage id="verifySuccess"/>
  224. </Typography>
  225. </Grid>
  226. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1,}}>
  227. <InputLabel htmlFor="email-login-title3">
  228. <Typography variant="h5" >
  229. <FormattedMessage id="setNewPassword"/>
  230. </Typography>
  231. </InputLabel>
  232. </Grid>
  233. </Grid>
  234. {/* <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  235. <Grid container direction="row" justifyContent="flex-start">
  236. <Grid item xs={12} md={12} lg={12}>
  237. <TextField
  238. fullWidth
  239. onChange={formik.handleChange}
  240. id="emailVerifyHash"
  241. name="emailVerifyHash"
  242. label={intl.formatMessage({id: 'securityCode'}) + ":"}
  243. placeholder={intl.formatMessage({id: 'securityCode'})}
  244. defaultValue={formik.values.emailVerifyHash}
  245. value={formik.values.emailVerifyHash}
  246. error={Boolean(formik.touched.emailVerifyHash && formik.errors.emailVerifyHash)}
  247. onBlur={formik.handleBlur}
  248. inputProps={{
  249. maxLength: 50,
  250. onKeyDown: (e) => {
  251. if (e.key === 'Enter') {
  252. e.preventDefault();
  253. }
  254. },
  255. }}
  256. InputLabelProps={{
  257. shrink: true
  258. }}
  259. />
  260. </Grid>
  261. {formik.touched.emailVerifyHash && formik.errors.emailVerifyHash && (
  262. <FormHelperText error id="standard-weight-helper-text-username-login">
  263. {formik.errors.emailVerifyHash}
  264. </FormHelperText>
  265. )}
  266. </Grid>
  267. </Grid> */}
  268. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  269. <Grid container direction="row" justifyContent="flex-start">
  270. <Grid item xs={12} md={12} lg={12}>
  271. <TextField
  272. fullWidth
  273. id="username"
  274. name="username"
  275. label={intl.formatMessage({id: 'userLoginName'}) + ":"}
  276. placeholder={intl.formatMessage({id: 'userLoginName'})}
  277. // defaultValue={username}
  278. value={username}
  279. disabled={true} />
  280. </Grid>
  281. </Grid>
  282. </Grid>
  283. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  284. <Grid container direction="row" justifyContent="flex-start">
  285. <Grid item xs={12} md={12} lg={12}>
  286. <TextField
  287. fullWidth
  288. autoFocus
  289. onChange={(e) => {
  290. formik.handleChange(e);
  291. changePassword(e.target.value);
  292. }}
  293. id="password"
  294. type={showPassword ? 'text' : 'password'}
  295. name="password"
  296. label={intl.formatMessage({id: 'newPassword'}) + ":"}
  297. placeholder={intl.formatMessage({id: 'newPassword'})}
  298. // defaultValue={formik.values.password.trim()}
  299. value={formik.values.password.trim()}
  300. error={Boolean(formik.touched.password && formik.errors.password)}
  301. onBlur={formik.handleBlur}
  302. inputProps={{
  303. onKeyDown: (e) => {
  304. if (e.key === 'Enter') {
  305. e.preventDefault();
  306. }
  307. },
  308. }}
  309. InputLabelProps={{
  310. shrink: true
  311. }}
  312. InputProps={{
  313. endAdornment:(
  314. <InputAdornment position="end">
  315. <IconButton
  316. aria-label="toggle password visibility"
  317. onClick={handleClickShowPassword}
  318. onMouseDown={handleMouseDownPassword}
  319. edge="end"
  320. size="large"
  321. >
  322. {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  323. </IconButton>
  324. </InputAdornment>
  325. )
  326. }}
  327. />
  328. </Grid>
  329. {/* <FormControl fullWidth sx={{ mt: 2 }}>
  330. <Grid container spacing={2} alignItems="center">
  331. <Grid item>
  332. <Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
  333. </Grid>
  334. <Grid item>
  335. <Typography variant="subtitle1">
  336. <FormattedMessage id={level ? level?.label : "pwWeak" }/>
  337. </Typography>
  338. </Grid>
  339. </Grid>
  340. </FormControl> */}
  341. {formik.touched.password && formik.errors.password && (
  342. <FormHelperText error id="helper-text-password-signup">
  343. {formik.errors.password}
  344. </FormHelperText>
  345. )}
  346. </Grid>
  347. </Grid>
  348. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  349. <Grid container direction="row" justifyContent="flex-start">
  350. <Grid item xs={12} md={12} lg={12}>
  351. <TextField
  352. fullWidth
  353. onChange={(e) => {
  354. formik.handleChange(e);
  355. // changePassword(e.target.value);
  356. }}
  357. id="confirmPassword"
  358. type={showConfirmPassword ? 'text' : 'password'}
  359. name="confirmPassword"
  360. label={intl.formatMessage({id: 'confirmPassword'}) + ":"}
  361. placeholder={intl.formatMessage({id: 'confirmPassword'})}
  362. // defaultValue={formik.values.confirmPassword.trim()}
  363. value={formik.values.confirmPassword.trim()}
  364. error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
  365. onBlur={formik.handleBlur}
  366. inputProps={{
  367. maxLength: 50,
  368. onKeyDown: (e) => {
  369. if (e.key === 'Enter') {
  370. e.preventDefault();
  371. }
  372. },
  373. }}
  374. InputLabelProps={{
  375. shrink: true
  376. }}
  377. InputProps={{
  378. endAdornment:(
  379. <InputAdornment position="end">
  380. <IconButton
  381. aria-label="toggle password visibility"
  382. onClick={handleClickShowConfirmPassword}
  383. onMouseDown={handleMouseDownPassword}
  384. edge="end"
  385. size="large"
  386. >
  387. {showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  388. </IconButton>
  389. </InputAdornment>
  390. )
  391. }}
  392. />
  393. </Grid>
  394. {formik.touched.confirmPassword && formik.errors.confirmPassword && (
  395. <FormHelperText error id="helper-text-confirmPassword-signup">
  396. {formik.errors.confirmPassword}
  397. </FormHelperText>
  398. )}
  399. </Grid>
  400. </Grid>
  401. <Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
  402. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  403. <Button
  404. aria-label={intl.formatMessage({id: 'confirm'})}
  405. variant="contained"
  406. type="submit"
  407. // onClick={()=>goLogin()}
  408. >
  409. <FormattedMessage id="confirm"/>
  410. </Button>
  411. </ThemeProvider>
  412. </Grid>
  413. </Grid>
  414. :
  415. // ERROR page
  416. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  417. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
  418. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  419. <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
  420. </Grid>
  421. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
  422. <Typography display="inline" variant="h4">
  423. <FormattedMessage id="verifyFail"/>
  424. </Typography>
  425. </Grid>
  426. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
  427. <Button color="error" variant="outlined" component={Link} to="/login">
  428. <Typography variant="h5">
  429. <FormattedMessage id="backToLogin"/>
  430. </Typography>
  431. </Button>
  432. </Grid>
  433. </Grid>
  434. }
  435. </form>
  436. </MainCard>
  437. </Grid>
  438. </Grid>
  439. );
  440. };
  441. export default Index;