Refactor PasswordPanel to pass navigation context via state to ForgotPassword using TextLink | Update ForgotPassword and CheckEmail to handle navigation context for Back links, ensuring users return to the correct page after password reset | Fix TextLink prop usage to avoid warnings by passing state and href correctly | Ensure error messages and navigation links use translation keys for localization
This commit is contained in:
1 parent
f564636cb4
commit
4ce4a124d6
5 files changed
+41
-11
No files matched your search
@@ -5,7 +5,7 @@ import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
|
||||
const TextLink = ({ text, linkText, href, target = "_self" }) => {
|
||||
const TextLink = ({ text, linkText, href, state, target = "_self" }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
@@ -19,6 +19,7 @@ const TextLink = ({ text, linkText, href, target = "_self" }) => {
|
||||
to={href}
|
||||
component={RouterLink}
|
||||
target={target}
|
||||
state={state}
|
||||
>
|
||||
{linkText}
|
||||
</Link>
|
||||
@@ -30,6 +31,7 @@ TextLink.propTypes = {
|
||||
text: PropTypes.string,
|
||||
linkText: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
state: PropTypes.object,
|
||||
target: PropTypes.string,
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ import { getTouchedFieldErrors } from "../../../Validation/error.js";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { clearAuthState } from "../../../Features/Auth/authSlice.js";
|
||||
import TextLink from "@/Components/v1/TextLink/index.jsx";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
const defaultPasswordsState = {
|
||||
password: "",
|
||||
@@ -31,6 +33,7 @@ const PasswordPanel = () => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const SPACING_GAP = theme.spacing(12);
|
||||
|
||||
@@ -267,8 +270,15 @@ const PasswordPanel = () => {
|
||||
)}
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<TextLink
|
||||
text={t("passwordPanel.forgotPasswordText", "Forgot password?")}
|
||||
linkText={t("passwordPanel.resetPasswordText", "Reset password")}
|
||||
state={{ from: location.pathname }}
|
||||
href={"/forgot-password"}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
@@ -281,7 +291,6 @@ const PasswordPanel = () => {
|
||||
}
|
||||
sx={{
|
||||
px: theme.spacing(12),
|
||||
mt: theme.spacing(20),
|
||||
}}
|
||||
>
|
||||
{t("commonSave", "Save")}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Box, Button, Stack, Typography } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { createToast } from "../../Utils/toastUtils.jsx";
|
||||
import { forgotPassword } from "../../Features/Auth/authSlice.js";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
@@ -17,6 +17,7 @@ const CheckEmail = () => {
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
|
||||
const [email, setEmail] = useState();
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
@@ -83,7 +84,9 @@ const CheckEmail = () => {
|
||||
|
||||
const handleNavigate = () => {
|
||||
sessionStorage.removeItem("email");
|
||||
navigate("/login");
|
||||
location.state?.from
|
||||
? navigate(location.state.from, { replace: true })
|
||||
: navigate("/login");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -219,7 +222,11 @@ const CheckEmail = () => {
|
||||
>
|
||||
<Typography display="inline-block">
|
||||
<Trans
|
||||
i18nKey="auth.forgotPassword.links.login"
|
||||
i18nKey={
|
||||
location.state?.from === "/account/password"
|
||||
? "auth.forgotPassword.links.accountPassword"
|
||||
: "auth.forgotPassword.links.login"
|
||||
}
|
||||
components={{
|
||||
a: (
|
||||
<Typography
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from "react-redux";
|
||||
import { forgotPassword } from "../../Features/Auth/authSlice.js";
|
||||
import { useEffect, useState } from "react";
|
||||
import { newOrChangedCredentials } from "../../Validation/validation.js";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx";
|
||||
import Logo from "@/assets/icons/checkmate-icon.svg?react";
|
||||
import Background from "@/assets/Images/background-grid.svg?react";
|
||||
@@ -18,6 +18,7 @@ const ForgotPassword = () => {
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const theme = useTheme();
|
||||
const location = useLocation();
|
||||
|
||||
const { isLoading } = useSelector((state) => state.auth);
|
||||
const [errors, setErrors] = useState({});
|
||||
@@ -51,11 +52,13 @@ const ForgotPassword = () => {
|
||||
const action = await dispatch(forgotPassword(form));
|
||||
if (action.payload.success) {
|
||||
sessionStorage.setItem("email", form.email);
|
||||
navigate("/check-email");
|
||||
navigate("/check-email", {
|
||||
state: location.state || { from: "/login" } // Preserve original from, fallback to login
|
||||
});
|
||||
createToast({
|
||||
body: t("auth.forgotPassword.toasts.sent").replace("<email/>", form.email),
|
||||
});
|
||||
} else {
|
||||
} else {
|
||||
if (action.payload) {
|
||||
// dispatch errors
|
||||
createToast({
|
||||
@@ -86,7 +89,9 @@ const ForgotPassword = () => {
|
||||
|
||||
const handleNavigate = () => {
|
||||
sessionStorage.removeItem("email");
|
||||
navigate("/login");
|
||||
location.state?.from
|
||||
? navigate(location.state.from, { replace: true })
|
||||
: navigate("/login");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -212,7 +217,11 @@ const ForgotPassword = () => {
|
||||
>
|
||||
<Typography display="inline-block">
|
||||
<Trans
|
||||
i18nKey="auth.forgotPassword.links.login"
|
||||
i18nKey={
|
||||
location.state?.from
|
||||
? "auth.forgotPassword.links.accountPassword"
|
||||
: "auth.forgotPassword.links.login"
|
||||
}
|
||||
components={{
|
||||
a: (
|
||||
<Typography
|
||||
|
||||
@@ -547,6 +547,7 @@
|
||||
"incidentsPageTitle": "Incidents",
|
||||
"checksPageTitle": "Checks",
|
||||
"passwordPanel": {
|
||||
"forgotPasswordText": "Forgot password?",
|
||||
"passwordChangedSuccess": "Your password was changed successfully.",
|
||||
"passwordInputIncorrect": "Your password input was incorrect.",
|
||||
"currentPassword": "Current password",
|
||||
@@ -555,6 +556,7 @@
|
||||
"enterNewPassword": "Enter your new password",
|
||||
"confirmNewPassword": "Confirm new password",
|
||||
"passwordRequirements": "New password must contain at least 8 characters and must have at least one uppercase letter, one lowercase letter, one number and one special character (!?@#$%^&*()-_=+[]{}|;:'\",./\\~`).",
|
||||
"resetPasswordText": "Reset password",
|
||||
"sessionExpired": "Your session has expired, please log in again to continue."
|
||||
},
|
||||
"emailSent": "Email sent successfully",
|
||||
@@ -744,6 +746,7 @@
|
||||
},
|
||||
"links": {
|
||||
"login": "Go back to <a>Log In</a>",
|
||||
"accountPassword": "Go back to <a>Account Password</a>",
|
||||
"resend": "Didn't receive the email? <a>Click to resend</a>"
|
||||
},
|
||||
"toasts": {
|
||||
|
||||
Reference in new issue
Block a user