frontend_nyla/src/pages/PasswordResetRequest.tsx
2026-04-11 19:44:52 +02:00

134 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';
import { useLanguage } from '../providers/language/LanguageContext';
function PasswordResetRequest() {
const { t } = useLanguage();
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(t('Bitte geben Sie Ihren Benutzernamen ein.'));
return;
}
try {
await requestReset(username.trim());
setSuccessMessage(t('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: t('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(t('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}>
<img
src="/logos/poweron-logo.png"
alt="PowerOn"
className={styles.logoImage}
/>
</div>
<div className={styles.loginSection}>
<div className={styles.loginBox}>
<h2 className={styles.title}>{t('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}>{t('Benutzername')}</label>
</div>
<div className={styles.infoMessage}>
<p>{t('Geben Sie Ihren Benutzernamen ein')}</p>
</div>
<button
className={`${styles.button} ${styles.loginButton}`}
onClick={handleSubmit}
disabled={isLoading}
>
{isLoading ? t('Wird gesendet…') : t('Reset-Link anfordern')}
</button>
</>
)}
<div className={styles.registerLink}>
<span>{t('Zurück zum')}</span>
<button
className={styles.textButton}
onClick={() => navigate("/login")}
>
{t('Login')}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default PasswordResetRequest;