11"use client" ;
22
3+ import { AxiosError } from "axios" ;
34import { useState , useEffect } from "react" ;
5+ import { toast } from "sonner" ;
6+ import { Loader2 } from "lucide-react" ;
47
58import { Button } from "@/components/ui/button" ;
6-
9+ import { axiosInstance } from "@/lib/axios" ;
710import { 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} ;
0 commit comments