瀏覽代碼

add forgot username page

master
Alex Cheung 1 年之前
父節點
當前提交
ac0288418c
共有 17 個檔案被更改,包括 1269 行新增73 行删除
  1. +8
    -0
      src/assets/style/navbarStyles.css
  2. +43
    -28
      src/layout/MainLayout/Header/index.js
  3. +134
    -0
      src/pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess.js
  4. +12
    -39
      src/pages/authentication/ForgotPassword/AuthCallback/index.js
  5. +0
    -2
      src/pages/authentication/ForgotPassword/ForgotPasswordApplyForm.js
  6. +159
    -0
      src/pages/authentication/ForgotUsername/AfterForgotPasswordPage.js
  7. +134
    -0
      src/pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess.js
  8. +462
    -0
      src/pages/authentication/ForgotUsername/AuthCallback/index.js
  9. +221
    -0
      src/pages/authentication/ForgotUsername/ForgotUsernameApplyForm.js
  10. +49
    -0
      src/pages/authentication/ForgotUsername/index.js
  11. +6
    -1
      src/pages/authentication/auth-forms/AuthLoginCustom.js
  12. +1
    -1
      src/routes/AfterLoginRoutes.js
  13. +25
    -2
      src/routes/LoginRoutes.js
  14. +6
    -0
      src/translations/en.json
  15. +2
    -0
      src/translations/zh-CN.json
  16. +6
    -0
      src/translations/zh-HK.json
  17. +1
    -0
      src/utils/ApiPathConst.js

+ 8
- 0
src/assets/style/navbarStyles.css 查看文件

@@ -94,10 +94,18 @@
/* font-family: 微軟正黑體; */
}
#sidebartop{
align-items: center;
justify-content: start;
padding: 0;
display: flex;
width: 100%;
}
#logoutContent{
align-items: center;
justify-content: center;
padding: 0;
display: flex;
width: 100%;
}
#sidebarbottom{
align-items: center;


+ 43
- 28
src/layout/MainLayout/Header/index.js 查看文件

@@ -94,27 +94,27 @@ function Header(props) {
<Link className="application" to='/application/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Application</Typography></Link>
</li>
<li>
<Link className="proof" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Proof</Typography></Link>
<Link className="proof" to='/proof/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Proof</Typography></Link>
</li>
<li>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Payment</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<Link className="paymentTop" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Payment</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<ul className='dropdown'>
<li>
<Link className="payment" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Online Payment Record</Typography></Link>
<Link className="payment" to='/paymentPage/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Online Payment Record</Typography></Link>
</li>
<li>
<Link className="downloadXML" to='/gfmis/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>GFMIS Generate XML</Typography></Link>
<Link className="downloadXML" to='/gfmis/search'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>GFMIS Generate XML</Typography></Link>
</li>
<li>
<Link className="createDemandNote" to='/paymentPage/createDemandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Create Demand Note</Typography></Link>
<Link className="createDemandNote" to='/paymentPage/createDemandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Create Demand Note</Typography></Link>
</li>
<li>
<Link className="demandNote" to='/paymentPage/demandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Demand Note</Typography></Link>
<Link className="demandNote" to='/paymentPage/demandNote' ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Demand Note</Typography></Link>
</li>
</ul>
</li>
<li>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Client</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Client</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<ul className='dropdown'>
<li>
<Link className="userSearchview" to='/userSearchview'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users (GLD)</Typography></Link>
@@ -135,7 +135,7 @@ function Header(props) {
</ul>
</li>
<li>
<Link className="client" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Settings</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<Link className="setting" ><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 1 }}>Settings</Typography><KeyboardArrowDownIcon sx={{ fontSize: '1.0rem' }} /></Link>
<ul className='dropdown'>
<li>
<Link className="userProfileGld" to='/user/profile'><Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}>Users Profile</Typography></Link>
@@ -148,9 +148,11 @@ function Header(props) {
</li>
</ul>
</li>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Logout</Typography></Link>
</li>
<Box sx={{display: {xs: 'none', sm: 'none', md: 'block'}}}>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>Logout</Typography></Link>
</li>
</Box>
</div>
:
<div id="individualUserContent">
@@ -271,11 +273,13 @@ function Header(props) {
</>
}
</li>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="logout" />
</Typography></Link>
</li>
<Box sx={{display: {xs: 'none', sm: 'none', md: 'block'}}}>
<li>
<Link className="logout" onClick={handleLogout}><Typography variant={"pnspsHeaderTitle"} sx={{ ml: 2 }}>
<FormattedMessage id="logout" />
</Typography></Link>
</li>
</Box>
</div>
);

@@ -301,9 +305,13 @@ function Header(props) {
const drawer = (
isUserLoggedIn() ?
<Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" /*onClick={handleDrawerToggle}*/ sx={{ textAlign: 'center', width: '300px' }}>
<Typography variant="h6" sx={{ my: 2 }}>
{/* <Typography variant="h6" sx={{ my: 2 }}>
PNSPS
</Typography>
</Typography> */}
<Box sx={{ mr: 2, mt:1, display: { md: 'none' } }}>
<MobileLogo />
<span id="mobileTitle" >PNSPS</span>
</Box>
<Divider />
<ul id="sidebartop">
{loginContent}
@@ -319,11 +327,12 @@ function Header(props) {
</Stack>
:
<Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
<Typography variant="h6" sx={{ my: 2 }}>
PNSPS
</Typography>
<Box sx={{ mr: 2, mt:1, display: { md: 'none' } }}>
<MobileLogo />
<span id="mobileTitle" >PNSPS</span>
</Box>
<Divider />
<ul id="sidebartop">
<ul id="logoutContent">
{logoutContent}
</ul>
<Divider />
@@ -366,7 +375,7 @@ function Header(props) {
justifyContent="flex-start"
alignItems="center"
spacing={0}
// sx={{width:{xs:'100%',md:'25%'}}}
sx={{width:{xs:'100%',md:'25%'}}}
>
<Box sx={{ width: '260px', flexGrow: 1, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Stack direction="row" justifyContent="flex-start" alignItems="center">
@@ -389,12 +398,18 @@ function Header(props) {
>
<MenuIcon style={{ color: '#0C489E' }} />
</IconButton>
<Box sx={{ mr: 2, display: { md: 'none' } }}>
<Stack direction="row" justifyContent="flex-start" alignItems="center">
<Box sx={{ flexGrow: 1, mr: 2, display: { sm: 'block', md: 'none' } }}>
<Stack direction="row" justifyContent="space-between" alignItems="center" width="100%">
<MobileLogo />
<span id="mobileTitle" >
<FormattedMessage id="PNSPS" />
</span>
<Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}>
<span id="mobileTitle">
<FormattedMessage id="PNSPS" />
</span>
</Stack>

<Stack justifyContent="flex-end" alignItems="center">
<LocaleSelector />
</Stack>
</Stack>
</Box>
</Stack>


+ 134
- 0
src/pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess.js 查看文件

@@ -0,0 +1,134 @@
// import { useFormik } from 'formik';
// import * as yup from 'yup';
import * as React from "react";
// import * as HttpUtils from "utils/HttpUtils";
// import * as UrlUtils from "utils/ApiPathConst";
// import { useNavigate } from "react-router-dom";
// import { useDispatch } from "react-redux";
// import { handleLogoutFunction, handleLogin} from 'auth/index';
// import useJwt from "auth/jwt/useJwt";

import {
Grid,
Typography,
Button,
// RadioGroup,
// Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
// InputLabel,
// OutlinedInput,
// FormHelperText,
// TextField,
// IconButton, InputAdornment,
// Box,
// FormControl
} from '@mui/material';
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';
// import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
// import {ThemeProvider} from "@emotion/react";
import {FormattedMessage,
// useIntl
} from "react-intl";
// import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
// import axios from 'axios';
import {
// useParams,
Link
} from 'react-router-dom';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';

// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ResetPasswordSuccess = () => {
// const dispatch = useDispatch()
// const navigate = useNavigate()
const [isLoading, setLoding] = React.useState(true);
// const params = useParams()
// const intl = useIntl();
React.useEffect(() => {
// console.log(params);
setLoding(false)
}, []);

// React.useEffect(() => {
// // console.log("if (enterUseEffect) handleVerify()");
// if (enterUseEffect){
// handleVerify()
// }
// }, [enterUseEffect])

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

return (
isLoading ?
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
<CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Typography display="inline" variant="h4">
<FormattedMessage id="resetPasswordSuccess"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Button color="success" variant="outlined" component={Link} to="/login">
<Typography variant="h5">
<FormattedMessage id="backToLogin"/>
</Typography>
</Button>
</Grid>
</Grid>
</MainCard>
</Grid>
</Grid>
);
};

export default ResetPasswordSuccess;

+ 12
- 39
src/pages/authentication/ForgotPassword/AuthCallback/index.js 查看文件

@@ -5,7 +5,9 @@ import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { handleLogoutFunction, handleLogin } from 'auth/index';
import { handleLogoutFunction,
// handleLogin
} from 'auth/index';
import useJwt from "auth/jwt/useJwt";

import {
@@ -35,7 +37,7 @@ import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
import axios from 'axios';
import { useParams,Link } from 'react-router-dom';
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
import LocaleContext from "components/I18nProvider";
// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

@@ -48,7 +50,7 @@ const Index = () => {
const [verifyState, setVerifyState] = React.useState(null)
const [enterUseEffect, setEnterUseEffect] = React.useState(false)
const [username, setUsername] = React.useState("")
const { setLocale } = React.useContext(LocaleContext);
// const { setLocale } = React.useContext(LocaleContext);
const params = useParams()
const intl = useIntl();
@@ -103,47 +105,16 @@ const Index = () => {
onSuccess: () => {
useJwt
.login({ username: username, password: values.password })
.then((response) => {
.then((
// response
) => {
// console.log(response)
const userData = {
id: response.data.id,
fullenName: response.data.name,
fullchName: response.data.chName,
email: response.data.email,
type: response.data.type,
role: response.data.role,
abilities: response.data.abilities,
creditor: response.data.creditor,
locale: response.data.preferLocale,
//avatar: require('src/assets/images/users/avatar-3.png').default,
}
const data = { ...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken }
// setSuccess(true)
// console.log(response.data);
if(response.data.type === "GLD"){
setLocale("en");
localStorage.setItem('locale','en');
}else{
if (response.data.preferLocale ==="zh_HK"){
setLocale("zh-HK");
localStorage.setItem('locale','zh-HK');
}
if (response.data.preferLocale ==="zh-CN"){
setLocale("zh-CN");
localStorage.setItem('locale','zh-CN');
}
}
dispatch(handleLogin(data))
navigate('/dashboard');
navigate('/forgot/password/success');
location.reload()
// setSumitting(false)
})
.catch((error) => {
// setSuccess(false)
console.error(error)
// console.error(error.response.data.error)
// setErrorMassage(error.response.data.error)
// setOpen(true)
});
},
onFail: (response)=>{
@@ -464,7 +435,9 @@ const Index = () => {
<CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Typography display="inline" variant="h4">驗證失敗,請聯絡相關的系統管理員協助。</Typography>
<Typography display="inline" variant="h4">
<FormattedMessage id="verifyFail"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Button color="error" variant="outlined" component={Link} to="/login">


+ 0
- 2
src/pages/authentication/ForgotPassword/ForgotPasswordApplyForm.js 查看文件

@@ -69,12 +69,10 @@ const ForgotPasswordApplyForm = () => {
onSuccess: function () {
// notifyActionSuccess(intl.formatMessage({id: 'submissionSuccess'}) + '!')
navigate('/forgot/password/sent');
console.log("jjj")
// location.reload();
},
onError:function () {
navigate('/forgot/password/sent');
console.log("hihihi")
}
});
}


+ 159
- 0
src/pages/authentication/ForgotUsername/AfterForgotPasswordPage.js 查看文件

@@ -0,0 +1,159 @@
// material-ui
import {
Grid,
Typography,
Button,
Stack,
InputLabel,
} from '@mui/material';

import * as React from "react";

import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';


import { useNavigate } from "react-router-dom";
import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import {FormattedMessage, useIntl} from "react-intl";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const AfterForgotPasswordPage = () => {
const intl = useIntl();
const navigate = useNavigate();

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

const handleContinue = () => {
// setOpen(false);
navigate('/login');
};

return (
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
{/* <Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
<Button
aria-label={intl.formatMessage({id: 'back'})}
title={intl.formatMessage({id: 'back'})}
sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid> */}
{/* <Grid item xs={12}>
<Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
</Grid> */}
<Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="center" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Grid container direction="column" alignItems="center">
<Grid item xs={12} md={12} lg={12} >
<InputLabel htmlFor="email-login-title1">
<Typography variant="h5" >
<FormattedMessage id="sentSecurityCode1"/>
</Typography>
</InputLabel>
</Grid>
<Grid item xs={12} md={12} lg={12} >
<InputLabel htmlFor="email-login-title2">
<Typography variant="h5" >
<FormattedMessage id="sentSecurityCode2"/>
</Typography>
</InputLabel>
</Grid>
{/* <Grid item xs={12} md={12} lg={12} sx={{mt:3}}>
<InputLabel htmlFor="email-login-title3">
<Typography variant="h5" >
<FormattedMessage id="requireSecurityCode"/>
</Typography>
</InputLabel>
</Grid> */}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { md: 'none', xl: 'none', lg: 'none' } }}>
<Grid container direction="column" alignItems="center">
<Grid item xs={12} md={12} lg={12} >
<InputLabel htmlFor="email-login-title1">
<Typography variant="h5" >
<FormattedMessage id="sentSecurityCode1"/>
</Typography>
</InputLabel>
</Grid>
<Grid item xs={12} md={12} lg={12} >
<InputLabel htmlFor="email-login-title2">
<Typography variant="h5" >
<FormattedMessage id="sentSecurityCode3"/>
</Typography>
</InputLabel>
</Grid>
<Grid item xs={12} md={12} lg={12} >
<InputLabel htmlFor="email-login-title4">
<Typography variant="h5" >
<FormattedMessage id="sentSecurityCode4"/>
</Typography>
</InputLabel>
</Grid>
{/* <Grid item xs={12} md={12} lg={12} sx={{mt:3}}>
<InputLabel htmlFor="email-login-title3">
<Typography variant="h5" >
<FormattedMessage id="requireSecurityCode"/>
</Typography>
</InputLabel>
</Grid> */}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<Button
aria-label={intl.formatMessage({id: 'confirm'})}
variant="contained"
// type="submit"
onClick={()=>handleContinue()}
>
<FormattedMessage id="confirm"/>
</Button>
</ThemeProvider>
</Grid>
</Grid>

</MainCard>
</Grid>
</Grid>
);
};


export default AfterForgotPasswordPage;

+ 134
- 0
src/pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess.js 查看文件

@@ -0,0 +1,134 @@
// import { useFormik } from 'formik';
// import * as yup from 'yup';
import * as React from "react";
// import * as HttpUtils from "utils/HttpUtils";
// import * as UrlUtils from "utils/ApiPathConst";
// import { useNavigate } from "react-router-dom";
// import { useDispatch } from "react-redux";
// import { handleLogoutFunction, handleLogin} from 'auth/index';
// import useJwt from "auth/jwt/useJwt";

import {
Grid,
Typography,
Button,
// RadioGroup,
// Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
// InputLabel,
// OutlinedInput,
// FormHelperText,
// TextField,
// IconButton, InputAdornment,
// Box,
// FormControl
} from '@mui/material';
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';
// import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
// import {ThemeProvider} from "@emotion/react";
import {FormattedMessage,
// useIntl
} from "react-intl";
// import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
// import axios from 'axios';
import {
// useParams,
Link
} from 'react-router-dom';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';

// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ResetPasswordSuccess = () => {
// const dispatch = useDispatch()
// const navigate = useNavigate()
const [isLoading, setLoding] = React.useState(true);
// const params = useParams()
// const intl = useIntl();
React.useEffect(() => {
// console.log(params);
setLoding(false)
}, []);

// React.useEffect(() => {
// // console.log("if (enterUseEffect) handleVerify()");
// if (enterUseEffect){
// handleVerify()
// }
// }, [enterUseEffect])

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

return (
isLoading ?
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
<CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Typography display="inline" variant="h4">
<FormattedMessage id="resetPasswordSuccess"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Button color="success" variant="outlined" component={Link} to="/login">
<Typography variant="h5">
<FormattedMessage id="backToLogin"/>
</Typography>
</Button>
</Grid>
</Grid>
</MainCard>
</Grid>
</Grid>
);
};

export default ResetPasswordSuccess;

+ 462
- 0
src/pages/authentication/ForgotUsername/AuthCallback/index.js 查看文件

@@ -0,0 +1,462 @@
import { useFormik } from 'formik';
import * as yup from 'yup';
import * as React from "react";
import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { handleLogoutFunction,
// handleLogin
} from 'auth/index';
import useJwt from "auth/jwt/useJwt";

import {
Grid,
Typography,
Button,
// RadioGroup,
// Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
InputLabel,
// OutlinedInput,
FormHelperText,
TextField,
IconButton, InputAdornment,
// Box,
// FormControl
} from '@mui/material';
import Loadable from 'components/Loadable';
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
// import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';
import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import {FormattedMessage, useIntl} from "react-intl";
import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons';
import axios from 'axios';
import { useParams,Link } from 'react-router-dom';
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
// import LocaleContext from "components/I18nProvider";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const Index = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const [showPassword, setShowPassword] = React.useState(false);
const [showConfirmPassword, setshowConfirmPassword] = React.useState(false);
const [isLoading, setLoding] = React.useState(true);
const [verifyState, setVerifyState] = React.useState(null)
const [enterUseEffect, setEnterUseEffect] = React.useState(false)
const [username, setUsername] = React.useState("")
// const { setLocale } = React.useContext(LocaleContext);
const params = useParams()
const intl = useIntl();
React.useEffect(() => {
console.log(params);
setEnterUseEffect(true)
}, []);

React.useEffect(() => {
// console.log("if (enterUseEffect) handleVerify()");
if (enterUseEffect){
handleVerify()
}
}, [enterUseEffect])

const handleVerify = async () => {
console.log(params);
await axios.get(UrlUtils.GET_FORGOT_PASSWORD_VERIFY_USER_ACCOUNT, {
params: {
email: decodeURIComponent(params.email),
emailVerifyHash: decodeURIComponent(params.verifyCode)
}
}).then(
(response)=>{
if (response.status === 200 && response.data) {
console.log(response)
setUsername(response.data.username)
setVerifyState(true)
} else {
setVerifyState(false)
}
setLoding(false)
}
).catch(error => {
console.log(error)
setVerifyState(false)
setLoding(false)
});

}

const goLogin = async (values) =>{
dispatch(handleLogoutFunction());
HttpUtils.post({
url: UrlUtils.POST_FORGOT_PASSWORD_NEW_PASSWORD,
params:{
username: username,
newPassword: values.password
},
onSuccess: () => {
useJwt
.login({ username: username, password: values.password })
.then((
// response
) => {
// console.log(response)
navigate('/forgot/password/success');
location.reload()
// setSumitting(false)
})
.catch((error) => {
console.error(error)
});
},
onFail: (response)=>{
console.log("Fail");
console.log(response);
// window.location.assign("/iamsmart/loginFail");
},
onError:(error)=>{
console.log(error);
// window.location.assign("/iamsmart/loginFail");
}
});
}

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

const handleClickShowPassword = () => {
setShowPassword(!showPassword);
};

const handleClickShowConfirmPassword = () => {
setshowConfirmPassword(!showConfirmPassword);
};

const handleMouseDownPassword = (event) => {
event.preventDefault();
};

const changePassword = (
// value
) => {
// const temp = strengthIndicator(value);
// setLevel(strengthColorChi(temp));
};

const formik = useFormik({
enableReinitialize: true,
initialValues: {
// username: '',
password: '',
confirmPassword: '',
// emailVerifyHash: '',
},
validationSchema: yup.object().shape({
// emailVerifyHash: yup.string().required(intl.formatMessage({id: 'requireSecurityCode'})),
// username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
password: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
.required(intl.formatMessage({id: 'requirePassword'}))
.matches(/^\S*$/, { message: (intl.formatMessage({id: 'noSpacePassword'}))})
.matches(/^(?=.*[a-z])/, { message: intl.formatMessage({id: 'atLeastOneSmallLetter'})})
.matches(/^(?=.*[A-Z])/, { message: intl.formatMessage({id: 'atLeastOneCapLetter'})})
.matches(/^(?=.*[0-9])/, { message: intl.formatMessage({id: 'atLeast1Number'})})
.matches(/^(?=.*[!@#%&])/, { message: intl.formatMessage({id: 'atLeast1SpecialChar'})}),
confirmPassword: yup.string().min(8, intl.formatMessage({id: 'atLeast8CharPassword'}))
.required(intl.formatMessage({id: 'pleaseConfirmPassword'}))
.oneOf([yup.ref('password'), null], intl.formatMessage({id: 'samePassword'})),
}),
onSubmit: values => {
// console.log(values)
goLogin(values)
}
});

return (
isLoading || verifyState == null ?
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
{/* <Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
<Button
aria-label={intl.formatMessage({id: 'back'})}
title={intl.formatMessage({id: 'back'})}
sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid> */}
{/* <Grid item xs={12}>
<Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
</Grid> */}
<Grid item xs={12} md={12} width={{ sx:"90%", sm:"90%",md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:730, md:800, lg: 1000 },
margin: { sm: 0, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<form onSubmit={formik.handleSubmit}>
{verifyState ?
// SUCCESS page
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid container direction="column" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, }}>
<Typography display="inline" variant="h4">
<FormattedMessage id="verifySuccess"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1,}}>
<InputLabel htmlFor="email-login-title3">
<Typography variant="h5" >
<FormattedMessage id="setNewPassword"/>
</Typography>
</InputLabel>
</Grid>
</Grid>
{/* <Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
onChange={formik.handleChange}
id="emailVerifyHash"
name="emailVerifyHash"
label={intl.formatMessage({id: 'securityCode'}) + ":"}
placeholder={intl.formatMessage({id: 'securityCode'})}
defaultValue={formik.values.emailVerifyHash}
value={formik.values.emailVerifyHash}
error={Boolean(formik.touched.emailVerifyHash && formik.errors.emailVerifyHash)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 50,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
/>
</Grid>
{formik.touched.emailVerifyHash && formik.errors.emailVerifyHash && (
<FormHelperText error id="standard-weight-helper-text-username-login">
{formik.errors.emailVerifyHash}
</FormHelperText>
)}
</Grid>
</Grid> */}
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
id="username"
name="username"
label={intl.formatMessage({id: 'userLoginName'}) + ":"}
placeholder={intl.formatMessage({id: 'userLoginName'})}
// defaultValue={username}
value={username}
disabled={true} />
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
onChange={(e) => {
formik.handleChange(e);
changePassword(e.target.value);
}}
id="password"
type={showPassword ? 'text' : 'password'}
name="password"
label={intl.formatMessage({id: 'newPassword'}) + ":"}
placeholder={intl.formatMessage({id: 'newPassword'})}
// defaultValue={formik.values.password.trim()}
value={formik.values.password.trim()}
error={Boolean(formik.touched.password && formik.errors.password)}
onBlur={formik.handleBlur}
inputProps={{
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
InputProps={{
endAdornment:(
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
size="large"
>
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Grid>
{/* <FormControl fullWidth sx={{ mt: 2 }}>
<Grid container spacing={2} alignItems="center">
<Grid item>
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
</Grid>
<Grid item>
<Typography variant="subtitle1">
<FormattedMessage id={level ? level?.label : "pwWeak" }/>
</Typography>
</Grid>
</Grid>
</FormControl> */}
{formik.touched.password && formik.errors.password && (
<FormHelperText error id="helper-text-password-signup">
{formik.errors.password}
</FormHelperText>
)}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12}>
<TextField
fullWidth
onChange={(e) => {
formik.handleChange(e);
// changePassword(e.target.value);
}}
id="confirmPassword"
type={showConfirmPassword ? 'text' : 'password'}
name="confirmPassword"
label={intl.formatMessage({id: 'confirmPassword'}) + ":"}
placeholder={intl.formatMessage({id: 'confirmPassword'})}
// defaultValue={formik.values.confirmPassword.trim()}
value={formik.values.confirmPassword.trim()}
error={Boolean(formik.touched.confirmPassword && formik.errors.confirmPassword)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 50,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
InputProps={{
endAdornment:(
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleClickShowConfirmPassword}
onMouseDown={handleMouseDownPassword}
edge="end"
size="large"
>
{showConfirmPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Grid>
{formik.touched.confirmPassword && formik.errors.confirmPassword && (
<FormHelperText error id="helper-text-confirmPassword-signup">
{formik.errors.confirmPassword}
</FormHelperText>
)}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} mt={1} sx={{mb:3}}>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<Button
aria-label={intl.formatMessage({id: 'confirm'})}
variant="contained"
type="submit"
// onClick={()=>goLogin()}
>
<FormattedMessage id="confirm"/>
</Button>
</ThemeProvider>
</Grid>
</Grid>
:
// ERROR page
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
{/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */}
<CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} />
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Typography display="inline" variant="h4">
<FormattedMessage id="verifyFail"/>
</Typography>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<Button color="error" variant="outlined" component={Link} to="/login">
<Typography variant="h5">
<FormattedMessage id="backToLogin"/>
</Typography>
</Button>
</Grid>
</Grid>
}
<Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"70vh", md: "70vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center">
</Grid>
</form>
</MainCard>
</Grid>
</Grid>
);
};

export default Index;

+ 221
- 0
src/pages/authentication/ForgotUsername/ForgotUsernameApplyForm.js 查看文件

@@ -0,0 +1,221 @@
// material-ui
import {
Grid,
Typography,
Button,
// RadioGroup,
Dialog, DialogTitle, DialogContent, DialogActions,
Stack,
InputLabel,
// OutlinedInput,
FormHelperText,
TextField,
// Box
} from '@mui/material';
import { useFormik } from 'formik';
import * as yup from 'yup';
import * as React from "react";
import * as HttpUtils from "utils/HttpUtils";
import * as UrlUtils from "utils/ApiPathConst";
// import * as FieldUtils from "utils/FieldUtils";
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
import ForwardIcon from '@mui/icons-material/Forward';
import MainCard from 'components/MainCard';


import { useNavigate } from "react-router-dom";
// import { notifyActionSuccess } from 'utils/CommonFunction';
import {PNSPS_LONG_BUTTON_THEME} from "themes/buttonConst";
import {ThemeProvider} from "@emotion/react";
import {FormattedMessage, useIntl} from "react-intl";

// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ForgotUsernameApplyForm = () => {
const [isWarningPopUp, setIsWarningPopUp] = React.useState(false);
// const [warningText, setWarningText] = React.useState("");s
// const [attachment, setAttachment] = React.useState({});
const intl = useIntl();

// const [issueId, setIssueId] = React.useState(loadedData.issueId);
const navigate = useNavigate();

const BackgroundHead = {
backgroundImage: `url(${titleBackgroundImg})`,
width: 'auto',
height: 'auto',
backgroundSize: 'contain',
backgroundRepeat: 'no-repeat',
backgroundColor: '#0C489E',
backgroundPosition: 'right'
}

const formik = useFormik({
enableReinitialize: true,
initialValues: {
// username: '',
emailAddress: '',
},
validationSchema: yup.object().shape({
// username: yup.string().required(intl.formatMessage({id: 'requireUsername'})),
emailAddress: yup.string().email(intl.formatMessage({id: 'validEmailFormat'})).max(255).required(intl.formatMessage({id: 'requireEmail'})),
}),
onSubmit: values => {
console.log(values)
HttpUtils.post({
url: UrlUtils.POST_FORGOT_USERNAME_EMAIL,
params: {
emailAddress: values.emailAddress,
},
// files: [attachment],
onSuccess: function () {
// notifyActionSuccess(intl.formatMessage({id: 'submissionSuccess'}) + '!')
navigate('/forgot/password/sent');
// location.reload();
},
onError:function () {
navigate('/forgot/password/sent');
}
});
}
});

return (
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" alignItems="center">
<Grid item xs={12} md={12} width="100%" >
<div style={BackgroundHead}>
<Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center">
<Typography ml={15} color='#FFF' variant="h4" sx={{display: { xs: 'none', sm: 'none', md: 'block' }}}>
<FormattedMessage id="forgotUserPassword"/>
</Typography>
</Stack>
</div>
</Grid>
<Grid item xs={12} width={{xs:"90%", sm:"90%", md:"60%", lg:"60%"}}>
<Button
aria-label={intl.formatMessage({id: 'back'})}
title={intl.formatMessage({id: 'back'})}
sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}
>
<ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} />
</Button>
</Grid>
{/* <Grid item xs={12}>
<Typography variant="pnspsFormParagraphBold">申請公共啟事</Typography>
</Grid> */}
<Grid item xs={12} md={12} width={{ md: "60%", xs: "90%" }}>
<MainCard
sx={{
maxWidth: { xs: 400, sm:600, md:800, lg: 1000 },
margin: { sm: 2.5, md: 3 },
'& > *': {
flexGrow: 1,
flexBasis: '50%'
}
}}
content={false}
border={false}
boxShadow
>
<form onSubmit={formik.handleSubmit}>
<Grid container spacing={2} sx={{ minHeight: '40vh' }} direction="column" justifyContent="flex-start" alignItems="center">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}>
<InputLabel htmlFor="email-login-title">
<Typography variant="h5" >
<FormattedMessage id="forgotUsernameSubTitle"/>
</Typography>
</InputLabel>
</Grid>
<Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { md: 'none', xl: 'none', lg: 'none' } }}>
<InputLabel htmlFor="email-login-subtitle">
<Typography variant="h6" >
<FormattedMessage id="forgotUsernameSubTitle1"/>
</Typography>
<Typography variant="h6" >
<FormattedMessage id="forgotPasswordSubTitle2"/>
</Typography>
</InputLabel>
</Grid>
<Grid item xs={12} md={12} lg={12} width={{xs:"70%", sm:"60%",md:"50%", lg:"50%"}}>
<Grid container direction="row" justifyContent="flex-start">
<Grid item xs={12} md={12} lg={12} sx={{ mb: 3}} >
<TextField
fullWidth
onChange={formik.handleChange}
id="emailAddress"
name="emailAddress"
placeholder={intl.formatMessage({id: 'userContactEmail'})}
label={intl.formatMessage({id: 'userContactEmail'}) + ":"}
defaultValue={formik.values.emailAddress}
value={formik.values.emailAddress}
error={Boolean(formik.touched.emailAddress && formik.errors.emailAddress)}
onBlur={formik.handleBlur}
inputProps={{
maxLength: 50,
onKeyDown: (e) => {
if (e.key === 'Enter') {
e.preventDefault();
}
},
}}
InputLabelProps={{
shrink: true
}}
/>
</Grid>
{formik.touched.emailAddress && formik.errors.emailAddress && (
<FormHelperText error id="standard-weight-helper-text-emailAddress-login">
{formik.errors.emailAddress}
</FormHelperText>
)}
</Grid>
</Grid>
<Grid item xs={12} md={12} lg={12} mt={1}>
<ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}>
<Button
aria-label={intl.formatMessage({id: 'continue'})}
variant="contained"
type="submit"
>
<FormattedMessage id="continue"/>
</Button>
</ThemeProvider>
</Grid>
</Grid>
</form>
</MainCard>
</Grid>
<div>
<Dialog
open={isWarningPopUp}
onClose={() => setIsWarningPopUp(false)}
PaperProps={{
sx: {
minWidth: '40vw',
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' },
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' }
}
}}
>
<DialogTitle>
<FormattedMessage id="attention"/>
</DialogTitle>
<DialogContent style={{ display: 'flex', }}>
{/* <Typography variant="h3" style={{ padding: '16px' }}>{warningText}</Typography> */}
</DialogContent>
<DialogActions>
<Button
aria-label={intl.formatMessage({id: 'ok'})}
onClick={() => setIsWarningPopUp(false)}
>
<FormattedMessage id="ok" />
</Button>
</DialogActions>
</Dialog>
</div>
</Grid>
);
};


export default ForgotUsernameApplyForm;

+ 49
- 0
src/pages/authentication/ForgotUsername/index.js 查看文件

@@ -0,0 +1,49 @@
// material-ui
import * as React from "react";
// import * as HttpUtils from "utils/HttpUtils";
// import * as UrlUtils from "utils/ApiPathConst";
// import * as DateUtils from "utils/DateUtils";
// import * as FormatUtils from "utils/FormatUtils";

import {
Grid
} from '@mui/material';

import Loadable from 'components/Loadable';
import { lazy } from 'react';
const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent')));
const ForgotUsernameApplyForm = Loadable(lazy(() => import('./ForgotUsernameApplyForm')));


// ==============================|| DASHBOARD - DEFAULT ||============================== //

const ApplyForm = () => {
// const [userData, setUserData] = React.useState(null);
// const [selections, setSelection] = React.useState([]);
const [isLoading, setLoding] = React.useState(true);

React.useEffect(() => {
loadUserData();
}, []);

const loadUserData = () => {
setLoding(false);
};

return (
isLoading ?
<Grid container sx={{ minHeight: '95vh', mb: 3 }} direction="column" justifyContent="center" alignItems="center">
<Grid item>
<LoadingComponent />
</Grid>
</Grid>
:
<ForgotUsernameApplyForm
// loadedData={userData}
// selections={selections}
/>
);
};


export default ApplyForm;

+ 6
- 1
src/pages/authentication/auth-forms/AuthLoginCustom.js 查看文件

@@ -337,12 +337,17 @@ const AuthLoginCustom = () => {
</AnimateButton>
</Grid>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
<Stack direction="column" justifyContent="flex-start" alignItems="flex-start" spacing={2}>
<Link component={RouterLink} to="/forgot/password" color="primary">
<Typography align="center" variant="h6">
<FormattedMessage id="forgotUserPassword"/>?
</Typography>
</Link>
<Link component={RouterLink} to="/forgot/username" color="primary">
<Typography align="center" variant="h6">
<FormattedMessage id="forgotUsername"/>?
</Typography>
</Link>
</Stack>
</Grid>
<Grid item xs={12}>


+ 1
- 1
src/routes/AfterLoginRoutes.js 查看文件

@@ -61,7 +61,7 @@ const AfterLoginRoutes = {
element: <Navigate to="/dashboard" />
},
{
path: 'forgot/password/loginFail',
path: 'forgot/password/success',
element: <Navigate to="/dashboard" />
},
]


+ 25
- 2
src/routes/LoginRoutes.js 查看文件

@@ -12,9 +12,16 @@ const RegisterForm = Loadable(lazy(() => import('pages/authentication/Register')
const BusRegisterForm = Loadable(lazy(() => import('pages/authentication/BusRegister')));
const IAmSmartRegister = Loadable(lazy(() => import('pages/authentication/IAmSmartRegister')));
const ErrorPage = Loadable(lazy(() => import('pages/extra-pages/ErrorPage')));

const ForgotPassword = Loadable(lazy(() => import('pages/authentication/ForgotPassword')));
const AfterForgotPasswordPage = Loadable(lazy(() => import('pages/authentication/ForgotPassword/AfterForgotPasswordPage')));
const ForgotPassword_Callback = Loadable(lazy(() => import('pages/authentication/ForgotPassword/AuthCallback')));
const ForgotPassword_Success = Loadable(lazy(() => import('pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess')));

const ForgotUsername = Loadable(lazy(() => import('pages/authentication/ForgotUsername')));
const AfterForgotUsernamePage = Loadable(lazy(() => import('pages/authentication/ForgotUsername/AfterForgotPasswordPage')));
const ForgotUsername_Callback = Loadable(lazy(() => import('pages/authentication/ForgotUsername/AuthCallback')));
const ForgotUsername_Success = Loadable(lazy(() => import('pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess')));

const IAmSmart_DirectLoginCallback = Loadable(lazy(() => import('pages/iAmSmart/DirectLoginCallback')));
//const IAmSmart_FallCallback = Loadable(lazy(() => import('pages/iAmSmart/FallCallback')));
@@ -116,8 +123,24 @@ const LoginRoutes = {
element: <ForgotPassword_Callback/>
},
{
path: 'forgot/password/loginFail',
element: <IAmSmart_FailCallback/>
path: 'forgot/password/success',
element: <ForgotPassword_Success/>
},
{
path: 'forgot/username',
element: <ForgotUsername/>
},
{
path: 'forgot/username/sent',
element: <AfterForgotUsernamePage/>
},
{
path: 'forgot/username/verify/:verifyCode/:email',
element: <ForgotUsername_Callback/>
},
{
path: 'forgot/username/success',
element: <ForgotUsername_Success/>
},
]
};


+ 6
- 0
src/translations/en.json 查看文件

@@ -72,10 +72,16 @@
"newPassword": "New Password",
"setNewPassword": "Please enter new password",
"forgotUserPassword": "Forgot Password",
"forgotUsername": "Forgot Username",
"forgotPasswordTitle": "Find Your Account",
"forgotPasswordSubTitle": "Please enter your username to receive the code to reset your password",
"forgotPasswordSubTitle1": "Please enter your username to receive",
"forgotPasswordSubTitle2": "the code to reset your password",

"forgotUsernameSubTitle": "Please enter your email to receive the code to reset your password",
"forgotUsernameSubTitle1": "Please enter your email to receive",
"resetPasswordSuccess": "Password reset successfully.",
"securityCode": "Security Code",
"sentSecurityCode1": "We sent your code to your setting email",
"sentSecurityCode2": "Please check your emails for a message with your code.",


+ 2
- 0
src/translations/zh-CN.json 查看文件

@@ -72,10 +72,12 @@
"newPassword": "新密码",
"setNewPassword": "请输入新密码",
"forgotUserPassword": "忘记密码",
"forgotUsername": "忘记用户登入名称",
"forgotPasswordTitle": "寻找你的帐号",
"forgotPasswordSubTitle": "请输入你的用户登入名称以重设密码",
"forgotPasswordSubTitle1": "请输入你的用户登入名称收",
"forgotPasswordSubTitle2": "以重设密码",
"resetPasswordSuccess": "已成功重设密码。",
"securityCode": "安全验证码",
"sentSecurityCode1": "我们已将验证码送至你的电邮:",
"sentSecurityCode2": "请查看你的电子邮件信箱中是否有包含验证码的信件。",


+ 6
- 0
src/translations/zh-HK.json 查看文件

@@ -72,10 +72,16 @@
"newPassword": "新密碼",
"setNewPassword": "請輸入新密碼",
"forgotUserPassword": "忘記密碼",
"forgotUsername": "忘記用戶登入名稱",
"forgotPasswordTitle": "尋找你的帳號",
"forgotPasswordSubTitle": "請輸入你的用戶登入名稱以重設密碼",
"forgotPasswordSubTitle1": "請輸入你的用戶登入名稱",
"forgotPasswordSubTitle2": "以重設密碼",

"forgotUsernameSubTitle": "請輸入你的電郵以重設密碼",
"forgotUsernameSubTitle1": "請輸入你的電郵",
"resetPasswordSuccess": "已成功重設密碼。",
"securityCode": "安全驗證碼",
"sentSecurityCode1": "我們已將驗證碼送至你的電郵:",
"sentSecurityCode2": "請查看你的電子郵件信箱中是否有包含驗證碼的信件。",


+ 1
- 0
src/utils/ApiPathConst.js 查看文件

@@ -76,6 +76,7 @@ export const GET_VERIFY_USER_ACCOUNT = apiPath+'/user/verifyEmail';
export const GET_FORGOT_PASSWORD_VERIFY_USER_ACCOUNT = apiPath+'/user/verifyForgotPasswordEmail';
export const POST_FORGOT_PASSWORD_NEW_PASSWORD = apiPath+'/user/forgotPasswordNewPassword';
export const POST_FORGOT_PASSWORD_EMAIL = apiPath+'/user/sendForgotPasswordEmail';
export const POST_FORGOT_USERNAME_EMAIL = apiPath+'/user/sendForgotUserameEmail';


//Public


Loading…
取消
儲存