fix: login redirect with Suspense boundary + read redirect query param

- Wrap useSearchParams() in Suspense boundary (Next.js requirement)
- Read ?redirect= query param for post-login redirect to /admin
- Auto-detect admin users and redirect to /admin
- Fallback to /dashboard for regular users

https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
This commit is contained in:
Claude
2026-02-10 17:03:51 +00:00
parent 9ae7dd2d2d
commit 7be84681f0

View File

@@ -1,14 +1,16 @@
"use client"; "use client";
import { useState } from "react"; import { Suspense, useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import { createClient } from "@/lib/supabase/client"; import { createClient } from "@/lib/supabase/client";
import Button from "@/components/ui/Button"; import Button from "@/components/ui/Button";
import Input from "@/components/ui/Input"; import Input from "@/components/ui/Input";
export default function LoginPage() { function LoginForm() {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams();
const redirectTo = searchParams.get("redirect");
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -35,19 +37,32 @@ export default function LoginPage() {
return; return;
} }
// Vérifier si l'utilisateur est admin pour la redirection // Si un redirect est spécifié dans l'URL, l'utiliser directement
if (redirectTo) {
router.push(redirectTo);
router.refresh();
return;
}
// Sinon, vérifier si l'utilisateur est admin
if (authData.user) { if (authData.user) {
try {
const { data: profile } = await supabase const { data: profile } = await supabase
.from("profiles") .from("profiles")
.select("is_admin") .select("is_admin, subscription_status")
.eq("id", authData.user.id) .eq("id", authData.user.id)
.single(); .single();
if (profile && (profile as { is_admin?: boolean }).is_admin) { const p = profile as { is_admin?: boolean; subscription_status?: string } | null;
if (p?.is_admin) {
router.push("/admin"); router.push("/admin");
router.refresh(); router.refresh();
return; return;
} }
} catch {
// RLS peut bloquer, on continue vers dashboard
}
} }
router.push("/dashboard"); router.push("/dashboard");
@@ -60,27 +75,6 @@ export default function LoginPage() {
}; };
return ( return (
<main className="min-h-screen flex items-center justify-center px-4">
<div className="w-full max-w-md">
{/* Logo */}
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center gap-2 mb-6">
<div className="w-10 h-10 gradient-bg rounded-xl flex items-center justify-center">
<span className="text-white font-bold">H</span>
</div>
<span className="text-2xl font-bold text-white">
Hook<span className="gradient-text">Lab</span>
</span>
</Link>
<h1 className="text-2xl font-bold text-white mb-2">
Content de te revoir
</h1>
<p className="text-white/60 text-sm">
Connecte-toi pour accéder à tes formations.
</p>
</div>
{/* Form */}
<div className="bg-dark-light border border-dark-border rounded-[20px] p-6 md:p-8"> <div className="bg-dark-light border border-dark-border rounded-[20px] p-6 md:p-8">
<form onSubmit={handleLogin} className="space-y-5"> <form onSubmit={handleLogin} className="space-y-5">
<Input <Input
@@ -125,6 +119,38 @@ export default function LoginPage() {
</p> </p>
</div> </div>
</div> </div>
);
}
export default function LoginPage() {
return (
<main className="min-h-screen flex items-center justify-center px-4">
<div className="w-full max-w-md">
{/* Logo */}
<div className="text-center mb-8">
<Link href="/" className="inline-flex items-center gap-2 mb-6">
<div className="w-10 h-10 gradient-bg rounded-xl flex items-center justify-center">
<span className="text-white font-bold">H</span>
</div>
<span className="text-2xl font-bold text-white">
Hook<span className="gradient-text">Lab</span>
</span>
</Link>
<h1 className="text-2xl font-bold text-white mb-2">
Content de te revoir
</h1>
<p className="text-white/60 text-sm">
Connecte-toi pour accéder à tes formations.
</p>
</div>
<Suspense fallback={
<div className="bg-dark-light border border-dark-border rounded-[20px] p-6 md:p-8 flex items-center justify-center py-12">
<div className="animate-spin w-6 h-6 border-2 border-primary border-t-transparent rounded-full" />
</div>
}>
<LoginForm />
</Suspense>
</div> </div>
</main> </main>
); );