import { useState, useEffect } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import styles from './Reset.module.css'; import { usePasswordReset } from '../hooks/useAuthentication'; import { generateAndStoreCSRFToken } from '../utils/csrfUtils'; import { LanguageSelector } from '../components/UiComponents/LanguageSelector'; import { useLanguage } from '../providers/language/LanguageContext'; function Reset() { const { t } = useLanguage(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { resetPassword, isLoading, error } = usePasswordReset(); const [password, setPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [passwordFocused, setPasswordFocused] = useState(false); const [confirmPasswordFocused, setConfirmPasswordFocused] = useState(false); const [validationError, setValidationError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const [tokenError, setTokenError] = useState(null); // Get token from URL const token = searchParams.get('token'); // Set page title and generate CSRF token useEffect(() => { document.title = "PowerOn AI Platform - Neues Passwort setzen"; generateAndStoreCSRFToken(); // Validate token exists and format if (!token) { setTokenError(t('Ungültiger Reset-Link. Bitte fordern Sie einen neuen Link an.')); } else if (!_isValidUUID(token)) { setTokenError(t('Ungültiger Reset-Link. Bitte fordern Sie einen neuen Link an.')); } }, [token, t]); const _isValidUUID = (str: string): boolean => { const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; return uuidRegex.test(str); }; const validateForm = (): boolean => { if (!password || password.length < 8) { setValidationError(t('Passwort muss mindestens 8 Zeichen lang sein.')); return false; } if (password !== confirmPassword) { setValidationError(t('Die Passwörter stimmen nicht überein.')); return false; } return true; }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setValidationError(null); if (!validateForm()) { return; } if (!token) { setValidationError(t('Token fehlt. Bitte fordern Sie einen neuen Reset-Link an.')); return; } try { await resetPassword(token, password); setSuccessMessage(t('Passwort erfolgreich gesetzt! Sie werden zum Login weitergeleitet…')); // Redirect to login after delay setTimeout(() => { navigate('/login', { state: { passwordReset: true, message: t('Passwort erfolgreich geändert. Bitte melden Sie sich an.') } }); }, 3000); } catch (err: any) { // Error is already set by the hook const errorMessage = err?.response?.data?.detail || err?.message || t('Passwort-Zurücksetzung fehlgeschlagen.'); if (errorMessage.includes('abgelaufen') || errorMessage.includes('expired') || errorMessage.includes('Ungültig') || errorMessage.includes('invalid')) { setValidationError(t('Der Reset-Link ist ungültig oder abgelaufen. Bitte fordern Sie einen neuen Link an.')); } else { setValidationError(errorMessage); } } }; // Show token error if invalid if (tokenError) { return (
PowerOn

{t('Neues Passwort setzen')}

{tokenError}
{t('Oder zurück zum')}
); } return (
PowerOn

{t('Neues Passwort setzen')}

{(validationError || error) && (
{validationError || error}
)} {successMessage && (
{successMessage}
)} {!successMessage && (
{t('Mindestens 8 Zeichen')}
{ setPassword(e.target.value); setValidationError(null); }} onFocus={() => setPasswordFocused(true)} onBlur={() => setPasswordFocused(false)} className={`${styles.input} ${passwordFocused || password ? styles.focused : ''}`} autoComplete="new-password" />
{ setConfirmPassword(e.target.value); setValidationError(null); }} onFocus={() => setConfirmPasswordFocused(true)} onBlur={() => setConfirmPasswordFocused(false)} className={`${styles.input} ${confirmPasswordFocused || confirmPassword ? styles.focused : ''}`} autoComplete="new-password" />
)}
{t('Zurück zum')}
); } export default Reset;