11'use client' ;
22
33import { useT } from '@gitroom/react/translation/get.transation.service.client' ;
4+ import { FormProvider , SubmitHandler , useForm } from 'react-hook-form' ;
5+ import { useFetch } from '@gitroom/helpers/utils/custom.fetch' ;
6+ import { Button } from '@gitroom/react/form/button' ;
7+ import { Input } from '@gitroom/react/form/input' ;
8+ import { useState , useEffect , useCallback } from 'react' ;
9+ import Link from 'next/link' ;
10+
11+ type ResendInputs = {
12+ email : string ;
13+ } ;
14+
15+ type ResendStatus = 'idle' | 'sent' | 'already_activated' ;
16+
17+ const COOLDOWN_SECONDS = 60 ;
418
519export function Activate ( ) {
620 const t = useT ( ) ;
21+ const fetch = useFetch ( ) ;
22+ const [ loading , setLoading ] = useState ( false ) ;
23+ const [ status , setStatus ] = useState < ResendStatus > ( 'idle' ) ;
24+ const [ cooldown , setCooldown ] = useState ( 0 ) ;
25+ const form = useForm < ResendInputs > ( ) ;
26+
27+ useEffect ( ( ) => {
28+ if ( cooldown <= 0 ) return ;
29+
30+ const timer = setInterval ( ( ) => {
31+ setCooldown ( ( prev ) => prev - 1 ) ;
32+ } , 1000 ) ;
33+
34+ return ( ) => clearInterval ( timer ) ;
35+ } , [ cooldown ] ) ;
36+
37+ const resetToForm = useCallback ( ( ) => {
38+ setStatus ( 'idle' ) ;
39+ setCooldown ( COOLDOWN_SECONDS ) ;
40+ } , [ ] ) ;
41+
42+ const onSubmit : SubmitHandler < ResendInputs > = async ( data ) => {
43+ setLoading ( true ) ;
44+ try {
45+ const response = await fetch ( '/auth/resend-activation' , {
46+ method : 'POST' ,
47+ body : JSON . stringify ( data ) ,
48+ } ) ;
49+ const result = await response . json ( ) ;
50+ if ( result . success ) {
51+ setStatus ( 'sent' ) ;
52+ setCooldown ( COOLDOWN_SECONDS ) ;
53+ } else if ( result . message === 'Account is already activated' ) {
54+ setStatus ( 'already_activated' ) ;
55+ } else {
56+ form . setError ( 'email' , {
57+ message : result . message || t ( 'failed_to_resend' , 'Failed to resend activation email' ) ,
58+ } ) ;
59+ }
60+ } catch ( e ) {
61+ form . setError ( 'email' , {
62+ message : t ( 'error_occurred' , 'An error occurred. Please try again.' ) ,
63+ } ) ;
64+ } finally {
65+ setLoading ( false ) ;
66+ }
67+ } ;
68+
769 return (
8- < div className = "flex flex-col" >
70+ < div className = "flex flex-col flex-1 " >
971 < div >
1072 < h1 className = "text-3xl font-bold text-start mb-4 cursor-pointer" >
1173 { t ( 'activate_your_account' , 'Activate your account' ) }
@@ -19,6 +81,78 @@ export function Activate() {
1981 'Please check your email to activate your account.'
2082 ) }
2183 </ div >
84+
85+ < div className = "mt-8 border-t border-fifth pt-6" >
86+ < h2 className = "text-lg font-semibold mb-4" >
87+ { t ( 'didnt_receive_email' , "Didn't receive the email?" ) }
88+ </ h2 >
89+ { status === 'sent' ? (
90+ < div className = "flex flex-col gap-4" >
91+ < div className = "text-green-400" >
92+ { t (
93+ 'activation_email_sent' ,
94+ 'Activation email has been sent! Please check your inbox.'
95+ ) }
96+ </ div >
97+ { cooldown > 0 ? (
98+ < p className = "text-sm text-textColor" >
99+ { t ( 'resend_available_in' , 'You can resend in' ) } { cooldown } s
100+ </ p >
101+ ) : (
102+ < Button
103+ onClick = { resetToForm }
104+ className = "rounded-[10px] !h-[52px]"
105+ >
106+ { t ( 'send_again' , 'Send Again' ) }
107+ </ Button >
108+ ) }
109+ </ div >
110+ ) : status === 'already_activated' ? (
111+ < div className = "flex flex-col gap-4" >
112+ < div className = "text-green-400" >
113+ { t (
114+ 'account_already_activated' ,
115+ 'Great news! Your account is already activated.'
116+ ) }
117+ </ div >
118+ < Link href = "/auth/login" >
119+ < Button className = "rounded-[10px] !h-[52px] w-full" >
120+ { t ( 'go_to_login' , 'Go to Login' ) }
121+ </ Button >
122+ </ Link >
123+ </ div >
124+ ) : (
125+ < FormProvider { ...form } >
126+ < form onSubmit = { form . handleSubmit ( onSubmit ) } className = "flex flex-col gap-4" >
127+ < Input
128+ label = { t ( 'label_email' , 'Email' ) }
129+ translationKey = "label_email"
130+ { ...form . register ( 'email' , { required : true } ) }
131+ type = "email"
132+ placeholder = { t ( 'email_address' , 'Email Address' ) }
133+ />
134+ < Button
135+ type = "submit"
136+ className = "rounded-[10px] !h-[52px]"
137+ loading = { loading }
138+ disabled = { cooldown > 0 }
139+ >
140+ { cooldown > 0
141+ ? `${ t ( 'resend_available_in' , 'You can resend in' ) } ${ cooldown } s`
142+ : t ( 'resend_activation_email' , 'Resend Activation Email' ) }
143+ </ Button >
144+ </ form >
145+ </ FormProvider >
146+ ) }
147+ { status !== 'already_activated' && (
148+ < p className = "mt-4 text-sm text-textColor" >
149+ { t ( 'already_activated' , 'Already activated?' ) }
150+ < Link href = "/auth/login" className = "underline cursor-pointer" >
151+ { t ( 'sign_in' , 'Sign In' ) }
152+ </ Link >
153+ </ p >
154+ ) }
155+ </ div >
22156 </ div >
23157 ) ;
24158}
0 commit comments