From ac0288418c369af9f6ed99f282b57bdb556440a0 Mon Sep 17 00:00:00 2001 From: Alex Cheung Date: Fri, 2 Feb 2024 17:56:11 +0800 Subject: [PATCH] add forgot username page --- src/assets/style/navbarStyles.css | 8 + src/layout/MainLayout/Header/index.js | 71 +-- .../AuthCallback/ResetPasswordSuccess.js | 134 +++++ .../ForgotPassword/AuthCallback/index.js | 51 +- .../ForgotPassword/ForgotPasswordApplyForm.js | 2 - .../ForgotUsername/AfterForgotPasswordPage.js | 159 ++++++ .../AuthCallback/ResetPasswordSuccess.js | 134 +++++ .../ForgotUsername/AuthCallback/index.js | 462 ++++++++++++++++++ .../ForgotUsername/ForgotUsernameApplyForm.js | 221 +++++++++ .../authentication/ForgotUsername/index.js | 49 ++ .../auth-forms/AuthLoginCustom.js | 7 +- src/routes/AfterLoginRoutes.js | 2 +- src/routes/LoginRoutes.js | 27 +- src/translations/en.json | 6 + src/translations/zh-CN.json | 2 + src/translations/zh-HK.json | 6 + src/utils/ApiPathConst.js | 1 + 17 files changed, 1269 insertions(+), 73 deletions(-) create mode 100644 src/pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess.js create mode 100644 src/pages/authentication/ForgotUsername/AfterForgotPasswordPage.js create mode 100644 src/pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess.js create mode 100644 src/pages/authentication/ForgotUsername/AuthCallback/index.js create mode 100644 src/pages/authentication/ForgotUsername/ForgotUsernameApplyForm.js create mode 100644 src/pages/authentication/ForgotUsername/index.js diff --git a/src/assets/style/navbarStyles.css b/src/assets/style/navbarStyles.css index 3555ab0..48fee66 100644 --- a/src/assets/style/navbarStyles.css +++ b/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; diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index ac9de32..7a33057 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -94,27 +94,27 @@ function Header(props) { Application
  • - Proof + Proof
  • - Payment + Payment
    • - Online Payment Record + Online Payment Record
    • - GFMIS Generate XML + GFMIS Generate XML
    • - Create Demand Note + Create Demand Note
    • - Demand Note + Demand Note
  • - Client + Client
    • Users (GLD) @@ -135,7 +135,7 @@ function Header(props) {
  • - Settings + Settings
    • Users Profile @@ -148,9 +148,11 @@ function Header(props) {
  • -
  • - Logout -
  • + +
  • + Logout +
  • +
    :
    @@ -271,11 +273,13 @@ function Header(props) { } -
  • - - - -
  • + +
  • + + + +
  • +
    ); @@ -301,9 +305,13 @@ function Header(props) { const drawer = ( isUserLoggedIn() ? - + {/* PNSPS - + */} + + + PNSPS +
      {loginContent} @@ -319,11 +327,12 @@ function Header(props) { : - - PNSPS - + + + PNSPS + -
        +
          {logoutContent}
        @@ -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%'}}} > @@ -389,12 +398,18 @@ function Header(props) { > - - + + - - - + + + + + + + + + diff --git a/src/pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess.js b/src/pages/authentication/ForgotPassword/AuthCallback/ResetPasswordSuccess.js new file mode 100644 index 0000000..05ba6b1 --- /dev/null +++ b/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 ? + + + + + + : + + +
        + + + + + +
        +
        + + *': { + flexGrow: 1, + flexBasis: '50%' + } + }} + content={false} + border={false} + boxShadow + > + + + {/* */} + + + + + + + + + + + + + +
        + ); +}; + +export default ResetPasswordSuccess; \ No newline at end of file diff --git a/src/pages/authentication/ForgotPassword/AuthCallback/index.js b/src/pages/authentication/ForgotPassword/AuthCallback/index.js index 62b2d93..ea9a78c 100644 --- a/src/pages/authentication/ForgotPassword/AuthCallback/index.js +++ b/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 = () => { - 驗證失敗,請聯絡相關的系統管理員協助。 + + + + */} + {/* + 申請公共啟事 + */} + + *': { + flexGrow: 1, + flexBasis: '50%' + } + }} + content={false} + border={false} + boxShadow + > + + + + + + + + + + + + + + + + + + {/* + + + + + + */} + + + + + + + + + + + + + + + + + + + + + + + + + + {/* + + + + + + */} + + + + + + + + + + + + + ); +}; + + +export default AfterForgotPasswordPage; diff --git a/src/pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess.js b/src/pages/authentication/ForgotUsername/AuthCallback/ResetPasswordSuccess.js new file mode 100644 index 0000000..05ba6b1 --- /dev/null +++ b/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 ? + + + + + + : + + +
        + + + + + +
        +
        + + *': { + flexGrow: 1, + flexBasis: '50%' + } + }} + content={false} + border={false} + boxShadow + > + + + {/* */} + + + + + + + + + + + + + +
        + ); +}; + +export default ResetPasswordSuccess; \ No newline at end of file diff --git a/src/pages/authentication/ForgotUsername/AuthCallback/index.js b/src/pages/authentication/ForgotUsername/AuthCallback/index.js new file mode 100644 index 0000000..ea9a78c --- /dev/null +++ b/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 ? + + + + + + : + + +
        + + + + + +
        +
        + {/* + + */} + {/* + 申請公共啟事 + */} + + *': { + flexGrow: 1, + flexBasis: '50%' + } + }} + content={false} + border={false} + boxShadow + > +
        + {verifyState ? + // SUCCESS page + + + + + + + + + + + + + + + + {/* + + + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + InputLabelProps={{ + shrink: true + }} + /> + + {formik.touched.emailVerifyHash && formik.errors.emailVerifyHash && ( + + {formik.errors.emailVerifyHash} + + )} + + */} + + + + + + + + + + + { + 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:( + + + {showPassword ? : } + + + ) + }} + /> + + {/* + + + + + + + + + + + */} + {formik.touched.password && formik.errors.password && ( + + {formik.errors.password} + + )} + + + + + + { + 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:( + + + {showConfirmPassword ? : } + + + ) + }} + /> + + {formik.touched.confirmPassword && formik.errors.confirmPassword && ( + + {formik.errors.confirmPassword} + + )} + + + + + + + + + : + // ERROR page + + + {/* */} + + + + + + + + + + + + } + + + + +
        +
        +
        +
        + ); +}; + +export default Index; \ No newline at end of file diff --git a/src/pages/authentication/ForgotUsername/ForgotUsernameApplyForm.js b/src/pages/authentication/ForgotUsername/ForgotUsernameApplyForm.js new file mode 100644 index 0000000..281a3e2 --- /dev/null +++ b/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 ( + + +
        + + + + + +
        +
        + + + + {/* + 申請公共啟事 + */} + + *': { + flexGrow: 1, + flexBasis: '50%' + } + }} + content={false} + border={false} + boxShadow + > +
        + + + + + + + + + + + + + + + + + + + + + + { + if (e.key === 'Enter') { + e.preventDefault(); + } + }, + }} + InputLabelProps={{ + shrink: true + }} + /> + + {formik.touched.emailAddress && formik.errors.emailAddress && ( + + {formik.errors.emailAddress} + + )} + + + + + + + + +
        +
        +
        +
        + setIsWarningPopUp(false)} + PaperProps={{ + sx: { + minWidth: '40vw', + maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, + maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } + } + }} + > + + + + + {/* {warningText} */} + + + + + +
        +
        + ); +}; + + +export default ForgotUsernameApplyForm; diff --git a/src/pages/authentication/ForgotUsername/index.js b/src/pages/authentication/ForgotUsername/index.js new file mode 100644 index 0000000..5467959 --- /dev/null +++ b/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 ? + + + + + + : + + ); +}; + + +export default ApplyForm; diff --git a/src/pages/authentication/auth-forms/AuthLoginCustom.js b/src/pages/authentication/auth-forms/AuthLoginCustom.js index 67d965c..20964b7 100644 --- a/src/pages/authentication/auth-forms/AuthLoginCustom.js +++ b/src/pages/authentication/auth-forms/AuthLoginCustom.js @@ -337,12 +337,17 @@ const AuthLoginCustom = () => { - + ? + + + ? + + diff --git a/src/routes/AfterLoginRoutes.js b/src/routes/AfterLoginRoutes.js index 4e745ef..e9ff126 100644 --- a/src/routes/AfterLoginRoutes.js +++ b/src/routes/AfterLoginRoutes.js @@ -61,7 +61,7 @@ const AfterLoginRoutes = { element: }, { - path: 'forgot/password/loginFail', + path: 'forgot/password/success', element: }, ] diff --git a/src/routes/LoginRoutes.js b/src/routes/LoginRoutes.js index f7fc1bb..9874ee3 100644 --- a/src/routes/LoginRoutes.js +++ b/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: }, { - path: 'forgot/password/loginFail', - element: + path: 'forgot/password/success', + element: + }, + { + path: 'forgot/username', + element: + }, + { + path: 'forgot/username/sent', + element: + }, + { + path: 'forgot/username/verify/:verifyCode/:email', + element: + }, + { + path: 'forgot/username/success', + element: }, ] }; diff --git a/src/translations/en.json b/src/translations/en.json index a28c0aa..b382907 100644 --- a/src/translations/en.json +++ b/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.", diff --git a/src/translations/zh-CN.json b/src/translations/zh-CN.json index 79b4610..0ea5812 100644 --- a/src/translations/zh-CN.json +++ b/src/translations/zh-CN.json @@ -72,10 +72,12 @@ "newPassword": "新密码", "setNewPassword": "请输入新密码", "forgotUserPassword": "忘记密码", + "forgotUsername": "忘记用户登入名称", "forgotPasswordTitle": "寻找你的帐号", "forgotPasswordSubTitle": "请输入你的用户登入名称以重设密码", "forgotPasswordSubTitle1": "请输入你的用户登入名称收", "forgotPasswordSubTitle2": "以重设密码", + "resetPasswordSuccess": "已成功重设密码。", "securityCode": "安全验证码", "sentSecurityCode1": "我们已将验证码送至你的电邮:", "sentSecurityCode2": "请查看你的电子邮件信箱中是否有包含验证码的信件。", diff --git a/src/translations/zh-HK.json b/src/translations/zh-HK.json index 1c860e4..a5d414c 100644 --- a/src/translations/zh-HK.json +++ b/src/translations/zh-HK.json @@ -72,10 +72,16 @@ "newPassword": "新密碼", "setNewPassword": "請輸入新密碼", "forgotUserPassword": "忘記密碼", + "forgotUsername": "忘記用戶登入名稱", "forgotPasswordTitle": "尋找你的帳號", "forgotPasswordSubTitle": "請輸入你的用戶登入名稱以重設密碼", "forgotPasswordSubTitle1": "請輸入你的用戶登入名稱", "forgotPasswordSubTitle2": "以重設密碼", + + "forgotUsernameSubTitle": "請輸入你的電郵以重設密碼", + "forgotUsernameSubTitle1": "請輸入你的電郵", + + "resetPasswordSuccess": "已成功重設密碼。", "securityCode": "安全驗證碼", "sentSecurityCode1": "我們已將驗證碼送至你的電郵:", "sentSecurityCode2": "請查看你的電子郵件信箱中是否有包含驗證碼的信件。", diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 73456ae..b4a50e3 100644 --- a/src/utils/ApiPathConst.js +++ b/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