From a8de8476e581fd9d0f93497da7ff9d673ab6b611 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Mon, 20 Nov 2023 00:00:30 +0800 Subject: [PATCH] Added reset password modal and confirm reset password page --- src/App.tsx | 10 ++ src/Components/API/API.tsx | 32 +++- src/Components/LoginModal/LoginModal.tsx | 10 -- .../ResetPasswordModal/ResetPasswordModal.tsx | 91 +++++++++++ src/Components/Types/Types.tsx | 6 + src/Pages/ActivationPage/ActivationPage.tsx | 10 ++ src/Pages/LandingPage/LandingPage.tsx | 46 +++++- .../ResetPasswordPage/ResetPasswordPage.tsx | 148 ++++++++++++++++++ 8 files changed, 335 insertions(+), 18 deletions(-) create mode 100644 src/Components/ResetPasswordModal/ResetPasswordModal.tsx create mode 100644 src/Pages/ResetPasswordPage/ResetPasswordPage.tsx diff --git a/src/App.tsx b/src/App.tsx index 6db1229..9cf4075 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import ErrorPage from "./Pages/ErrorPage/ErrorPage"; import DashboardPage from "./Pages/DashboardPage/DashboardPage"; import Revalidator from "./Components/Revalidator/Revalidator"; import ActivationPage from "./Pages/ActivationPage/ActivationPage"; +import ResetPasswordPage from "./Pages/ResetPasswordPage/ResetPasswordPage"; const queryClient = new QueryClient(); const router = createHashRouter([ @@ -42,6 +43,15 @@ const router = createHashRouter([ ), errorElement: , }, + { + path: "/reset_password_confirm/:uid/:token", + element: ( + <> + + + ), + errorElement: , + }, ]); export default function App() { diff --git a/src/Components/API/API.tsx b/src/Components/API/API.tsx index 2b22ca5..29fdaee 100644 --- a/src/Components/API/API.tsx +++ b/src/Components/API/API.tsx @@ -1,6 +1,11 @@ /* eslint-disable react-refresh/only-export-components */ import axios from "axios"; -import { ActivationType, LoginType, RegisterType } from "../Types/Types"; +import { + ActivationType, + LoginType, + RegisterType, + ResetPasswordConfirmType, +} from "../Types/Types"; const instance = axios.create({ baseURL: "http://localhost:8000/", @@ -130,3 +135,28 @@ export function ActivationAPI(activation: ActivationType) { return false; }); } +export function ResetPasswordAPI(email: string) { + return instance + .post("api/v1/accounts/users/reset_password/", { email: email }) + .then(() => { + console.log("Activation Success"); + return true; + }) + .catch(() => { + console.log("Activation failed"); + return false; + }); +} + +export function ResetPasswordConfirmAPI(info: ResetPasswordConfirmType) { + return instance + .post("api/v1/accounts/users/reset_password_confirm/", info) + .then(() => { + console.log("Reset Success"); + return true; + }) + .catch(() => { + console.log("Reset failed"); + return false; + }); +} diff --git a/src/Components/LoginModal/LoginModal.tsx b/src/Components/LoginModal/LoginModal.tsx index 6cc9459..fb6a5c0 100644 --- a/src/Components/LoginModal/LoginModal.tsx +++ b/src/Components/LoginModal/LoginModal.tsx @@ -106,16 +106,6 @@ export default function LoginModal() { />

Remember me

-
-

- Forgot password? -

-
+
+ +

Forgot Password

+
+

+ Enter your email to request a password reset +

+
+ ) => { + setEmail(e.target.value); + setError(""); + }} + value={email} + placeholder={"Enter email associated with account"} + /> +

{error}

+
+
+ + ); +} diff --git a/src/Components/Types/Types.tsx b/src/Components/Types/Types.tsx index 784a3b6..efcb59a 100644 --- a/src/Components/Types/Types.tsx +++ b/src/Components/Types/Types.tsx @@ -16,6 +16,12 @@ export type ActivationType = { token: string; }; +export type ResetPasswordConfirmType = { + uid: string; + token: string; + new_password: string; +}; + export type AddEquipmentType = { name: string; remarks: string; diff --git a/src/Pages/ActivationPage/ActivationPage.tsx b/src/Pages/ActivationPage/ActivationPage.tsx index 3117228..e95cf28 100644 --- a/src/Pages/ActivationPage/ActivationPage.tsx +++ b/src/Pages/ActivationPage/ActivationPage.tsx @@ -27,6 +27,16 @@ export default function ActivationPage() { progress: undefined, theme: "light", }); + toast("Please login to continue", { + position: "top-right", + autoClose: 6000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "light", + }); setTimeout(() => { navigate("/dashboard"); }); diff --git a/src/Pages/LandingPage/LandingPage.tsx b/src/Pages/LandingPage/LandingPage.tsx index ea0ac88..8c1d046 100644 --- a/src/Pages/LandingPage/LandingPage.tsx +++ b/src/Pages/LandingPage/LandingPage.tsx @@ -9,9 +9,11 @@ import RegisterModal from "../../Components/RegisterModal/RegisterModal"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { RootState } from "../../Components/Plugins/Redux/Store/Store"; +import ResetPasswordModal from "../../Components/ResetPasswordModal/ResetPasswordModal"; export default function LandingPage() { - const [LoginModalOpen, SetLoginModalOpen] = useState(false); - const [RegisterModalOpen, SetRegisterModalOpen] = useState(false); + const [loginmodalOpen, SetloginmodalOpen] = useState(false); + const [registermodalOpen, SetRegisterModalOpen] = useState(false); + const [resetmodalOpen, SetResetModalOpen] = useState(false); const authenticated = useSelector((state: RootState) => state.auth.value); const navigate = useNavigate(); @@ -68,8 +70,9 @@ export default function LandingPage() { type={"light"} label={"Login"} onClick={() => { - SetLoginModalOpen(true); + SetloginmodalOpen(true); SetRegisterModalOpen(false); + SetResetModalOpen(false); }} />
diff --git a/src/Pages/ResetPasswordPage/ResetPasswordPage.tsx b/src/Pages/ResetPasswordPage/ResetPasswordPage.tsx new file mode 100644 index 0000000..c70bdde --- /dev/null +++ b/src/Pages/ResetPasswordPage/ResetPasswordPage.tsx @@ -0,0 +1,148 @@ +import { useNavigate, useParams } from "react-router-dom"; +import styles, { colors } from "../../styles"; +import { ResetPasswordConfirmAPI } from "../../Components/API/API"; +import { useState } from "react"; +import { toast } from "react-toastify"; +import { VisibilityOff, Visibility } from "@mui/icons-material"; +import { TextField, InputAdornment, IconButton } from "@mui/material"; +import Button from "../../Components/Button/Button"; +export default function ResetPasswordPage() { + const { uid, token } = useParams(); + const [feedback, setFeedback] = useState(""); + const [user, setUser] = useState({ + password: "", + confirm_password: "", + }); + const [showPassword, setShowPassword] = useState(false); + const navigate = useNavigate(); + return ( +
+
+

+ Confirm Password Reset +

+ + { + setShowPassword(!showPassword); + setFeedback(""); + }} + edge="end" + > + {showPassword ? : } + + + ), + }} + label="New Password" + placeholder={"Enter new password"} + onChange={(e: React.ChangeEvent) => + setUser({ ...user, password: e.target.value }) + } + value={user.password} + /> + + { + setShowPassword(!showPassword); + setFeedback(""); + }} + edge="end" + > + {showPassword ? : } + + + ), + }} + label="Confirm Password" + placeholder={"Re-enter password"} + onChange={(e: React.ChangeEvent) => + setUser({ ...user, password: e.target.value }) + } + value={user.password} + /> +
+
{" "} +
+ +

{feedback}

+
+
+ ); +}