ISSUE 4: add recaptcha before submission in sign up form and email validation

This commit is contained in:
Ayobami
2025-07-01 11:00:18 +01:00
parent 05cd9c8318
commit e51d369ba1
+73 -38
View File
@@ -8,6 +8,7 @@ import { useSignUpContext } from "./signUpContext";
import { callCustomAPI, oauthLoginApi } from "@/utils/callCustomAPI";
import { LoadingButton } from "@/components/frontend";
import TLDs from "@/assets/json/email-tlds.json";
import ReCAPTCHA from "react-google-recaptcha";
const SignUpForm = () => {
const navigate = useNavigate();
@@ -15,9 +16,18 @@ const SignUpForm = () => {
const role = signUpData.role;
const schema = yup.object({
email: yup
.string(),
.string()
.required("Email is required")
.email("Invalid email address")
.test("tld-check", "Invalid email TLD", (value) => {
if (!value) return false;
const tld = value.split(".").pop();
return TLDs.includes(tld);
}),
});
const [loading, setLoading] = useState(false);
const [recaptchaValue, setRecaptchaValue] = useState(null);
const [recaptchaError, setRecaptchaError] = useState("");
const {
register,
@@ -32,12 +42,20 @@ const SignUpForm = () => {
});
const onSubmit = async (data) => {
setRecaptchaError("");
if (!recaptchaValue) {
setRecaptchaError("Please complete the recaptcha.");
return;
}
setLoading(true);
try {
const result = await callCustomAPI("email-exist", "post", { email: data.email }, "");
const result = await callCustomAPI(
"email-exist",
"post",
{ email: data.email },
""
);
if (result.error || result.exist) throw new Error("User already exists");
dispatch({ type: "SET_EMAIL", payload: data.email });
navigate("/signup/details" + "?role=" + role);
} catch (err) {
@@ -61,77 +79,87 @@ const SignUpForm = () => {
window.open(result.data, "_self");
};
if (!signUpData.role) return <Navigate to={"/signup/select-role"} />;
return (
<>
<section className="flex w-full flex-col items-center justify-center bg-white md:w-1/2">
<section className='flex w-full flex-col items-center justify-center bg-white md:w-1/2'>
<form
className="flex w-full max-w-md flex-col px-6"
className='flex w-full max-w-md flex-col px-6'
onSubmit={handleSubmit(onSubmit)}
autoComplete="off"
autoComplete='off'
>
<h1 className="mb-8 text-center text-3xl font-semibold md:text-5xl md:font-bold">{role == "host" ? "Become a host" : "Sign up"}</h1>
<h1 className='mb-8 text-center text-3xl font-semibold md:text-5xl md:font-bold'>
{role == "host" ? "Become a host" : "Sign up"}
</h1>
<input
autoComplete="off"
autoComplete='off'
{...register("email")}
type="text"
className="mb-8 resize-none rounded-sm border-2 bg-transparent p-2 px-4 focus:outline-none active:outline-none"
placeholder="Email"
type='text'
className='mb-8 resize-none rounded-sm border-2 bg-transparent p-2 px-4 focus:outline-none active:outline-none'
placeholder='Email'
/>
{Object.entries(errors).length > 0 ? (
<p className="error-vibrate my-3 rounded-md border border-[#C42945] bg-white py-2 px-3 text-center text-sm normal-case text-[#C42945]">{Object.values(errors)[0].message}</p>
<p className='error-vibrate my-3 rounded-md border border-[#C42945] bg-white px-3 py-2 text-center text-sm normal-case text-[#C42945]'>
{Object.values(errors)[0].message}
</p>
) : (
<></>
)}
<div className='mb-4 flex justify-center'>
<ReCAPTCHA
sitekey={import.meta.env.VITE_RECAPTCHA_SITE_KEY}
onChange={(val) => {
setRecaptchaValue(val);
setRecaptchaError("");
}}
/>
</div>
{recaptchaError && (
<p className='mb-2 text-center text-xs italic text-red-500'>
{recaptchaError}
</p>
)}
<LoadingButton
loading={loading}
type="submit"
className={`login-btn-gradient rounded tracking-wide text-white outline-none focus:outline-none ${loading ? "py-1" : "py-2"}`}
type='submit'
className={`login-btn-gradient rounded tracking-wide text-white outline-none focus:outline-none ${
loading ? "py-1" : "py-2"
}`}
disabled={!recaptchaValue}
>
Continue
</LoadingButton>
</form>
<div className="hr my-6 text-center">OR</div>
<div className="oauth flex w-full max-w-md flex-col gap-4 px-6 text-[#344054]">
<div className='hr my-6 text-center'>OR</div>
<div className='oauth flex w-full max-w-md flex-col gap-4 px-6 text-[#344054]'>
<button
onClick={() => handleGoogleLogin()}
className="flex items-center justify-center gap-2 border-2 py-[10px]"
className='flex items-center justify-center gap-2 border-2 py-[10px]'
>
<img
src="/google-icon.png"
className="h-[18px] w-[18px]"
/>
<img src='/google-icon.png' className='h-[18px] w-[18px]' />
<span>Sign Up With Google</span>
</button>
<button
onClick={() => handleFacebookLogin()}
className="flex items-center justify-center gap-2 border-2 py-[10px]"
className='flex items-center justify-center gap-2 border-2 py-[10px]'
>
<img
src="/facebook-icon.png"
className="h-[16px] w-[16px]"
/>
<img src='/facebook-icon.png' className='h-[16px] w-[16px]' />
<span>Sign Up With Facebook</span>
</button>
<button
onClick={() => handleAppleLogin()}
className="flex items-center justify-center gap-2 border-2 py-[10px]"
className='flex items-center justify-center gap-2 border-2 py-[10px]'
>
<img
src="/apple-icon.png"
className="h-[16px] w-[16px]"
/>
<img src='/apple-icon.png' className='h-[16px] w-[16px]' />
<span>Sign Up With Apple</span>
</button>
<div>
<h3 className="text-center text-sm normal-case text-gray-800">
<h3 className='text-center text-sm normal-case text-gray-800'>
Already have an account?{" "}
<Link
to={"/login" + "?role=" + role}
className="my-text-gradient mb-8 self-end text-sm font-semibold"
className='my-text-gradient mb-8 self-end text-sm font-semibold'
>
Log In
</Link>{" "}
@@ -140,8 +168,15 @@ const SignUpForm = () => {
</div>
</section>
<section
style={{ backgroundImage: `url(${role == "host" ? "/jumbotron1.jpg" : "/sign-up-bg.jpg"})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center" }}
className="hidden w-1/2 md:block bg-contain"
style={{
backgroundImage: `url(${
role == "host" ? "/jumbotron1.jpg" : "/sign-up-bg.jpg"
})`,
backgroundSize: "cover",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
}}
className='hidden w-1/2 bg-contain md:block'
></section>
</>
);