Skip to content

Commit 75c4bc8

Browse files
Guigui64260claude
andcommitted
fix(auth): le formulaire de connexion reste verrouillé jusqu'à l'ouverture de la page
`loading` retombait dans le `finally`, dès la réponse de `signIn`, avant que `router.push` ait rendu la page cible. Sur une liaison lente, le formulaire restait visible et actif plusieurs secondes après une connexion acceptée ; l'utilisateur re-soumettait. Observé deux fois sur un compte en Nouvelle-Calédonie : deux `login_logs` « ok » à 18 s (26/08) puis 9 s (28/08) d'écart, même appareil. Après succès, le bouton reste désactivé avec le libellé « Connexion réussie, ouverture… » jusqu'à ce que la navigation démonte le composant ; un filet de 20 s rend la main avec un message si la page ne s'ouvre pas. Un refus ou une erreur réseau relâchent le verrou comme avant. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 78a0aac commit 75c4bc8

1 file changed

Lines changed: 27 additions & 5 deletions

File tree

src/components/auth/LoginForm.tsx

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,28 @@ export function LoginForm({ googleEnabled = false }: { googleEnabled?: boolean }
5555
const [resending, setResending] = React.useState(false)
5656
const [resendMessage, setResendMessage] = React.useState<{ ok: boolean; texte: string } | null>(null)
5757
const [loading, setLoading] = React.useState(false)
58+
// Connexion acceptée, page cible en cours d'ouverture. Le formulaire reste
59+
// verrouillé jusqu'à ce que la navigation le démonte : avant, `loading`
60+
// retombait dès la réponse de `signIn`, AVANT le rendu du tableau de bord.
61+
// Sur une liaison lente (compte en Nouvelle-Calédonie, 2026-08-26 et 28), le
62+
// formulaire restait visible et actif plusieurs secondes, et l'utilisatrice
63+
// re-soumettait — deux connexions « ok » à 9 et 18 s d'écart à chaque visite.
64+
const [redirecting, setRedirecting] = React.useState(false)
65+
66+
// Filet : si la page cible ne s'ouvre pas, ne pas laisser un formulaire mort.
67+
React.useEffect(() => {
68+
if (!redirecting) return
69+
const t = setTimeout(() => {
70+
setRedirecting(false)
71+
setLoading(false)
72+
setError("Connexion acceptée, mais la page met du temps à s'ouvrir. Rechargez la page.")
73+
}, 20_000)
74+
return () => clearTimeout(t)
75+
}, [redirecting])
5876

5977
async function handleSubmit(e: React.FormEvent) {
6078
e.preventDefault()
79+
if (loading) return
6180
setError("")
6281
setRefusCode("")
6382
setResendMessage(null)
@@ -76,13 +95,16 @@ export function LoginForm({ googleEnabled = false }: { googleEnabled?: boolean }
7695
const code = result.code ?? ""
7796
setRefusCode(code)
7897
setError(messageRefusConnexion(code))
79-
} else {
80-
router.push(callbackUrl)
81-
router.refresh()
98+
setLoading(false)
99+
return
82100
}
101+
102+
// Succès : `loading` reste vrai, seul le libellé change.
103+
setRedirecting(true)
104+
router.push(callbackUrl)
105+
router.refresh()
83106
} catch {
84107
setError("Une erreur est survenue")
85-
} finally {
86108
setLoading(false)
87109
}
88110
}
@@ -248,7 +270,7 @@ export function LoginForm({ googleEnabled = false }: { googleEnabled?: boolean }
248270
{loading ? (
249271
<>
250272
<Loader2 className="h-4 w-4 animate-spin" />
251-
Connexion...
273+
{redirecting ? "Connexion réussie, ouverture…" : "Connexion..."}
252274
</>
253275
) : (
254276
<>

0 commit comments

Comments
 (0)