import { Form, Link, useNavigate, useNavigation, useSearchParams } from "react-router"; import { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import LoadingButton from "~/components/ui/buttons/LoadingButton"; import ExclamationTriangleIcon from "~/components/ui/icons/ExclamationTriangleIcon"; import InputText, { RefInputText } from "~/components/ui/input/InputText"; import { useRootData } from "~/utils/data/useRootData"; export type LoginActionData = { error?: string; fieldErrors?: { email: string | undefined; password: string | undefined; }; fields?: { email: string; password: string; }; /** * D1 — gesetzt, wenn das Passwort stimmt, der Nutzer aber 2FA aktiviert hat. Das Session-Cookie * traegt dann nur den Pending-Zustand; der Client wird zur Verify-Route (`mfaVerifyPath`) geleitet. */ requiresMfa?: boolean; mfaVerifyPath?: string; /** D-D0a — Magic-Link-Login: gesetzt, wenn der Anmeldelink ausgegeben wurde (zeigt den "Link gesendet"-Screen). */ magicLinkSent?: boolean; magicLinkEmail?: string; }; export default function LoginForm({ actionData, redirectTo }: { actionData: LoginActionData | null | undefined; redirectTo?: string }) { const { t } = useTranslation(); const { appConfiguration, csrf } = useRootData(); const navigation = useNavigation(); const [searchParams] = useSearchParams(); const emailErrorId = actionData?.fieldErrors?.email ? "email-error" : undefined; const passwordErrorId = actionData?.fieldErrors?.password ? "password-error" : undefined; const navigate = useNavigate(); const mfaVerifyPath = actionData?.mfaVerifyPath ?? "/login-mfa"; const emailInput = useRef(null); useEffect(() => { if (appConfiguration.auth.authMethods.emailPassword.enabled) { setTimeout(() => { emailInput.current?.input.current?.focus(); }, 300); } }, [appConfiguration.auth.authMethods.emailPassword.enabled]); // D1 — Passwort ok, aber 2FA noetig: das Pending-Cookie ist bereits gesetzt, jetzt zur Verify-Route. useEffect(() => { if (actionData?.requiresMfa) { navigate(mfaVerifyPath); } }, [actionData?.requiresMfa, mfaVerifyPath, navigate]); if (actionData?.requiresMfa) { return (

{t("account.loginMfa.redirecting")}

{t("account.loginMfa.continue")}
); } return (

{t("account.login.headline")}

{appConfiguration.subscription.allowSignUpBeforeSubscribe && (

{t("account.login.orRegister")}

)}
{appConfiguration.auth.authMethods.emailPassword.enabled && (
{/* */} {actionData?.fieldErrors?.email ? ( ) : null}
{/* */} {actionData?.fieldErrors?.password ? ( ) : null}
{t("account.login.forgot")} {t("account.login.button")}
{actionData?.error && navigation.state === "idle" ? (
{actionData.error}
) : null}
)}
); }