Skip to content

Commit 775612d

Browse files
authored
Merge pull request #58 from Seyi-Amusan/feature-verify-reset-otp-integration
Feature verify reset otp integration
2 parents 354f3bc + e4d2258 commit 775612d

File tree

5 files changed

+125
-30
lines changed

5 files changed

+125
-30
lines changed

LEADERBOARD.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# GitHub Leaderboard
32

43
🏆 **Welcome to the Official Leaderboard!** 🏆
@@ -18,5 +17,4 @@ A heartfelt **thank you** to all our fantastic contributors for their hard work
1817

1918
---
2019

21-
*Want to see your name on the leaderboard? Contribute to our project on [GitHub](https://github.com/mlsanigeria/speak-to-docs) and make an impact!*
22-
20+
_Want to see your name on the leaderboard? Contribute to our project on [GitHub](https://github.com/mlsanigeria/speak-to-docs) and make an impact!_

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Watch our info session on how to get started with Hacktoberfest and contribute t
8888
We maintain a leaderboard to track your contributions and their impact on our projects. The more you contribute, the higher you'll climb on the leaderboard.
8989

9090
<!-- Section Start -->
91+
9192
### Top 10 Contributors
9293

9394
Thank you to all our fantastic contributors for their hard work and dedication! Here are our top 10 contributors:

src/app/reset-password/page.tsx

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/app/verify-reset-otp/page.tsx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"use client";
2+
3+
import { Suspense, useState } from "react";
4+
import { useRouter, useSearchParams } from "next/navigation";
5+
import { Button } from "@/components/ui/button";
6+
import { Input } from "@/components/ui/input";
7+
import { toast } from "sonner";
8+
9+
function VerifyResetOtpContent() {
10+
const router = useRouter();
11+
const searchParams = useSearchParams();
12+
const email = searchParams.get("email") || localStorage.getItem("resetEmail");
13+
14+
const [otp, setOtp] = useState("");
15+
const [loading, setLoading] = useState(false);
16+
17+
const handleSubmit = async (e: React.FormEvent) => {
18+
e.preventDefault();
19+
20+
if (!/^\d{6}$/.test(otp)) {
21+
toast.error("Please enter a valid 6-digit numeric code");
22+
return;
23+
}
24+
25+
if (!email) {
26+
toast.error(
27+
"Email not found. Please restart the password reset process.",
28+
);
29+
return;
30+
}
31+
32+
setLoading(true);
33+
34+
try {
35+
const response = await fetch(
36+
`${process.env.NEXT_PUBLIC_API_URL}/verify_reset_otp`,
37+
{
38+
method: "POST",
39+
headers: { "Content-Type": "application/json" },
40+
body: JSON.stringify({ email, otp }),
41+
},
42+
);
43+
44+
const data = await response.json();
45+
46+
if (response.ok) {
47+
localStorage.setItem("resetEmail", email);
48+
toast.success("OTP verified successfully!");
49+
router.push(`/new-password?email=${encodeURIComponent(email)}`);
50+
} else {
51+
const errorMsg = Array.isArray(data.detail)
52+
? data.detail[0]?.msg
53+
: typeof data.detail === "string"
54+
? data.detail
55+
: "Invalid or expired OTP";
56+
toast.error(errorMsg);
57+
}
58+
} catch (error) {
59+
console.error(error);
60+
toast.error("Network error. Please try again.");
61+
} finally {
62+
setLoading(false);
63+
}
64+
};
65+
66+
return (
67+
<main className="flex flex-col items-center justify-center min-h-screen bg-[#222222] px-4">
68+
<section className="w-full max-w-md text-center">
69+
<h2 className="text-2xl text-white mb-4">Verify Reset Code</h2>
70+
<p className="text-gray-400 mb-6">
71+
Enter the 6-digit code sent to your email.
72+
</p>
73+
74+
<form onSubmit={handleSubmit} className="space-y-4">
75+
<Input
76+
value={otp}
77+
onChange={(e) => setOtp(e.target.value)}
78+
placeholder="Enter OTP"
79+
maxLength={6}
80+
disabled={loading}
81+
className="border text-white h-12 text-center tracking-widest disabled:opacity-50"
82+
/>
83+
<Button
84+
type="submit"
85+
disabled={loading}
86+
className="w-full py-3 h-12 hover:bg-[#FF7A50]/90 text-white rounded-md text-sm leading-none"
87+
style={{ fontFamily: "var(--font-source-serif-pro)" }}
88+
>
89+
{loading ? "Verifying..." : "Verify Code"}
90+
</Button>
91+
</form>
92+
93+
<div className="mt-4 text-sm text-gray-400">
94+
Didn’t get a code?{" "}
95+
<a href="/forgot-password" className="text-[#FF7A50] font-semibold">
96+
Resend
97+
</a>
98+
</div>
99+
</section>
100+
</main>
101+
);
102+
}
103+
104+
export default function VerifyResetOtpPage() {
105+
return (
106+
<Suspense
107+
fallback={<div className="text-white text-center mt-10">Loading...</div>}
108+
>
109+
<VerifyResetOtpContent />
110+
</Suspense>
111+
);
112+
}

src/components/features/forgot-password/forgot-password-form.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { zodResolver } from "@hookform/resolvers/zod";
44
import { useForm } from "react-hook-form";
55
import { toast } from "sonner";
6-
import { z } from "zod";
6+
import { email, z } from "zod";
77

88
import { Button } from "@/components/ui/button";
99
import {
@@ -34,20 +34,19 @@ export const ForgotPasswordForm = () => {
3434
async function onSubmit(data: z.infer<typeof ForgotPasswordFormSchema>) {
3535
setIsLoading(true);
3636
try {
37-
const response = await fetch(
38-
`${process.env.NEXT_PUBLIC_API_URL}/reset-password`,
39-
{
40-
method: "POST",
41-
headers: { "Content-Type": "application/json" },
42-
body: JSON.stringify({ email: data.email }),
43-
},
44-
);
37+
const url = `${process.env.NEXT_PUBLIC_API_URL}/resend_otp?email=${encodeURIComponent(data.email)}`;
38+
const response = await fetch(url, { method: "POST" });
39+
40+
console.log("Endpoint:", url);
41+
console.log("Response:", response);
4542

4643
if (response.ok) {
4744
toast.success("Password reset link sent! Please check your email.");
48-
// Optionally store the email for the next step
49-
//localStorage.setItem("resetEmail", data.email);
50-
router.push("/verify-reset-otp");
45+
localStorage.setItem("resetEmail", data.email);
46+
router.push(
47+
`/verify-reset-otp?email=${encodeURIComponent(data.email)}`,
48+
);
49+
// router.push("/verify-reset-otp");
5150
} else {
5251
const errorData = await response.json();
5352
toast.error(

0 commit comments

Comments
 (0)