Skip to content

Commit bdf392c

Browse files
Merge pull request #53 from kumaradarsh2/feature/resend-otp-button
2 parents c8bea9c + 9854372 commit bdf392c

File tree

2 files changed

+67
-41
lines changed

2 files changed

+67
-41
lines changed
Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
"use client";
22

3+
import { AxiosError } from "axios";
34
import { useState, useEffect } from "react";
5+
import { toast } from "sonner";
6+
import { Loader2 } from "lucide-react";
47

58
import { Button } from "@/components/ui/button";
6-
9+
import { axiosInstance } from "@/lib/axios";
710
import { cn } from "@/lib/utils";
811

9-
export const ResendOTPButton = () => {
12+
// Define the props the component will accept
13+
interface ResendOTPButtonProps {
14+
email: string;
15+
}
16+
17+
export const ResendOTPButton = ({ email }: ResendOTPButtonProps) => {
1018
const [timer, setTimer] = useState(30);
11-
const [isDisabled, setIsDisabled] = useState(true);
19+
const [isCoolingDown, setIsCoolingDown] = useState(true);
20+
const [isLoading, setIsLoading] = useState(false);
1221

22+
// This useEffect handles the countdown timer
1323
useEffect(() => {
1424
let interval: NodeJS.Timeout;
1525

16-
if (isDisabled) {
26+
if (isCoolingDown) {
1727
interval = setInterval(() => {
1828
setTimer((prev) => {
1929
if (prev <= 1) {
2030
clearInterval(interval);
21-
setIsDisabled(false);
31+
setIsCoolingDown(false);
2232
return 0;
2333
}
2434
return prev - 1;
@@ -27,21 +37,52 @@ export const ResendOTPButton = () => {
2737
}
2838

2939
return () => clearInterval(interval);
30-
}, [isDisabled]);
40+
}, [isCoolingDown]);
41+
42+
// This is the new function to handle the API call
43+
const handleResend = async () => {
44+
setIsLoading(true);
45+
try {
46+
// Make the POST request to the backend
47+
await axiosInstance.post("/resend_otp", { email });
48+
49+
// On success, show a notification and restart the timer
50+
toast.success("A new OTP has been sent to your email.");
51+
setTimer(30);
52+
setIsCoolingDown(true);
53+
} catch (error) {
54+
// On failure, show an error notification
55+
let errorMessage = "Failed to resend OTP. Please try again.";
3156

32-
const handleResend = () => {
33-
setTimer(30);
34-
setIsDisabled(true);
57+
// Check if the error is an Axios error
58+
if (error instanceof AxiosError && error.response?.data?.message) {
59+
errorMessage = error.response.data.message;
60+
}
61+
62+
toast.error(errorMessage);
63+
} finally {
64+
setIsLoading(false);
65+
}
3566
};
3667

68+
const isDisabled = isCoolingDown || isLoading;
69+
3770
return (
3871
<Button
3972
variant="link"
4073
onClick={handleResend}
4174
disabled={isDisabled}
42-
className={cn(isDisabled ? "cursor-not-allowed" : "cursor-pointer")}
75+
className={cn(
76+
"p-0 h-auto font-normal", // Styling to make it look like a simple link
77+
isDisabled ? "cursor-not-allowed" : "cursor-pointer",
78+
)}
4379
>
44-
{isDisabled ? `Resend in ${timer}s` : "Resend OTP"}
80+
{isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
81+
{isLoading
82+
? "Sending..."
83+
: isCoolingDown
84+
? `Resend OTP in ${timer}s`
85+
: "Resend OTP"}
4586
</Button>
4687
);
4788
};

src/components/features/signup/verify-account-form.tsx

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
InputOTPGroup,
2323
InputOTPSlot,
2424
} from "@/components/ui/input-otp";
25+
import { ResendOTPButton } from "./resend-otp-button"; // Import the button
2526

2627
import { REGEXP_ONLY_DIGITS } from "input-otp";
2728

@@ -62,35 +63,15 @@ export const VerifyAccountForm = () => {
6263
},
6364
});
6465

65-
async function onSubmit(data: z.infer<typeof VerifyAccountFormSchema>) {
66-
try {
67-
setIsOtpIncorrect(false);
68-
69-
const response = await fetch(
70-
"https://naija-nutri-hub.azurewebsites.net/verify",
71-
{
72-
method: "POST",
73-
headers: { "Content-Type": "application/json" },
74-
body: JSON.stringify({
75-
email: email,
76-
otp: data.code,
77-
}),
78-
},
79-
);
80-
81-
const result = await response.json();
82-
83-
if (response.ok) {
84-
toast.success("Account verified successfully!");
85-
router.push("/login");
86-
} else {
87-
console.error(result);
88-
setIsOtpIncorrect(true);
89-
toast.error(result.message || "Invalid or expired OTP.");
90-
}
91-
} catch (error) {
92-
console.error("Verification error:", error);
93-
toast.error("Something went wrong. Please try again.");
66+
function onSubmit(data: z.infer<typeof VerifyAccountFormSchema>) {
67+
// This part should also be replaced with a real API call in a future task
68+
const CORRECT_OTP = "123456";
69+
70+
if (data.code !== CORRECT_OTP) {
71+
setIsOtpIncorrect(true);
72+
// This resets the form after an incorrect attempt
73+
form.reset({ code: "" });
74+
return;
9475
}
9576
}
9677

@@ -170,7 +151,11 @@ export const VerifyAccountForm = () => {
170151
<p>Security code doesn&apos;t match</p>
171152
</div>
172153
) : (
173-
<p className="text-sm">Resend code by Email</p>
154+
// Replaced the static text with the ResendOTPButton component
155+
<div className="text-sm text-muted-foreground flex items-center justify-center gap-1">
156+
<span>Didn&apos;t receive code?</span>
157+
<ResendOTPButton email={email} />
158+
</div>
174159
)}
175160

176161
<Button type="submit" className="w-full h-11 text-base">

0 commit comments

Comments
 (0)