import { useEffect } from "react"; import { Form, Link, useNavigate, useNavigation, useSearchParams } from "react-router"; import { useTranslation } from "react-i18next"; import { FeatherArrowLeft, FeatherMail, FeatherRotateCw, FeatherWand2 } from "@subframe/core"; import { Button } from "~/ui/components/Button"; import { LinkButton } from "~/ui/components/LinkButton"; import { TextInput } from "~/ui/components/TextInput"; import { useRootData } from "~/utils/data/useRootData"; import { AuthShell, AuthStatus, AuthDivider } from "~/components/auth/AuthShell"; import type { LoginActionData } from "~/modules/users/components/LoginForm"; // Login-Screen nach Davids Subframe-Design ("Login"): Logo + Card (Anmelden/Willkommen zurueck) + // E-Mail/Passwort + "Passwort vergessen?" + Anmelden + "oder" + Magic-Link + Footer "Registrieren". // Voll an die bestehende Login-Action verdrahtet (action=login, csrf, redirectTo, Feldfehler, 2FA-Redirect). // Reines ~/ui (TextInput/Button/LinkButton) + AuthShell. Wird vom Login-Route fuer den NICHT-Admin-Pfad // gerendert; der Admin-/SSO-Pfad bleibt in login.tsx unveraendert. export default function LoginScreen({ actionData, redirectTo, }: { actionData: LoginActionData | null | undefined; redirectTo?: string; }) { const { t } = useTranslation(); const { csrf } = useRootData(); const navigation = useNavigation(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const isSubmitting = navigation.state !== "idle"; const mfaVerifyPath = actionData?.mfaVerifyPath ?? "/login-mfa"; const emailError = actionData?.fieldErrors?.email; const passwordError = actionData?.fieldErrors?.password; // D1 — Passwort ok, aber 2FA noetig: Pending-Cookie ist 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")}
); } // D-D0a — Magic-Link ausgegeben -> Davids "Link gesendet"-Screen (AuthStatus). if (actionData?.magicLinkSent) { return ( } tone="positive" title={t("account.login.magicLinkSentTitle")} message={t("account.login.magicLinkSentBody", { email: actionData.magicLinkEmail ?? "" })} hint={t("account.login.magicLinkSentHint")} dataUiId="ui.auth.login.magicLinkSent" >
} disabled={isSubmitting} data-ui-id="ui.auth.login.magicLinkResend"> {t("account.login.magicLinkResend")}
} onClick={() => navigate("/login")} data-ui-id="ui.auth.login.backToLogin"> {t("account.login.backToLogin")}
); } return ( {t("account.login.noAccount")} {t("account.login.register")} } >
{t("account.login.forgot")} {actionData?.error && navigation.state === "idle" ? (

{actionData.error}

) : null}
{/* Magic-Link-Login: submitet die Login-Form (via form="loginForm") mit intent=magicLink -> login-Action gibt den Login-Magic-Link aus -> "Link gesendet"-Screen. */}
); }