ldc-ovoteam/resources/ts/front/Components/Base/RecaptchaForm.tsx
Jérémy Munsch cd2d8ed397
refactor(i18n): replace GetTranslation with trans function
- Updated translation utility to improve consistency and reduce redundancy.
- Removed deprecated useTrans hook and related code.
- Introduced a new Zustand store for managing translations and locale settings.
- Cleaned up unused hooks and files related to localization.
2026-10-19 17:43:33 +02:00

120 lines
3.3 KiB
TypeScript

/** REACT / INERTIA */
import { usePage } from "@inertiajs/react";
import React, { SubmitEventHandler } from "react";
/** LUCIDE */
import { InfoIcon } from "lucide-react";
/** SHADCN */
import { Button } from "@/components/ui/button";
/** BASE */
import InputError from "$/base/InputError";
import { useRecaptcha } from "@/front/providers/RecaptchaProvider";
import trans from "@/hooks/use-translations";
import { cn } from "@/lib/utils";
interface CustomData {
"g-recaptcha-response"?: string;
}
type BannerClassName = {
classNames?: {
wrapperClassName?: string;
btnClassName?: string;
};
};
type Props<TFormData> = {
/* eslint-disable no-unused-vars, @typescript-eslint/no-unused-vars */
onSubmit: SubmitEventHandler<HTMLFormElement>;
data: TFormData & CustomData;
children: React.ReactNode;
footer?: React.ReactNode;
banner?: BannerClassName;
classNames?: {
wrapperClassName?: string;
formClassName?: string;
};
};
function RecaptchaNotice({ banner }: Readonly<{ banner?: BannerClassName }>) {
const { enabled } = useRecaptcha();
const title = trans("cookie-notice.custom.recaptcha.title");
const warning = trans("cookie-notice.custom.recaptcha.warning");
const label = trans("cookie-notice.custom.recaptcha.accept");
const handleAccept = () => {
// @ts-expect-error External library
window.WebCookieNotice?.acceptCookie("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={handleAccept}
>
{label}
</Button>
</div>
</div>
);
}
export default function RecaptchaForm<TFormData>({
onSubmit,
classNames,
banner,
data,
children,
footer,
}: Readonly<Props<TFormData>>) {
const { getToken, formRef, enabled } = useRecaptcha();
const { errors } = usePage().props;
const { recaptchaKey } = usePage().props.cookieEnv as CookieEnv;
const handleSubmit: SubmitEventHandler<HTMLFormElement> = (e) => {
e.preventDefault();
if (!enabled) return;
const token = getToken();
// eslint-disable-next-line no-param-reassign
data["g-recaptcha-response"] = 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 ?? undefined}
inert={!enabled}
>
{children}
{enabled && (
<>
<InputError message={errors["g-recaptcha-response"]} />
<div className="r_captcha flex justify-center mt-8" />
</>
)}
{footer}
</form>
</div>
);
}