Skip to content

Commit

Permalink
Forget and Reset password page design completed
Browse files Browse the repository at this point in the history
  • Loading branch information
Md-Rubel-Ahmed-Rana committed Jul 6, 2024
1 parent 52781b4 commit 80684ff
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 3 deletions.
60 changes: 60 additions & 0 deletions frontend/src/components/pages/forgetPassword/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useRouter } from "next/router";
import { SubmitHandler, useForm } from "react-hook-form";

type FormData = {
email: string;
};

const ForgetPasswordPage = () => {
const router = useRouter();
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormData>({ mode: "onChange" });
const handleSubmitEmail: SubmitHandler<FormData> = (data) => {
router.push("/reset-password");
};
return (
<div className="h-screen flex items-center justify-center">
<div className="bg-gray-50 p-8 rounded shadow-md w-full max-w-md">
<h1 className="text-2xl font-bold mb-4">Forgot Password</h1>
<p className="mb-4 text-gray-600">
Enter your email to reset your password.
</p>
<form onSubmit={handleSubmit(handleSubmitEmail)}>
<div className="mb-4">
<input
autoFocus
type="email"
{...register("email", {
required: "Email is required",
pattern: {
value: /\S+@\S+\.\S+/,
message: "Invalid email address",
},
})}
className={`appearance-none dark:text-white rounded-md relative block w-full px-3 py-2 border ${
errors.email ? "border-red-500" : "border-gray-300"
} placeholder-gray-500 text-gray-900 rounded-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm`}
placeholder="Enter your email"
/>
{errors.email && (
<p className="mt-2 text-sm text-red-500">
{errors.email.message}
</p>
)}
</div>
<button
type="submit"
className={`w-full text-white py-2 px-4 rounded bg-blue-500 hover:bg-blue-600`}
>
Submit
</button>
</form>
</div>
</div>
);
};

export default ForgetPasswordPage;
9 changes: 6 additions & 3 deletions frontend/src/components/pages/login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,13 @@ const Login = () => {
</button>
</div>
</div>
<div className="text-center my-4">
<button className="outline-none" type="button">
<div className="my-4">
<Link
className="text-sm text-blue-500 underline"
href={"/forget-password"}
>
Forget password?
</button>
</Link>
</div>
<div className="mt-6">
<button
Expand Down
132 changes: 132 additions & 0 deletions frontend/src/components/pages/resetPassword/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { useRouter } from "next/router";
import { useState } from "react";
import { IoMdEye, IoMdEyeOff } from "react-icons/io";
import { SubmitHandler, useForm } from "react-hook-form";
import Swal from "sweetalert2";

type FormData = {
password: string;
confirmPassword: string;
};

const ResetPasswordPage = () => {
const router = useRouter();
const [togglePassword, setTogglePassword] = useState<{
password: boolean;
confirmPassword: boolean;
}>({
password: false,
confirmPassword: false,
});
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm<FormData>({ mode: "onChange" });
const handleResetPassword: SubmitHandler<FormData> = (data) => {
Swal.fire({
position: "center",
icon: "success",
title: "Password reset successful",
text: "Now, try to login with new password",
showConfirmButton: false,
timer: 2000,
});
router.push("/login");
};

const handleTogglePassword = (type: string) => {
if (type === "password") {
setTogglePassword((prev) => ({ ...prev, password: !prev.password }));
} else {
setTogglePassword((prev) => ({
...prev,
confirmPassword: !prev.confirmPassword,
}));
}
};

const password = watch("password");

return (
<div className="h-screen flex items-center justify-center">
<div className="bg-gray-50 p-8 rounded shadow-md w-full max-w-md">
<h1 className="text-2xl font-bold mb-2">Reset Password</h1>
<p className="mb-2 text-gray-600">Change your password carefully</p>
<form onSubmit={handleSubmit(handleResetPassword)}>
<div className="-mt-px relative mb-4">
<label htmlFor="password">Password</label>
<input
aria-label="Password"
type={togglePassword.password ? "text" : "password"}
{...register("password", {
required: "Password is required",
minLength: {
value: 6,
message: "Password must be at least 6 characters",
},
})}
className={`appearance-none dark:text-white rounded-md relative block w-full px-3 py-2 border ${
errors.password ? "border-red-500" : "border-gray-300"
} placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm`}
placeholder="Enter a new password"
/>
{errors.password && (
<p className="mt-2 text-sm text-red-500">
{errors.password.message}
</p>
)}
<button
type="button"
className="absolute top-9 right-2 z-50"
onClick={() => handleTogglePassword("password")}
>
{togglePassword.password ? <IoMdEye /> : <IoMdEyeOff />}
</button>
</div>
<div className="-mt-px relative mb-4">
<label htmlFor="confirmPassword">Confirm Password</label>
<input
aria-label="Confirm Password"
type={togglePassword.confirmPassword ? "text" : "password"}
{...register("confirmPassword", {
required: "Confirm Password is required",
minLength: {
value: 6,
message: "Confirm Password must be at least 6 characters",
},
validate: (value) =>
value === password || "Passwords do not match",
})}
className={`appearance-none dark:text-white rounded-md relative block w-full px-3 py-2 border ${
errors.confirmPassword ? "border-red-500" : "border-gray-300"
} placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm`}
placeholder="Enter a new password"
/>
{errors.confirmPassword && (
<p className="mt-2 text-sm text-red-500">
{errors.confirmPassword.message}
</p>
)}
<button
type="button"
className="absolute top-9 right-2 z-50"
onClick={() => handleTogglePassword("confirmPassword")}
>
{togglePassword.confirmPassword ? <IoMdEye /> : <IoMdEyeOff />}
</button>
</div>
<button
type="submit"
className={`w-full text-white py-2 px-4 rounded bg-blue-500 hover:bg-blue-600`}
>
Reset Password
</button>
</form>
</div>
</div>
);
};

export default ResetPasswordPage;
14 changes: 14 additions & 0 deletions frontend/src/pages/forget-password/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ForgetPasswordPage from "@/components/pages/forgetPassword";
import RootLayout from "@/layout/RootLayout";
import { NextPageWithLayout } from "pages/_app";
import React, { ReactElement } from "react";

const ForgetPassword: NextPageWithLayout = () => {
return <ForgetPasswordPage />;
};

export default ForgetPassword;

ForgetPassword.getLayout = function (page: ReactElement) {
return <RootLayout>{page}</RootLayout>;
};
14 changes: 14 additions & 0 deletions frontend/src/pages/reset-password/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ResetPasswordPage from "@/components/pages/resetPassword";
import RootLayout from "@/layout/RootLayout";
import { NextPageWithLayout } from "pages/_app";
import React, { ReactElement } from "react";

const ResetPassword: NextPageWithLayout = () => {
return <ResetPasswordPage />;
};

export default ResetPassword;

ResetPassword.getLayout = function (page: ReactElement) {
return <RootLayout>{page}</RootLayout>;
};

0 comments on commit 80684ff

Please sign in to comment.