Commit ed8c6b3c by asranov0003

feat: add recover password page

parent e599a481
import React from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import {
useAppDispatch,
useAppSelector,
type RootState,
} from "../../stores/store";
import { useForm } from "react-hook-form";
import { authRecover } from "../../stores/slices/authSlice";
import AuthHeader from "../Auth/AuthHeader";
import CInput from "../../components/CInput";
import CButton from "../../components/CButton";
interface IRecoverFormData {
login: string;
newPassword: string;
repeatPassword: string;
}
const RecoverPasswor: React.FC = () => {
const { t } = useTranslation();
const navigate = useNavigate();
const dispatch = useAppDispatch();
const { loadingRecover, errorRecover, successRecover } = useAppSelector(
(state: RootState) => state.auth
);
const {
register,
handleSubmit,
formState: { errors },
watch,
} = useForm<IRecoverFormData>();
const newPasswordValue = watch("newPassword");
const onSubmit = async (data: IRecoverFormData) => {
dispatch(authRecover(data));
};
return (
<div className="wrapper recover">
<AuthHeader back onBack={() => navigate("/settings")} />
<h2>{t("auth.passwordRecovery")}</h2>
<form className="auth__form" onSubmit={handleSubmit(onSubmit)}>
<CInput
label={`${t("auth.login")}`}
placeholder={`${t("auth.loginPlaceholder")}`}
{...register("login", { required: t("error.requiredField") })}
error={errors.login?.message as string}
/>
<CInput
label={`${t("auth.newPassword")}`}
placeholder={`${t("auth.newPasswordPlaceholder")}`}
type="password"
{...register("newPassword", { required: t("error.requiredField") })}
error={errors.newPassword?.message as string}
/>
<CInput
label={`${t("auth.repeatPassword")}`}
placeholder={`${t("auth.repeatPasswordPlaceholder")}`}
type="password"
{...register("repeatPassword", {
required: t("error.requiredField"),
validate: (value) =>
value === newPasswordValue || t("auth.passwordsDoNotMatch"),
})}
error={errors.repeatPassword?.message as string}
/>
{successRecover && (
<p className="text-success text-center">{successRecover}</p>
)}
{errorRecover && (
<p className="text-danger text-center">{errorRecover}</p>
)}
<CButton title={`${t("button.continue")}`} isLoading={loadingRecover} />
</form>
</div>
);
};
export default RecoverPasswor;
export { default } from "./RecoverPassword";
......@@ -19,6 +19,8 @@
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
color: var(--text-color);
cursor: pointer;
}
......
......@@ -12,6 +12,7 @@ import { useAppDispatch } from "../../stores/store";
import { logout } from "../../stores/slices/authSlice";
import CModal from "../../components/CModal";
import CButton from "../../components/CButton";
import { Link } from "react-router-dom";
const Settings: React.FC = () => {
const [isOpenLogoutModal, setIsOpenLogoutModal] = useState(false);
......@@ -64,10 +65,13 @@ const Settings: React.FC = () => {
{t("settings.deleteAccount")}
</div>
<div className="settings__content__action">
<Link
to={"/settings/recover-password"}
className="settings__content__action"
>
<IoKeyOutline className="settings__content__action__icon" />{" "}
{t("settings.recoverPassword")}
</div>
</Link>
<div className="settings__content__action" onClick={toggleLogoutModal}>
<MdOutlineLogout className="settings__content__action__icon" />{" "}
......
......@@ -28,6 +28,7 @@ import BlockApps from "../pages/BlockApps";
import UsageLimits from "../pages/UsageLimits";
import Terms from "../pages/Auth/Terms";
import Privacy from "../pages/Auth/Privacy";
import RecoverPassword from "../pages/RecoverPassword";
const Router: React.FC = () => {
const isAuthenticated = !!localStorage.getItem(`token-${TG_USER_ID}`);
......@@ -129,6 +130,16 @@ const Router: React.FC = () => {
],
},
{
path: "/settings",
element: <ProtectedRoute element={<Outlet />} redirectTo="/" />,
children: [
{
path: "recover-password",
element: <RecoverPassword />,
},
],
},
{
path: "/pincode",
element: <Pincode />,
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment