Skip to content
This repository was archived by the owner on May 30, 2023. It is now read-only.

Commit 1b53a53

Browse files
author
Lộc Phạm
authored
Merge pull request #254 from daita-technologies/feat/invisible-captcha
feat: integrate invisible captcha
2 parents 1d9d31e + 703036b commit 1b53a53

4 files changed

Lines changed: 67 additions & 12 deletions

File tree

src/components/ReCaptchaInput/index.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
import { useEffect } from "react";
12
import { Controller } from "react-hook-form";
23
import { Box, FormHelperText } from "@mui/material";
34
import ReCAPTCHA from "react-google-recaptcha";
45
import { RECAPTCHA_SITE_KEY } from "constants/defaultValues";
56
import { ReCaptchaInputProps } from "./type";
6-
import { useEffect } from "react";
7+
8+
const REQUIRE_RECAPTCHA_ERROR_MESSAGE = "You need to verify the captcha.";
79

810
const ReCaptchaInput = function ({
911
recaptchaRef,
@@ -14,15 +16,16 @@ const ReCaptchaInput = function ({
1416
register("captcha", {
1517
required: {
1618
value: true,
17-
message: "You need to verify the captcha.",
19+
message: REQUIRE_RECAPTCHA_ERROR_MESSAGE,
1820
},
1921
});
2022
}, []);
23+
2124
return (
2225
<Controller
2326
control={control}
2427
name="captcha"
25-
render={({ field, fieldState: { error } }) => (
28+
render={({ fieldState: { error } }) => (
2629
<Box
2730
display="flex"
2831
flexDirection="column"
@@ -33,10 +36,12 @@ const ReCaptchaInput = function ({
3336
<ReCAPTCHA
3437
ref={recaptchaRef}
3538
sitekey={RECAPTCHA_SITE_KEY}
36-
onChange={(token: any) => field.onChange(token)}
39+
size="invisible"
3740
/>
38-
39-
{error && <FormHelperText error>{error.message}</FormHelperText>}
41+
{/* NOTE: We use invisible recaptcha is auto generate when submitted, therefore no need show required message */}
42+
{error && error.message !== REQUIRE_RECAPTCHA_ERROR_MESSAGE && (
43+
<FormHelperText error>{error.message}</FormHelperText>
44+
)}
4045
</Box>
4146
)}
4247
/>

src/routes/ForgotPasswordPage/index.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { MyButton, ReCaptchaInput } from "components";
1919
import { ChangeEvent, useEffect, useRef, useState } from "react";
2020
import ReCAPTCHA from "react-google-recaptcha";
2121
import { Helmet } from "react-helmet";
22-
import { SubmitHandler, useForm } from "react-hook-form";
22+
import { SubmitErrorHandler, SubmitHandler, useForm } from "react-hook-form";
2323
import { useDispatch, useSelector } from "react-redux";
2424
import { useHistory } from "react-router-dom";
2525
import { RootState } from "reduxes";
@@ -60,6 +60,7 @@ const ForgotPasswordPage = function () {
6060
handleSubmit,
6161
formState: { errors },
6262
setValue,
63+
getValues,
6364
trigger,
6465
} = useForm<ForgotPasswordRequestFields>({ mode: "onChange" });
6566
const recaptchaRef = useRef<ReCAPTCHA>(null);
@@ -88,6 +89,22 @@ const ForgotPasswordPage = function () {
8889
}
8990
};
9091

92+
const generateReCatpchaToken = async () => {
93+
if (recaptchaRef && recaptchaRef.current) {
94+
const token = await recaptchaRef.current.executeAsync();
95+
setValue("captcha", token || "");
96+
onSubmit(getValues());
97+
}
98+
};
99+
100+
const onInvalidSubmit: SubmitErrorHandler<ForgotPasswordRequestFields> = (
101+
error
102+
) => {
103+
if (error.captcha && error.captcha.type === "required") {
104+
generateReCatpchaToken();
105+
}
106+
};
107+
91108
const password = useRef({});
92109
password.current = watch("password", "");
93110

@@ -170,7 +187,7 @@ const ForgotPasswordPage = function () {
170187
sent to your email to verify.
171188
</Typography>
172189
<Box sx={{ mt: 3, py: 0, px: "14px" }}>
173-
<form onSubmit={handleSubmit(onSubmit)}>
190+
<form onSubmit={handleSubmit(onSubmit, onInvalidSubmit)}>
174191
<TextField
175192
variant="outlined"
176193
required

src/routes/LoginPage/LoginForm.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
} from "constants/defaultValues";
2626
import { useEffect, useRef, useState } from "react";
2727
import ReCAPTCHA from "react-google-recaptcha";
28-
import { SubmitHandler, useForm } from "react-hook-form";
28+
import { SubmitErrorHandler, SubmitHandler, useForm } from "react-hook-form";
2929
import { useDispatch, useSelector } from "react-redux";
3030
import { useHistory, useLocation } from "react-router-dom";
3131
import { RootState } from "reduxes";
@@ -68,10 +68,25 @@ const LoginForm = function () {
6868
const isLoginAccountVerified = useSelector(
6969
(state: RootState) => state.authReducer.isLoginAccountVerified
7070
);
71+
7172
const onSubmit: SubmitHandler<LoginFormFields> = (data) => {
7273
dispatch(loginAction(data));
7374
};
7475

76+
const generateReCatpchaToken = async () => {
77+
if (recaptchaRef && recaptchaRef.current) {
78+
const token = await recaptchaRef.current.executeAsync();
79+
setValue("captcha", token || "");
80+
onSubmit(getValues());
81+
}
82+
};
83+
84+
const onInvalidSubmit: SubmitErrorHandler<LoginFormFields> = (error) => {
85+
if (error.captcha && error.captcha.type === "required") {
86+
generateReCatpchaToken();
87+
}
88+
};
89+
7590
const handleClickShowPassword = () => {
7691
setIsShowPassword(!isShowPassword);
7792
};
@@ -152,7 +167,7 @@ const LoginForm = function () {
152167
👋 Sign In
153168
</Typography>
154169
<Box mt={3}>
155-
<form onSubmit={handleSubmit(onSubmit)}>
170+
<form onSubmit={handleSubmit(onSubmit, onInvalidSubmit)}>
156171
<TextField
157172
variant="outlined"
158173
required

src/routes/RegisterPage/UserInfoForm.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
import moment from "moment";
2424
import { ChangeEvent, useEffect, useRef, useState } from "react";
2525
import ReCAPTCHA from "react-google-recaptcha";
26-
import { SubmitHandler, useForm } from "react-hook-form";
26+
import { SubmitErrorHandler, SubmitHandler, useForm } from "react-hook-form";
2727
import { useDispatch, useSelector } from "react-redux";
2828
import { RootState } from "reduxes";
2929
import { registerAction } from "reduxes/auth/actions";
@@ -81,6 +81,7 @@ const UserInfoForm = function ({
8181
register,
8282
control,
8383
setValue,
84+
getValues,
8485
watch,
8586
handleSubmit,
8687
trigger,
@@ -121,6 +122,20 @@ const UserInfoForm = function ({
121122
}
122123
};
123124

125+
const generateReCatpchaToken = async () => {
126+
if (recaptchaRef && recaptchaRef.current) {
127+
const token = await recaptchaRef.current.executeAsync();
128+
setValue("captcha", token || "");
129+
onSubmit(getValues());
130+
}
131+
};
132+
133+
const onInvalidSubmit: SubmitErrorHandler<RegisterFormFields> = (error) => {
134+
if (error.captcha && error.captcha.type === "required") {
135+
generateReCatpchaToken();
136+
}
137+
};
138+
124139
const [isShowPassword, setIsShowPassword] = useState(false);
125140

126141
const handleClickShowPassword = () => {
@@ -158,7 +173,10 @@ const UserInfoForm = function ({
158173

159174
return (
160175
<Box>
161-
<form onSubmit={handleSubmit(onSubmit)} autoComplete={autoCompleteString}>
176+
<form
177+
onSubmit={handleSubmit(onSubmit, onInvalidSubmit)}
178+
autoComplete={autoCompleteString}
179+
>
162180
<TextField
163181
variant="outlined"
164182
required

0 commit comments

Comments
 (0)