ldc-ker-chant/resources/ts/front/Components/cookie/recaptcha/RecaptchaForm.tsx
2026-07-10 11:32:24 +02:00

124 lines
3.6 KiB
TypeScript

import { usePage } from "@inertiajs/react";
import { InfoIcon } from "lucide-react";
import type React from "react";
import { type SubmitEvent } from "react";
import { Button } from "@/components/ui/button";
import { cnServices } from "@/front/Components/cookie/constants";
import InputError from "@/front/Components/cookie/InputError";
import { useRecaptcha } from "@/front/Components/cookie/recaptcha/RecaptchaProvider";
import { type CookieEnv } from "@/front/types/cookie";
import useCookieNotice from "@/hooks/use-cookie-notice";
import useTrans from "@/hooks/use-translations";
import { cn } from "@/lib/utils";
interface CustomData {
"g-recaptcha-response"?: string;
}
interface BannerClassName {
classNames?: {
wrapperClassName?: string;
btnClassName?: string;
};
}
interface Props<TFormData> {
onSubmit: (e: SubmitEvent<HTMLFormElement>) => void;
data: TFormData & CustomData;
children: React.ReactNode;
footer?: React.ReactNode;
banner?: BannerClassName;
classNames?: {
wrapperClassName?: string;
formClassName?: string;
};
}
function RecaptchaNotice({ banner }: { banner?: BannerClassName }) {
const { enabled } = useRecaptcha();
const title = useTrans("cookie-notice.custom.recaptcha.title");
const warning = useTrans("cookie-notice.custom.recaptcha.warning");
const label = useTrans("cookie-notice.custom.recaptcha.accept");
const { accept } = useCookieNotice(cnServices.RECAPTCHA);
if (enabled) return null;
return (
<div
data-cookie-name="recaptcha"
className={cn(
"cn-cookie-activate flex flex-col rounded-lg border border-destructive/50 bg-card text-card-foreground shadow-sm gap-4 mb-4 p-6",
banner?.classNames?.wrapperClassName,
)}
>
<p className="text-2xl font-semibold leading-none tracking-tight flex flex-row w-full items-start">
<InfoIcon className="mr-1" />
{title}
</p>
<div className="flex flex-row justify-between items-center">
<small className="text-success fw-normal fs-5">{warning}</small>
<Button
className={cn(banner?.classNames?.btnClassName)}
id="recaptcha-accept"
type="button"
onClick={accept}
>
{label}
</Button>
</div>
</div>
);
}
export default function RecaptchaForm<TFormData>({
onSubmit,
classNames,
banner,
data,
children,
footer,
}: Props<TFormData>) {
const { getToken, formRef, enabled } = useRecaptcha();
const { errors } = usePage().props;
const { recaptchaKey, recaptchaBypassKey } = usePage().props
.cookieEnv as CookieEnv;
const { mode } = usePage().props.appEnv as AppEnv;
const isTestingEnv = mode === "testing";
const formIsEnabled = isTestingEnv || enabled;
const handleSubmit = (e: SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
if (!formIsEnabled) return;
const token = getToken();
// eslint-disable-next-line react-hooks/immutability
data["g-recaptcha-response"] = isTestingEnv ? recaptchaBypassKey : token;
onSubmit(e);
};
return (
<div className={cn(classNames?.wrapperClassName)}>
<RecaptchaNotice banner={banner} />
<form
className={cn(classNames?.formClassName)}
ref={formRef}
onSubmit={handleSubmit}
data-recaptcha-key={recaptchaKey}
{...(!formIsEnabled ? { inert: true } : {})}
>
{children}
{formIsEnabled && (
<>
<InputError message={errors["g-recaptcha-response"]} />
<div className="r_captcha flex justify-center mt-8" />
</>
)}
{footer}
</form>
</div>
);
}