129 lines
4.8 KiB
TypeScript
129 lines
4.8 KiB
TypeScript
import { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
import styles from './PasswordResetRequest.module.css';
|
|
import { usePasswordResetRequest } from '../hooks/useAuthentication';
|
|
import { generateAndStoreCSRFToken } from '../utils/csrfUtils';
|
|
|
|
function PasswordResetRequest() {
|
|
const navigate = useNavigate();
|
|
const { requestReset, isLoading } = usePasswordResetRequest();
|
|
const [username, setUsername] = useState('');
|
|
const [usernameFocused, setUsernameFocused] = useState(false);
|
|
const [validationError, setValidationError] = useState<string | null>(null);
|
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
|
|
|
// Set page title and generate CSRF token
|
|
useEffect(() => {
|
|
document.title = "PowerOn AI Platform - Passwort zurücksetzen";
|
|
generateAndStoreCSRFToken();
|
|
}, []);
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setValidationError(null);
|
|
|
|
if (!username.trim()) {
|
|
setValidationError('Bitte geben Sie Ihren Benutzernamen ein.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await requestReset(username.trim());
|
|
setSuccessMessage('Falls ein Konto mit diesem Benutzernamen existiert, wurde ein Reset-Link an die hinterlegte E-Mail-Adresse gesendet. Bitte prüfen Sie auch Ihren Spam-Ordner.');
|
|
|
|
// Redirect to login after delay
|
|
setTimeout(() => {
|
|
navigate('/login', {
|
|
state: {
|
|
passwordResetRequested: true,
|
|
message: 'Bitte prüfen Sie Ihre E-Mail für den Passwort-Reset-Link.'
|
|
}
|
|
});
|
|
}, 5000);
|
|
} catch (err) {
|
|
// For security, still show success message even on error
|
|
setSuccessMessage('Falls ein Konto mit diesem Benutzernamen existiert, wurde ein Reset-Link an die hinterlegte E-Mail-Adresse gesendet. Bitte prüfen Sie auch Ihren Spam-Ordner.');
|
|
setTimeout(() => {
|
|
navigate('/login');
|
|
}, 5000);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={styles.container}>
|
|
<div className={styles.mainContent}>
|
|
<div className={styles.logo}>
|
|
<div className={styles.logoText}>
|
|
<span className={styles.logoPower}>Power</span>
|
|
<span className={styles.logoOn}>On</span>
|
|
</div>
|
|
</div>
|
|
<div className={styles.loginSection}>
|
|
<div className={styles.loginBox}>
|
|
<h2 className={styles.title}>Passwort zurücksetzen</h2>
|
|
<div className={styles.loginForm}>
|
|
{validationError && (
|
|
<div className={styles.error}>{validationError}</div>
|
|
)}
|
|
|
|
{successMessage && (
|
|
<div className={styles.success}>{successMessage}</div>
|
|
)}
|
|
|
|
{!successMessage && (
|
|
<>
|
|
<div className={styles.floatingLabelInput}>
|
|
<input
|
|
type="text"
|
|
placeholder=" "
|
|
value={username}
|
|
onChange={(e) => {
|
|
setUsername(e.target.value);
|
|
setValidationError(null);
|
|
}}
|
|
onFocus={() => setUsernameFocused(true)}
|
|
onBlur={() => setUsernameFocused(false)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
handleSubmit(e);
|
|
}
|
|
}}
|
|
className={`${styles.input} ${usernameFocused || username ? styles.focused : ''}`}
|
|
/>
|
|
<label className={usernameFocused || username ? styles.focusedLabel : styles.label}>Benutzername</label>
|
|
</div>
|
|
|
|
<div className={styles.infoMessage}>
|
|
<p>Geben Sie Ihren Benutzernamen ein. Falls ein Konto existiert, erhalten Sie einen Link zum Zurücksetzen des Passworts an Ihre hinterlegte E-Mail-Adresse.</p>
|
|
</div>
|
|
|
|
<button
|
|
className={`${styles.button} ${styles.loginButton}`}
|
|
onClick={handleSubmit}
|
|
disabled={isLoading}
|
|
>
|
|
{isLoading ? "Wird gesendet..." : "Reset-Link anfordern"}
|
|
</button>
|
|
</>
|
|
)}
|
|
|
|
<div className={styles.registerLink}>
|
|
<span>Zurück zum</span>
|
|
<button
|
|
className={styles.textButton}
|
|
onClick={() => navigate("/login")}
|
|
>
|
|
Login
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default PasswordResetRequest;
|