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'; function Reset() { 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('Ungültiger Reset-Link. Bitte fordern Sie einen neuen Link an.'); } else if (!_isValidUUID(token)) { setTokenError('Ungültiger Reset-Link. Bitte fordern Sie einen neuen Link an.'); } }, [token]); 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('Passwort muss mindestens 8 Zeichen lang sein.'); return false; } if (password !== confirmPassword) { setValidationError('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('Token fehlt. Bitte fordern Sie einen neuen Reset-Link an.'); return; } try { await resetPassword(token, password); setSuccessMessage('Passwort erfolgreich gesetzt! Sie werden zum Login weitergeleitet...'); // Redirect to login after delay setTimeout(() => { navigate('/login', { state: { passwordReset: true, message: '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 || 'Passwort-Zurücksetzung fehlgeschlagen.'; if (errorMessage.includes('abgelaufen') || errorMessage.includes('expired') || errorMessage.includes('Ungültig') || errorMessage.includes('invalid')) { setValidationError('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

Neues Passwort setzen

{tokenError}
oder zurück zum
); } return (
PowerOn

Neues Passwort setzen

{(validationError || error) && (
{validationError || error}
)} {successMessage && (
{successMessage}
)} {!successMessage && (
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" />
)}
Zurück zum
); } export default Reset;