1
1
"use client" ;
2
2
import Link from "next/link" ;
3
- import { useState } from "react" ;
3
+ import { useState , useRef } from "react" ;
4
+ import HCaptcha from "@hcaptcha/react-hcaptcha" ;
4
5
import { zodResolver } from "@hookform/resolvers/zod" ;
5
6
import { useForm } from "react-hook-form" ;
6
7
import { signin , signinWithOAuth } from "@/app/(auth)/actions" ;
8
+ import { HCAPTCHA_SITE_KEY_PUBLIC } from "@/utils/constants" ;
7
9
import { Provider } from "@supabase/supabase-js" ;
8
10
import { Button } from "@/components/ui/button" ;
9
11
import { Input } from "@/components/ui/input" ;
@@ -25,6 +27,8 @@ import { useToggle } from "@/hooks/useToggle";
25
27
export default function SignIn ( ) {
26
28
const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
27
29
const [ errorMessage , setErrorMessage ] = useState < string | null > ( null ) ;
30
+ const [ captchaToken , setCaptchaToken ] = useState < string > ( ) ;
31
+ const captcha = useRef < HCaptcha > ( null ) ;
28
32
const searchParams = useSearchParams ( ) ;
29
33
const callbackForDesktopApp = searchParams ?. get ( "callback" ) ?? "" ;
30
34
@@ -42,9 +46,15 @@ export default function SignIn() {
42
46
setErrorMessage ( null ) ;
43
47
44
48
try {
49
+ if ( ! captchaToken ) {
50
+ setErrorMessage ( "Please complete the CAPTCHA" ) ;
51
+ return ;
52
+ }
53
+
45
54
const formData = new FormData ( ) ;
46
55
formData . append ( "email" , data . email ) ;
47
56
formData . append ( "password" , data . password ) ;
57
+ formData . append ( "captchaToken" , captchaToken ) ;
48
58
49
59
const response = await signin ( formData , callbackForDesktopApp ) ;
50
60
if ( response ?. error ) {
@@ -56,6 +66,8 @@ export default function SignIn() {
56
66
setErrorMessage ( "An unexpected error occurred. Please try again." ) ;
57
67
} finally {
58
68
setIsSubmitting ( false ) ;
69
+ captcha . current ?. resetCaptcha ( ) ;
70
+ setCaptchaToken ( undefined ) ;
59
71
}
60
72
} ;
61
73
@@ -193,6 +205,17 @@ export default function SignIn() {
193
205
Forgot Password?
194
206
</ Link >
195
207
</ div >
208
+
209
+ < div className = "flex justify-center" >
210
+ < HCaptcha
211
+ ref = { captcha }
212
+ sitekey = { HCAPTCHA_SITE_KEY_PUBLIC }
213
+ onVerify = { ( token ) => {
214
+ setCaptchaToken ( token ) ;
215
+ } }
216
+ />
217
+ </ div >
218
+
196
219
< Button
197
220
type = "submit"
198
221
size = "lg"
0 commit comments