Files
Novodraft/ax3Client/src/Components/Account/PasswordReset.js
2026-05-23 17:08:47 -04:00

217 lines
6.9 KiB
JavaScript

import React, { useState, useEffect } from "react";
import {
checkActionCode,
confirmPasswordReset,
getAuth,
sendPasswordResetEmail,
} from "firebase/auth";
import Button from "../../pageElements/Button";
import { useSearchParams } from "react-router-dom";
const PasswordResetPage = () => {
const auth = getAuth();
const [isBusy, setIsBusy] = useState(false);
const [isCodeValid, setIsCodeValid] = useState(null);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [done, setDone] = useState(false);
const [notice, setNotice] = useState("");
const [searchParams] = useSearchParams();
const mode = searchParams.get("mode");
const oobCode = searchParams.get("oobCode");
useEffect(() => {
async function handleCheckCode() {
if (!oobCode) {
setIsCodeValid(false);
return;
}
try {
await checkActionCode(auth, oobCode);
setIsCodeValid(true);
} catch (error) {
setIsCodeValid(false);
}
}
handleCheckCode();
}, [auth, oobCode]);
const handleResetPassword = async (e) => {
e.preventDefault();
if (isBusy) {
return;
}
setIsBusy(true);
setNotice("");
try {
await sendPasswordResetEmail(auth, email);
setDone(true);
} catch (error) {
if (error.code === "auth/invalid-email") {
setNotice("Invalid email.");
} else {
setNotice(`Error occured (${error.code}).`);
}
} finally {
setIsBusy(false);
}
};
const handleConfirmPasswordReset = async (e) => {
e.preventDefault();
if (isBusy) {
return;
}
if (password !== confirmPassword) {
setNotice("Passwords do not match");
return;
}
setIsBusy(true);
try {
await confirmPasswordReset(auth, oobCode, password);
setDone(true);
} catch (error) {
if (error.code === "auth/weak-password") {
setNotice("Weak password.");
} else {
setNotice(`Error occured (${error.code}).`);
}
} finally {
setIsBusy(false);
}
};
const resetMode = mode === "resetPassword" ? "resetPassword" : "enterEmail";
return (
<div className="password-reset-container">
<div className="password-reset-form-wrapper">
<div className="password-reset-form">
{resetMode === "enterEmail" ? (
<>
<div className="password-reset-header">
<h2 className="password-reset-header-text">
Enter Account Email
</h2>
</div>
{!done ? (
<form>
<div className="form-floating">
<input
type="email"
className="form-control"
id="emailInput"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
disabled={isBusy}
></input>
<label htmlFor="emailInput" className="form-label">
Email
</label>
</div>
<div className="alert-box">
{"" !== notice && (
<div className="password-reset-alert" role="alert">
{notice}
</div>
)}
</div>
<div className="password-reset-button-wrapper">
<Button
className="primary-button"
onClick={(e) => handleResetPassword(e)}
labelText="Submit"
disabled={isBusy}
/>
</div>
</form>
) : null}
{done && (
<div className="success-container">
<p className="reset-sent-text">
A password reset link was sent.
</p>
</div>
)}
</>
) : null}
{resetMode === "resetPassword" ? (
<>
<div className="password-reset-header">
<h2 className="password-reset-header-text">
Enter New Password
</h2>
</div>
{!done && isCodeValid !== null && isCodeValid ? (
<form>
<div className="form-floating mb-3">
<input
type="password"
className="form-control"
id="passwordInput"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
disabled={isBusy}
></input>
<label htmlFor="emailInput" className="form-label">
Enter new password
</label>
</div>
<div className="form-floating">
<input
type="password"
className="form-control"
id="confirmPasswordInput"
placeholder="Confirm Password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
disabled={isBusy}
></input>
<label
htmlFor="confirmPasswordInput"
className="form-label"
>
Confirm password
</label>
</div>
<div className="alert-box">
{"" !== notice && (
<div className="password-reset-alert" role="alert">
{notice}
</div>
)}
</div>
<div className="password-reset-button-wrapper">
<Button
className="primary-button"
onClick={(e) => handleConfirmPasswordReset(e)}
labelText="Submit"
disabled={isBusy}
/>
</div>
</form>
) : null}
{!done && isCodeValid !== null && !isCodeValid && (
<div className="success-container">
<p className="reset-sent-text">
Bad or already used password reset code.
</p>
</div>
)}
{done && (
<div className="success-container">
<p className="reset-sent-text">Password changed.</p>
</div>
)}
</>
) : null}
</div>
</div>
</div>
);
};
export default PasswordResetPage;