No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

521 líneas
31 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 {
  8. Grid,
  9. Typography,
  10. Button,
  11. // RadioGroup,
  12. Dialog, DialogTitle, DialogContent, DialogActions,
  13. Stack,
  14. // InputLabel,
  15. // OutlinedInput,
  16. FormHelperText,
  17. TextField,
  18. IconButton, InputAdornment,
  19. CircularProgress,
  20. // Box,
  21. // FormControl
  22. } from '@mui/material';
  23. import Loadable from 'components/Loadable';
  24. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  25. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  26. // import ForwardIcon from '@mui/icons-material/Forward';
  27. import MainCard from 'components/MainCard';
  28. import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
  29. import {ThemeProvider} from "@emotion/react";
  30. import {FormattedMessage, useIntl} from "react-intl";
  31. import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
  32. import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
  33. import { useDispatch } from "react-redux";
  34. import { handleLogoutFunction} from 'auth/index';
  35. import { isPasswordExpiry } from "utils/Utils";
  36. import usePageTitle from "components/usePageTitle";
  37. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  38. const Index = () => {
  39. usePageTitle("userChangePassword");
  40. const dispatch = useDispatch()
  41. const navigate = useNavigate()
  42. const [showPassword, setShowPassword] = React.useState(false);
  43. const [showNewPassword, setShowNewPassword] = React.useState(false);
  44. const [showConfirmPassword, setshowConfirmPassword] = React.useState(false);
  45. const [isLoading, setLoding] = React.useState(true);
  46. const [isChanged, setIsChanged] = React.useState(false);
  47. const [comfirmChangeMessage, setComfirmChangeMessage] = React.useState(false);
  48. const [expiryErr, setExpiryErr] = React.useState(false);
  49. const [expiryErrText, setExpiryErrText] = React.useState("");
  50. const [changePasswordValues, setChangePasswordValues] = React.useState();
  51. const [isChangingPassword, setIsChangingPassword] = React.useState(false);
  52. const changePwdInFlightRef = React.useRef(false);
  53. const intl = useIntl();
  54. React.useEffect(() => {
  55. setLoding(false)
  56. }, []);
  57. const goLogin = (values) =>{
  58. if (changePwdInFlightRef.current) {
  59. return;
  60. }
  61. changePwdInFlightRef.current = true;
  62. setIsChangingPassword(true);
  63. setComfirmChangeMessage(false);
  64. HttpUtils.post({
  65. url: UrlUtils.PATCH_CHANGE_PASSWORD,
  66. params:{
  67. password: values.password,
  68. newPassword: values.newPassword
  69. },
  70. onSuccess: function (){
  71. setIsChanged(true);
  72. changePwdInFlightRef.current = false;
  73. setIsChangingPassword(false);
  74. },
  75. onFail: function () {
  76. changePwdInFlightRef.current = false;
  77. setIsChangingPassword(false);
  78. },
  79. onError:function (error) {
  80. // console.log(error.response.data);
  81. setExpiryErrText(intl.formatMessage({ id: error.response.data.error }))
  82. setExpiryErr(true)
  83. changePwdInFlightRef.current = false;
  84. setIsChangingPassword(false);
  85. // window.location.assign("/iamsmart/loginFail");
  86. }
  87. });
  88. }
  89. const BackgroundHead = {
  90. backgroundImage: `url(${titleBackgroundImg})`,
  91. width: 'auto',
  92. height: 'auto',
  93. backgroundSize: 'contain',
  94. backgroundRepeat: 'no-repeat',
  95. backgroundColor: '#0C489E',
  96. backgroundPosition: 'right'
  97. }
  98. const handleClickShowPassword = () => {
  99. setShowPassword(!showPassword);
  100. };
  101. const handleClickShowNewPassword = () => {
  102. setShowNewPassword(!showNewPassword);
  103. };
  104. const handleClickShowConfirmPassword = () => {
  105. setshowConfirmPassword(!showConfirmPassword);
  106. };
  107. const handleMouseDownPassword = (event) => {
  108. event.preventDefault();
  109. };
  110. const handleMouseDownNewPassword = (event) => {
  111. event.preventDefault();
  112. };
  113. const changePassword = (
  114. // value
  115. ) => {
  116. // const temp = strengthIndicator(value);
  117. // setLevel(strengthColorChi(temp));
  118. };
  119. const logout = () => {
  120. dispatch(handleLogoutFunction());
  121. navigate('/login');
  122. };
  123. const formik = useFormik({
  124. enableReinitialize: true,
  125. initialValues: {
  126. // username: '',
  127. password: '',
  128. newPassword: '',
  129. confirmPassword: '',
  130. // emailVerifyHash: '',
  131. },
  132. validationSchema: yup.object().shape({
  133. // emailVerifyHash: yup.string().required(intl.formatMessage({id: 'requireSecurityCode'})),
  134. // username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
  135. password: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  136. .required(intl.formatMessage({id: 'requirePassword'}))
  137. .matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
  138. .matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
  139. .matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
  140. .matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
  141. .matches(/^(?=.*\W)/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
  142. newPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  143. .required(intl.formatMessage({id: 'requirePassword'}))
  144. .matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
  145. .matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
  146. .matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
  147. .matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
  148. .matches(/^(?=.*\W)/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
  149. confirmPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
  150. .required(intl.formatMessage({id: 'pleaseConfirmPassword'}))
  151. .oneOf([yup.ref('newPassword'), null], intl.formatMessage({id: 'samePassword'})),
  152. }),
  153. onSubmit: values => {
  154. // console.log(values)
  155. setChangePasswordValues(values)
  156. setComfirmChangeMessage(true)
  157. }
  158. });
  159. const handleCCPChange = (e) => {
  160. e.preventDefault();
  161. };
  162. return (
  163. isLoading ?
  164. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
  165. <Grid item>
  166. <LoadingComponent />
  167. </Grid>
  168. </Grid>
  169. :
  170. <Grid container sx={{ minHeight: '87vh', mb: 3 }} direction="column" alignItems="center">
  171. <Grid item xs={12} md={12} width="100%" >
  172. <div style={BackgroundHead}>
  173. <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
  174. <Typography component="h1" ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
  175. <FormattedMessage id="userChangePassword"/>
  176. </Typography>
  177. </Stack>
  178. </div>
  179. </Grid>
  180. <Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
  181. <MainCard
  182. sx={{
  183. maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
  184. margin: { sm: 0, md: 3 },
  185. '& > *': {
  186. flexGrow: 1,
  187. flexBasis: '50%'
  188. }
  189. }}
  190. content={false}
  191. border={false}
  192. boxShadow
  193. >
  194. {
  195. !isChanged ?
  196. <form onSubmit={formik.handleSubmit}>
  197. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  198. {isPasswordExpiry()?
  199. <Grid item width="70%" xs={12} md={12} lg={12} sx={{ mb: 1, mt:2 }}>
  200. <Typography variant="h5" component="span">
  201. <FormattedMessage id="passwordExpired"/>
  202. </Typography>
  203. </Grid>
  204. :
  205. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:2 }}>
  206. <Typography variant="h5" component="span">
  207. <FormattedMessage id="setNewPassword"/>
  208. </Typography>
  209. </Grid>
  210. }
  211. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  212. <Grid container direction="row" justifyContent="flex-start">
  213. <Grid item xs={12} md={12} lg={12}>
  214. <TextField
  215. fullWidth
  216. autoFocus
  217. onChange={(e) => {
  218. formik.handleChange(e);
  219. changePassword(e.target.value);
  220. }}
  221. id="password"
  222. type={showPassword ? 'text' : 'password'}
  223. name="password"
  224. label={intl.formatMessage({id: 'oldPassword'}) + ":"}
  225. placeholder={intl.formatMessage({id: 'oldPassword'})}
  226. // defaultValue={formik.values.password.trim()}
  227. value={formik.values.password.trim()}
  228. error={Boolean(formik.touched.password && formik.errors.password)}
  229. onBlur={formik.handleBlur}
  230. inputProps={{
  231. onKeyDown: (e) => {
  232. if (e.key === 'Enter') {
  233. e.preventDefault();
  234. }
  235. },
  236. }}
  237. InputLabelProps={{
  238. shrink: true
  239. }}
  240. InputProps={{
  241. endAdornment:(
  242. <InputAdornment position="end">
  243. <IconButton
  244. aria-label={intl.formatMessage({
  245. id: showPassword ? "ariaHidePassword" : "ariaShowPassword"
  246. })}
  247. onClick={handleClickShowPassword}
  248. onMouseDown={handleMouseDownPassword}
  249. edge="end"
  250. size="large"
  251. >
  252. {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  253. </IconButton>
  254. </InputAdornment>
  255. )
  256. }}
  257. />
  258. </Grid>
  259. {formik.touched.password && formik.errors.password && (
  260. <FormHelperText error id="helper-text-password-signup">
  261. {formik.errors.password}
  262. </FormHelperText>
  263. )}
  264. </Grid>
  265. </Grid>
  266. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  267. <Grid container direction="row" justifyContent="flex-start">
  268. <Grid item xs={12} md={12} lg={12}>
  269. <TextField
  270. fullWidth
  271. // autoFocus
  272. onChange={(e) => {
  273. formik.handleChange(e);
  274. changePassword(e.target.value);
  275. }}
  276. id="newPassword"
  277. type={showNewPassword ? 'text' : 'password'}
  278. name="newPassword"
  279. label={intl.formatMessage({id: 'newPassword'}) + ":"}
  280. placeholder={intl.formatMessage({id: 'newPassword'})}
  281. // defaultValue={formik.values.password.trim()}
  282. value={formik.values.newPassword.trim()}
  283. error={Boolean(formik.touched.newPassword && formik.errors.newPassword)}
  284. onBlur={formik.handleBlur}
  285. inputProps={{
  286. onKeyDown: (e) => {
  287. if (e.key === 'Enter') {
  288. e.preventDefault();
  289. }
  290. },
  291. }}
  292. InputLabelProps={{
  293. shrink: true
  294. }}
  295. InputProps={{
  296. endAdornment:(
  297. <InputAdornment position="end">
  298. <IconButton
  299. aria-label={intl.formatMessage({ id: 'ariaToggleNewPasswordVisibility' })}
  300. onClick={handleClickShowNewPassword}
  301. onMouseDown={handleMouseDownNewPassword}
  302. edge="end"
  303. size="large"
  304. >
  305. {showNewPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  306. </IconButton>
  307. </InputAdornment>
  308. )
  309. }}
  310. />
  311. </Grid>
  312. {formik.touched.newPassword && formik.errors.newPassword && (
  313. <FormHelperText error id="helper-text-newPassword-signup">
  314. {formik.errors.newPassword}
  315. </FormHelperText>
  316. )}
  317. </Grid>
  318. </Grid>
  319. <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
  320. <Grid container direction="row" justifyContent="flex-start">
  321. <Grid item xs={12} md={12} lg={12}>
  322. <TextField
  323. fullWidth
  324. onChange={(e) => {
  325. formik.handleChange(e);
  326. // changePassword(e.target.value);
  327. }}
  328. id="confirmPassword"
  329. type={showConfirmPassword ? 'text' : 'password'}
  330. name="confirmPassword"
  331. label={intl.formatMessage({id: 'confirmNewPassword'}) + ":"}
  332. placeholder={intl.formatMessage({id: 'confirmNewPassword'})}
  333. // defaultValue={formik.values.confirmPassword.trim()}
  334. value={formik.values.confirmPassword.trim()}
  335. error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
  336. onBlur={formik.handleBlur}
  337. onCut={handleCCPChange}
  338. onCopy={handleCCPChange}
  339. onPaste={handleCCPChange}
  340. inputProps={{
  341. maxLength: 50,
  342. onKeyDown: (e) => {
  343. // console.log(e)
  344. if (e.key === 'Enter') {
  345. e.preventDefault();
  346. }
  347. },
  348. }}
  349. InputLabelProps={{
  350. shrink: true
  351. }}
  352. InputProps={{
  353. endAdornment:(
  354. <InputAdornment position="end">
  355. <IconButton
  356. aria-label={intl.formatMessage({
  357. id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword"
  358. })}
  359. onClick={handleClickShowConfirmPassword}
  360. onMouseDown={handleMouseDownPassword}
  361. edge="end"
  362. size="large"
  363. >
  364. {showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
  365. </IconButton>
  366. </InputAdornment>
  367. )
  368. }}
  369. />
  370. </Grid>
  371. {formik.touched.confirmPassword && formik.errors.confirmPassword && (
  372. <FormHelperText error id="helper-text-confirmPassword-signup">
  373. {formik.errors.confirmPassword}
  374. </FormHelperText>
  375. )}
  376. </Grid>
  377. <Grid container spacing={2} alignItems="center">
  378. <Grid item sx={{ mt: 1 }}>
  379. <Typography variant="subtitle1">
  380. •<FormattedMessage id="pwRemark1" /><br />
  381. •<FormattedMessage id="pwRemark2" /><br />
  382. •<FormattedMessage id="pwRemark3" /><br />
  383. •<FormattedMessage id="pwRemark4" /><br />
  384. •<FormattedMessage id="pwRemark5"/><br />
  385. </Typography>
  386. </Grid>
  387. </Grid>
  388. </Grid>
  389. <Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
  390. <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
  391. <Button
  392. aria-label={intl.formatMessage({id: 'confirm'})}
  393. variant="contained"
  394. type="submit"
  395. disabled={isChangingPassword}
  396. // onClick={()=>goLogin()}
  397. >
  398. <FormattedMessage id="confirm"/>
  399. </Button>
  400. </ThemeProvider>
  401. </Grid>
  402. </Grid>
  403. <div>
  404. <Dialog
  405. open={comfirmChangeMessage}
  406. onClose={() => setComfirmChangeMessage(false)}
  407. PaperProps={{
  408. sx: {
  409. minWidth: '40vw',
  410. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  411. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  412. }
  413. }}
  414. >
  415. <DialogTitle></DialogTitle>
  416. <DialogContent style={{ display: 'flex', }}>
  417. <Stack direction="column" justifyContent="space-between">
  418. <Typography variant="h5" component="span" style={{ padding: '10px' }}>
  419. <FormattedMessage id ="changePasswordConfirm"/>
  420. </Typography>
  421. </Stack>
  422. </DialogContent>
  423. <DialogActions>
  424. <Button disabled={isChangingPassword} onClick={() => setComfirmChangeMessage(false)}>
  425. <Typography variant="h5" component="span">
  426. <FormattedMessage id="close"/>
  427. </Typography>
  428. </Button>
  429. <Button
  430. disabled={isChangingPassword}
  431. onClick={() => goLogin(changePasswordValues)}
  432. startIcon={isChangingPassword ? <CircularProgress color="inherit" size={18} /> : null}
  433. >
  434. <Typography variant="h5" component="span">
  435. <FormattedMessage id="confirm"/>
  436. </Typography>
  437. </Button>
  438. </DialogActions>
  439. </Dialog>
  440. <Dialog
  441. open={expiryErr}
  442. onClose={() => setExpiryErr(false)}
  443. PaperProps={{
  444. sx: {
  445. minWidth: '40vw',
  446. maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
  447. maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
  448. }
  449. }}
  450. >
  451. <DialogTitle>
  452. <Typography variant="h5" component="span" style={{ padding: '10px' }}>
  453. <FormattedMessage id ="MSG.actionFail"/>
  454. </Typography>
  455. </DialogTitle>
  456. <DialogContent style={{ display: 'flex', }}>
  457. <Stack direction="column" justifyContent="space-between">
  458. <Typography variant="h5" component="span">
  459. {
  460. expiryErrText
  461. }
  462. </Typography>
  463. </Stack>
  464. </DialogContent>
  465. <DialogActions>
  466. <Button onClick={() => setExpiryErr(false)}>
  467. <Typography variant="h5" component="span">
  468. <FormattedMessage id="close"/>
  469. </Typography>
  470. </Button>
  471. </DialogActions>
  472. </Dialog>
  473. </div>
  474. </form>
  475. :
  476. <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
  477. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
  478. {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
  479. <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
  480. </Grid>
  481. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
  482. <Typography display="inline" variant="h4" component="span">
  483. <FormattedMessage id="resetPasswordSuccess"/>
  484. </Typography>
  485. </Grid>
  486. <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}>
  487. <Button color="success" variant="outlined" onClick={()=>logout()}>
  488. <Typography variant="h5" component="span">
  489. <FormattedMessage id="backToLogin"/>
  490. </Typography>
  491. </Button>
  492. </Grid>
  493. </Grid>
  494. }
  495. </MainCard>
  496. </Grid>
  497. </Grid>
  498. );
  499. };
  500. export default Index;