Skip to content

Commit 27d7294

Browse files
author
alexdcdc
committed
reset password screens
1 parent b465797 commit 27d7294

4 files changed

Lines changed: 209 additions & 3 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
"use client";
2+
3+
import submitHandler from "@/util/formAction";
4+
import toast from "react-hot-toast";
5+
import { useApiClient } from "@/hooks/useApiClient";
6+
// import { useFetch } from "@/hooks/useFetch";
7+
import { useEffect, useState } from "react";
8+
import { useRouter, useSearchParams } from "next/navigation";
9+
import { CgSpinner } from "react-icons/cg";
10+
11+
export default function SignInPage() {
12+
const { apiClient } = useApiClient();
13+
const router = useRouter();
14+
const params = useSearchParams();
15+
const token = params.get("token") || "";
16+
const [isTokenValid, setIsTokenValid] = useState(false);
17+
18+
//DELETE THIS WHEN API ROUTE IS IMPLEMENTED
19+
useEffect(() => {
20+
setIsTokenValid(true);
21+
console.log(token);
22+
}, [setIsTokenValid, token]);
23+
24+
const isLoading = false; //DELETE THIS LINE WHEN API ROUTE IS IMPLEMENTED
25+
/*
26+
const { isLoading } = useFetch(`/api/reset-password/verify?token=${token}`, {
27+
onSuccess: () => {
28+
setIsTokenValid(true);
29+
},
30+
onError: () => {
31+
toast.error("Error while validating token");
32+
},
33+
});
34+
*/
35+
36+
const handleSubmit = submitHandler(async (formData: FormData) => {
37+
try {
38+
const password = formData.get("password");
39+
const confirmPassword = formData.get("confirmPassword");
40+
if (!password || !confirmPassword || password != confirmPassword) {
41+
toast.error("Passwords do not match");
42+
return;
43+
}
44+
45+
// Uncomment when API route is implemented
46+
/*
47+
await apiClient.post("/api/reset-password/change", {
48+
body: new URLSearchParams({
49+
password: password as string,
50+
token: token,
51+
}).toString(),
52+
});
53+
*/
54+
55+
console.log(formData, apiClient);
56+
toast.success("Password reset successfully!");
57+
router.push("/signIn");
58+
} catch (e) {
59+
toast.error("Unknown error");
60+
console.error(e);
61+
}
62+
});
63+
64+
return (
65+
<main className="bg-gradient-to-tr from-[#4AA6EB] to-[#F0424E] w-screen h-screen flex flex-col justify-center items-center">
66+
<div className="bg-white py-6 px-6 rounded-xl">
67+
<div className="flex flex-col justify-center items-center">
68+
{/* eslint-disable-next-line @next/next/no-img-element */}
69+
<img src="/logo.svg" alt="Hope for Haiti Logo" className="mb-4" />
70+
<h1 className="mb-1 text-xl font-semibold">Reset Password</h1>
71+
<h2 className="mb-4 text-gray-800 opacity-70 font-light text-sm whitespace-normal w-64 sm:w-80">
72+
Please enter your new password.
73+
</h2>
74+
</div>
75+
{isLoading && <CgSpinner />}
76+
{!isLoading && isTokenValid && (
77+
<form onSubmit={handleSubmit} className="w-64 sm:w-80">
78+
<div className="mb-4">
79+
<label
80+
className="block text-gray-800 text-sm mb-2 font-light"
81+
htmlFor="password"
82+
>
83+
Password
84+
</label>
85+
<input
86+
className="bg-zinc-50 appearance-none border-gray-200 rounded w-full py-2 px-3 text-gray-700 leading-tight font-light text-sm"
87+
id="password"
88+
name="password"
89+
type="password"
90+
placeholder="Password"
91+
autoComplete="new-password"
92+
required
93+
/>
94+
</div>
95+
<div className="mb-4">
96+
<label
97+
className="block text-gray-800 text-sm mb-2 font-light"
98+
htmlFor="confirmPassword"
99+
>
100+
Confirm Password
101+
</label>
102+
<input
103+
className="bg-zinc-50 appearance-none border-gray-200 rounded w-full py-2 px-3 text-gray-700 leading-tight font-light text-sm"
104+
id="confirmPassword"
105+
name="confirmPassword"
106+
type="password"
107+
placeholder="Confirm Password"
108+
autoComplete="new-password"
109+
required
110+
/>
111+
</div>
112+
<button
113+
className="w-full bg-red-500 hover:bg-red-700 text-white py-1 px-4 mt-7 rounded focus:outline-none focus:shadow-outline"
114+
type="submit"
115+
>
116+
Reset password
117+
</button>
118+
</form>
119+
)}
120+
</div>
121+
</main>
122+
);
123+
}

‎src/app/reset-password/page.tsx‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
"use client";
2+
3+
import submitHandler from "@/util/formAction";
4+
import Link from "next/link";
5+
import toast from "react-hot-toast";
6+
import { useApiClient } from "@/hooks/useApiClient";
7+
import { useState } from "react";
8+
9+
export default function SignInPage() {
10+
const { apiClient } = useApiClient();
11+
const [submitted, setSubmitted] = useState(false);
12+
const handleSubmit = submitHandler(async (formData: FormData) => {
13+
try {
14+
// Uncomment below when api route is finished
15+
/*
16+
await apiClient.post("/api/reset-password", {
17+
body: formData,
18+
});
19+
*/
20+
console.log(formData, apiClient);
21+
setSubmitted(true);
22+
} catch (e) {
23+
toast.error("Unknown error");
24+
console.error(e);
25+
}
26+
});
27+
28+
return (
29+
<main className="bg-gradient-to-tr from-[#4AA6EB] to-[#F0424E] w-screen h-screen flex flex-col justify-center items-center">
30+
<div className="bg-white py-6 px-6 rounded-xl">
31+
<div className="flex flex-col justify-center items-center">
32+
{/* eslint-disable-next-line @next/next/no-img-element */}
33+
<img src="/logo.svg" alt="Hope for Haiti Logo" className="mb-4" />
34+
<h1 className="mb-1 text-xl font-semibold">Forgot Password</h1>
35+
<h2 className="mb-4 text-gray-800 opacity-70 font-light text-sm whitespace-normal w-64 sm:w-80">
36+
Please enter your email and we will send you a recovery link.
37+
</h2>
38+
</div>
39+
{!submitted ? (
40+
<form onSubmit={handleSubmit} className="w-64 sm:w-80">
41+
<div className="mb-4">
42+
<label
43+
className="block text-gray-800 text-sm mb-2 font-light"
44+
htmlFor="email"
45+
>
46+
Email
47+
</label>
48+
<input
49+
className="bg-zinc-50 appearance-none border-gray-200 rounded w-full py-2 px-3 text-gray-700 leading-tight font-light text-sm"
50+
id="email"
51+
name="email"
52+
type="email"
53+
placeholder="Email"
54+
required
55+
/>
56+
</div>
57+
<button
58+
className="w-full bg-red-500 hover:bg-red-700 text-white py-1 px-4 mt-7 rounded focus:outline-none focus:shadow-outline"
59+
type="submit"
60+
>
61+
Send recovery link
62+
</button>
63+
<Link href="/signIn">
64+
<button
65+
className="w-full bg-white hover:bg-gray-200 text-red-500 py-1 px-4 mt-2 rounded focus:outline-none focus:shadow-outline"
66+
type="submit"
67+
>
68+
Return to login
69+
</button>
70+
</Link>
71+
</form>
72+
) : (
73+
<div>Password reset email sent. Please check your inbox.</div>
74+
)}
75+
</div>
76+
</main>
77+
);
78+
}

‎src/app/signIn/page.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export default function SignInPage() {
8787
</label>
8888
</div>
8989
<div>
90-
<Link href={"/signIn"} className="text-red-500 text-xs">
90+
<Link href={"/reset-password"} className="text-red-500 text-xs">
9191
Forgot Password
9292
</Link>
9393
</div>

‎src/components/AuthenticationProvider.tsx‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ function VerifyAuthentication({
1414
const pathName = usePathname();
1515
const { loading, user } = useUser();
1616
const router = useRouter();
17-
18-
const onAuthPages = pathName === "/signIn" || pathName === "/register";
17+
const authPages = [
18+
"/signIn",
19+
"/register",
20+
"/reset-password",
21+
"/reset-password/change",
22+
];
23+
const onAuthPages = authPages.includes(pathName);
1924

2025
useEffect(() => {
2126
if (loading) return;

0 commit comments

Comments
 (0)