Final Feature 9c #10

Merged
Lars merged 18 commits from develop into main 2026-03-21 12:41:41 +01:00
2 changed files with 59 additions and 7 deletions
Showing only changes of commit ca9112ebc0 - Show all commits

View File

@ -86,6 +86,18 @@ export function AuthProvider({ children }) {
return data
}
const setAuthFromToken = (token, profile) => {
// Direct token/profile set (for email verification auto-login)
localStorage.setItem(TOKEN_KEY, token)
localStorage.setItem(PROFILE_KEY, profile.id)
setSession({
token,
profile_id: profile.id,
role: profile.role || 'user',
profile
})
}
const logout = async () => {
const token = localStorage.getItem(TOKEN_KEY)
if (token) {
@ -102,7 +114,7 @@ export function AuthProvider({ children }) {
return (
<AuthContext.Provider value={{
session, loading, needsSetup,
login, setup, logout,
login, setup, logout, setAuthFromToken,
isAdmin, canUseAI, canExport,
token: session?.token,
profileId: session?.profile_id,

View File

@ -7,9 +7,9 @@ export default function Verify() {
const [searchParams] = useSearchParams()
const token = searchParams.get('token')
const navigate = useNavigate()
const { login } = useAuth()
const { setAuthFromToken } = useAuth()
const [status, setStatus] = useState('loading') // loading | success | error | expired
const [status, setStatus] = useState('loading') // loading | success | error | expired | already_verified
const [error, setError] = useState(null)
const [email, setEmail] = useState('')
const [resending, setResending] = useState(false)
@ -27,8 +27,8 @@ export default function Verify() {
const result = await api.verifyEmail(token)
// Auto-login with returned token
if (result.token) {
login(result.token, result.profile)
if (result.token && result.profile) {
setAuthFromToken(result.token, result.profile)
setStatus('success')
// Redirect to dashboard after 2 seconds
@ -42,8 +42,14 @@ export default function Verify() {
} catch (err) {
const errorMsg = err.message || 'Verifizierung fehlgeschlagen'
// Check if already verified
if (errorMsg.includes('bereits bestätigt') || errorMsg.includes('already verified')) {
setStatus('already_verified')
// Auto-redirect to login after 3 seconds
setTimeout(() => navigate('/login'), 3000)
}
// Check if token expired
if (errorMsg.includes('abgelaufen') || errorMsg.includes('expired')) {
else if (errorMsg.includes('abgelaufen') || errorMsg.includes('expired')) {
setStatus('expired')
setError(errorMsg)
} else {
@ -54,7 +60,7 @@ export default function Verify() {
}
verify()
}, [token, login, navigate])
}, [token, setAuthFromToken, navigate])
const handleResend = async () => {
if (!email.trim()) {
@ -177,6 +183,40 @@ export default function Verify() {
)
}
if (status === 'already_verified') {
return (
<div style={{
maxWidth:420, margin:'0 auto', padding:'60px 20px',
textAlign:'center'
}}>
<div style={{
background:'var(--accent-light)',
border:'2px solid var(--accent)',
borderRadius:16, padding:'40px 24px', marginBottom:24
}}>
<div style={{fontSize:48, marginBottom:16}}></div>
<h2 style={{marginBottom:12, color:'var(--accent-dark)'}}>
E-Mail bereits bestätigt
</h2>
<p style={{color:'var(--text2)', lineHeight:1.6, marginBottom:24}}>
Deine E-Mail-Adresse wurde bereits verifiziert.
Du kannst dich jetzt anmelden.
</p>
<p style={{fontSize:13, color:'var(--text3)'}}>
Du wirst gleich zum Login weitergeleitet...
</p>
</div>
<button
onClick={() => navigate('/login')}
className="btn btn-primary btn-full"
>
Jetzt anmelden
</button>
</div>
)
}
if (status === 'error') {
return (
<div style={{