import { useState } from "react"; import { Form, useLocation, useNavigate, useNavigation } from "react-router"; import { useTranslation } from "react-i18next"; import { FeatherAlertTriangle, FeatherCheck } from "@subframe/core"; import { useRootData } from "~/utils/data/useRootData"; import { AuthShell, AuthStatus } from "~/components/auth/AuthShell"; import { Button } from "~/ui/components/Button"; import { LinkButton } from "~/ui/components/LinkButton"; import { Progress } from "~/ui/components/Progress"; import { TextInput } from "~/ui/components/TextInput"; // Reset-Password-Screen nach Davids Subframe-Design ("Reset Password" + States): Logo + Card // (Neues Passwort + Staerke-Progress + Bestaetigung + "Passwort speichern"). Token kommt aus der URL (t), // E-Mail aus dem Loader (e) -> beide als hidden Inputs. action validiert (mismatch/weak/token). // success -> Davids "Reset Password _ Success"; fehlende/ungueltige Link-Daten -> "Reset Link _ Invalid". function passwordStrength(pw: string): number { if (!pw) return 0; const checks = [pw.length >= 8, /[A-Z]/.test(pw), /[a-z]/.test(pw), /\d/.test(pw), /[^A-Za-z0-9]/.test(pw)]; return Math.round((checks.filter(Boolean).length / checks.length) * 100); } export default function ResetPasswordScreen({ data, actionData, }: { data: { email: string }; actionData: { success?: string; error?: string; fields?: { verifyToken?: string; email?: string } } | null | undefined; }) { const { t } = useTranslation(); const { csrf } = useRootData(); const navigation = useNavigation(); const navigate = useNavigate(); const location = useLocation(); const isSubmitting = navigation.state !== "idle"; const verifyToken = actionData?.fields?.verifyToken || new URLSearchParams(location.search).get("t") || ""; const [password, setPassword] = useState(""); const strength = passwordStrength(password); const strengthLabel = strength < 40 ? t("account.newPassword.strengthWeak") : strength < 80 ? t("account.newPassword.strengthMedium") : t("account.newPassword.strengthStrong"); if (actionData?.success) { return ( } tone="positive" title={t("account.newPassword.successTitle")} message={t("account.newPassword.successBody")} dataUiId="ui.auth.reset.success" > navigate("/login")} data-ui-id="ui.auth.reset.successBackToLogin"> {t("account.forgot.backToLogin")} ); } // Kein/ungueltiger Link (keine E-Mail im e-Param) -> Davids "Reset Link _ Invalid". if (!data.email) { return ( } tone="negative" title={t("account.newPassword.invalidTitle")} message={t("account.newPassword.invalidBody")} dataUiId="ui.auth.reset.invalid" > navigate("/forgot-password")} data-ui-id="ui.auth.reset.requestNew"> {t("account.newPassword.requestNew")} navigate("/login")} data-ui-id="ui.auth.reset.invalidBackToLogin"> {t("account.forgot.backToLogin")} ); } return ( setPassword(event.target.value)} disabled={isSubmitting} data-ui-id="ui.auth.reset.password" /> = 80 ? "success" : undefined} /> {t("account.register.passwordStrength")}: {strengthLabel} {t("account.register.passwordHint")} {t("account.newPassword.button")} {actionData?.error && navigation.state === "idle" ? ( {actionData.error} ) : null} navigate("/login")} data-ui-id="ui.auth.reset.backToLogin"> {t("account.forgot.backToLogin")} ); }
{actionData.error}