127 lines
5.1 KiB
JavaScript
127 lines
5.1 KiB
JavaScript
import { useState } from 'react'
|
|
import { Check, ArrowLeft } from 'lucide-react'
|
|
|
|
export function ForgotPassword({ onBack }) {
|
|
const [email, setEmail] = useState('')
|
|
const [sent, setSent] = useState(false)
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState(null)
|
|
|
|
const handleSubmit = async () => {
|
|
if (!email.trim()) return setError('E-Mail eingeben')
|
|
setLoading(true); setError(null)
|
|
try {
|
|
const r = await fetch('/api/auth/forgot-password', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ email: email.trim() })
|
|
})
|
|
if (!r.ok) throw new Error(await r.text())
|
|
setSent(true)
|
|
} catch(e) {
|
|
setError(e.message)
|
|
} finally { setLoading(false) }
|
|
}
|
|
|
|
if (sent) return (
|
|
<div style={{textAlign:'center',padding:'20px 0'}}>
|
|
<div style={{fontSize:48,marginBottom:12}}>📧</div>
|
|
<div style={{fontSize:16,fontWeight:700,marginBottom:8}}>E-Mail gesendet</div>
|
|
<div style={{fontSize:13,color:'var(--text2)',lineHeight:1.6,marginBottom:20}}>
|
|
Falls ein Konto mit dieser E-Mail existiert, hast du einen Link zum Zurücksetzen erhalten.
|
|
Bitte prüfe auch deinen Spam-Ordner.
|
|
</div>
|
|
<button className="btn btn-secondary btn-full" onClick={onBack}>
|
|
<ArrowLeft size={14}/> Zurück zum Login
|
|
</button>
|
|
</div>
|
|
)
|
|
|
|
return (
|
|
<div>
|
|
<div style={{display:'flex',alignItems:'center',gap:10,marginBottom:20}}>
|
|
<button onClick={onBack}
|
|
style={{background:'none',border:'none',cursor:'pointer',color:'var(--text3)',fontSize:20,padding:4}}>←</button>
|
|
<div>
|
|
<div style={{fontWeight:600,fontSize:16}}>Passwort vergessen</div>
|
|
<div style={{fontSize:12,color:'var(--text3)'}}>Recovery-Link per E-Mail</div>
|
|
</div>
|
|
</div>
|
|
<div style={{fontSize:13,color:'var(--text2)',marginBottom:16,lineHeight:1.6}}>
|
|
Gib deine E-Mail-Adresse ein. Du erhältst einen Link zum Zurücksetzen deines Passworts.
|
|
</div>
|
|
<input type="email" className="form-input" placeholder="deine@email.de"
|
|
value={email} onChange={e=>setEmail(e.target.value)}
|
|
onKeyDown={e=>e.key==='Enter'&&handleSubmit()}
|
|
style={{width:'100%',marginBottom:12,boxSizing:'border-box'}} autoFocus/>
|
|
{error && <div style={{color:'#D85A30',fontSize:12,marginBottom:10}}>{error}</div>}
|
|
<button className="btn btn-primary btn-full" onClick={handleSubmit} disabled={loading}>
|
|
{loading
|
|
? <><div className="spinner" style={{width:14,height:14}}/> Senden…</>
|
|
: <>Recovery-Link senden</>}
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function ResetPassword({ token, onDone }) {
|
|
const [pin, setPin] = useState('')
|
|
const [pin2, setPin2] = useState('')
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState(null)
|
|
const [done, setDone] = useState(false)
|
|
|
|
const handleReset = async () => {
|
|
if (pin.length < 4) return setError('Mind. 4 Zeichen')
|
|
if (pin !== pin2) return setError('Eingaben stimmen nicht überein')
|
|
setLoading(true); setError(null)
|
|
try {
|
|
const r = await fetch('/api/auth/reset-password', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ token, pin })
|
|
})
|
|
if (!r.ok) {
|
|
const err = await r.json()
|
|
throw new Error(err.detail || 'Fehler')
|
|
}
|
|
setDone(true)
|
|
} catch(e) {
|
|
setError(e.message)
|
|
} finally { setLoading(false) }
|
|
}
|
|
|
|
if (done) return (
|
|
<div style={{textAlign:'center',padding:'20px 0'}}>
|
|
<div style={{fontSize:48,marginBottom:12}}>✅</div>
|
|
<div style={{fontSize:16,fontWeight:700,marginBottom:8}}>Passwort geändert</div>
|
|
<div style={{fontSize:13,color:'var(--text2)',marginBottom:20}}>
|
|
Du kannst dich jetzt mit deinem neuen Passwort einloggen.
|
|
</div>
|
|
<button className="btn btn-primary btn-full" onClick={onDone}>
|
|
Zum Login
|
|
</button>
|
|
</div>
|
|
)
|
|
|
|
return (
|
|
<div>
|
|
<div style={{fontSize:16,fontWeight:700,marginBottom:6}}>Neues Passwort setzen</div>
|
|
<div style={{fontSize:13,color:'var(--text2)',marginBottom:16}}>
|
|
Wähle ein neues Passwort oder eine neue PIN (mind. 4 Zeichen).
|
|
</div>
|
|
<input type="password" className="form-input" placeholder="Neues Passwort"
|
|
value={pin} onChange={e=>setPin(e.target.value)}
|
|
style={{width:'100%',marginBottom:10,boxSizing:'border-box'}} autoFocus/>
|
|
<input type="password" className="form-input" placeholder="Wiederholen"
|
|
value={pin2} onChange={e=>setPin2(e.target.value)}
|
|
onKeyDown={e=>e.key==='Enter'&&handleReset()}
|
|
style={{width:'100%',marginBottom:12,boxSizing:'border-box'}}/>
|
|
{error && <div style={{color:'#D85A30',fontSize:12,marginBottom:10}}>{error}</div>}
|
|
<button className="btn btn-primary btn-full" onClick={handleReset} disabled={loading}>
|
|
{loading ? <><div className="spinner" style={{width:14,height:14}}/> Speichern…</> : 'Passwort setzen'}
|
|
</button>
|
|
</div>
|
|
)
|
|
}
|