77 lines
2.2 KiB
JavaScript
77 lines
2.2 KiB
JavaScript
import { useEffect, useRef, useState } from 'react'
|
|
import { useNavigate, useSearchParams, Link } from 'react-router-dom'
|
|
import { useAuth } from '../context/AuthContext'
|
|
|
|
// Point d'arrivée après un aller-retour OAuth : le backend nous renvoie ici
|
|
// avec le JWT et le profil encodés dans l'URL.
|
|
export default function AuthCallback() {
|
|
const navigate = useNavigate()
|
|
const [searchParams] = useSearchParams()
|
|
const { login } = useAuth()
|
|
|
|
const errorParam = searchParams.get('error')
|
|
const [error, setError] = useState(errorParam || '')
|
|
|
|
// StrictMode monte deux fois en dev : on ne traite le token qu'une seule fois.
|
|
const handled = useRef(false)
|
|
|
|
useEffect(() => {
|
|
if (handled.current) return
|
|
handled.current = true
|
|
|
|
if (errorParam) return
|
|
|
|
const token = searchParams.get('token')
|
|
const encodedUser = searchParams.get('user')
|
|
|
|
if (!token || !encodedUser) {
|
|
setTimeout(() => {
|
|
setError('Réponse de connexion incomplète.')
|
|
}, 0)
|
|
return
|
|
}
|
|
|
|
try {
|
|
const user = JSON.parse(atob(encodedUser))
|
|
login(user, token)
|
|
|
|
if (user.role === 'ADMIN') {
|
|
navigate('/admin', { replace: true })
|
|
} else if (user.role === 'EMPLOYEE') {
|
|
navigate('/employe', { replace: true })
|
|
} else {
|
|
navigate('/mes-gains', { replace: true })
|
|
}
|
|
} catch {
|
|
setTimeout(() => {
|
|
setError('Réponse de connexion illisible.')
|
|
}, 0)
|
|
}
|
|
}, [searchParams, errorParam, login, navigate])
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="min-h-screen bg-white flex flex-col justify-center items-center px-8 max-w-sm mx-auto text-center">
|
|
<div className="mb-4 px-4 py-3 rounded-lg bg-red-50 border border-red-200 text-red-600 text-sm">
|
|
{error}
|
|
</div>
|
|
|
|
<Link
|
|
to="/connexion"
|
|
className="text-sm text-[#006B6B] font-medium hover:underline"
|
|
>
|
|
Retour à la connexion
|
|
</Link>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white flex flex-col justify-center items-center px-8 max-w-sm mx-auto text-center">
|
|
<p className="text-gray-500 text-sm">
|
|
Connexion en cours…
|
|
</p>
|
|
</div>
|
|
)
|
|
}
|