import React, { useEffect, useRef, useState } from "react"; import { Alert, Box, Button, TextField, Typography } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { api, getApiErrorMessage } from "../api"; import { useToast } from "../toast"; import { useI18n } from "../i18n/I18nProvider"; import AuthPageFrame from "../layout/AuthPageFrame"; export default function ResetPasswordPage() { const { toast } = useToast(); const { t } = useI18n(); const navigate = useNavigate(); const [email, setEmail] = useState(""); const [token, setToken] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [loading, setLoading] = useState(false); const [fieldErrors, setFieldErrors] = useState<{ newPassword?: string; confirmPassword?: string }>({}); const [submitError, setSubmitError] = useState(null); const passwordRef = useRef(null); const confirmPasswordRef = useRef(null); useEffect(() => { const params = new URLSearchParams(window.location.search); setEmail(params.get("email") || ""); setToken(params.get("token") || ""); }, []); const missingResetInfo = !email || !token; return ( { e.preventDefault(); if (missingResetInfo) { toast(t("missingResetLinkInfo"), "error"); return; } const errors: { newPassword?: string; confirmPassword?: string } = {}; if (!newPassword || newPassword.length < 8) errors.newPassword = t("passwordTooShort"); if (confirmPassword !== newPassword) errors.confirmPassword = t("passwordsDoNotMatch"); setFieldErrors(errors); if (Object.keys(errors).length > 0) { (errors.newPassword ? passwordRef : confirmPasswordRef).current?.focus(); return; } setSubmitError(null); setLoading(true); api .post("/auth/reset-password", { email, token, newPassword }) .then(() => { toast(t("passwordResetSuccess"), "success"); navigate("/login", { replace: true }); }) .catch((e2: any) => { setSubmitError(getApiErrorMessage(e2, t("resetFailed"))); }) .finally(() => setLoading(false)); }} sx={{ display: "flex", flexDirection: "column", gap: 1.5 }} > {missingResetInfo ? {t("missingResetLinkInfo")} : null} {submitError ? {submitError} : null} setEmail(e.target.value)} disabled={!missingResetInfo} fullWidth /> { setNewPassword(e.target.value); setFieldErrors((f) => ({ ...f, newPassword: undefined, confirmPassword: undefined })); }} autoComplete="new-password" inputRef={passwordRef} error={Boolean(fieldErrors.newPassword)} helperText={fieldErrors.newPassword || t("passwordTooShort")} fullWidth /> { setConfirmPassword(e.target.value); setFieldErrors((f) => ({ ...f, confirmPassword: undefined })); }} autoComplete="new-password" inputRef={confirmPasswordRef} error={Boolean(fieldErrors.confirmPassword)} helperText={fieldErrors.confirmPassword} fullWidth /> button": { maxWidth: "100%", whiteSpace: "normal", overflowWrap: "anywhere" } }}> {loading ? {t("saving")} : null} ); }