refactor: make Header a server component to avoid auth flash on load
Some checks failed
Deploy with Docker Compose / deploy (push) Has been cancelled

Move session check from client-side useSession() to server-side auth(),
so the authenticated state is known at initial render. Extract interactive
parts (ThemeToggle, UserMenu, WorkshopsDropdown, NavLinks) into small
client components.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 11:14:27 +01:00
parent a10205994c
commit 9298eef0cb
7 changed files with 223 additions and 170 deletions

View File

@@ -0,0 +1,74 @@
'use client';
import Link from 'next/link';
import { signOut } from 'next-auth/react';
import { useState, useRef } from 'react';
import { Avatar } from '@/components/ui';
import { useClickOutside } from '@/hooks/useClickOutside';
interface UserMenuProps {
userName: string | null | undefined;
userEmail: string;
}
export function UserMenu({ userName, userEmail }: UserMenuProps) {
const [menuOpen, setMenuOpen] = useState(false);
const userMenuRef = useRef<HTMLDivElement>(null);
useClickOutside(userMenuRef, () => setMenuOpen(false), menuOpen);
return (
<div ref={userMenuRef} className="relative">
<button
onClick={() => setMenuOpen(!menuOpen)}
className="flex h-9 items-center gap-2 rounded-lg border border-border bg-card pl-1.5 pr-3 transition-colors hover:bg-card-hover"
>
<Avatar email={userEmail} name={userName} size={24} />
<span className="text-sm font-medium text-foreground">
{userName || userEmail.split('@')[0]}
</span>
<svg
className={`h-4 w-4 text-muted transition-transform ${menuOpen ? 'rotate-180' : ''}`}
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
{menuOpen && (
<div className="absolute right-0 z-20 mt-2 w-48 rounded-lg border border-border bg-card py-1 shadow-lg">
<div className="border-b border-border px-4 py-2">
<p className="text-xs text-muted">Connecté en tant que</p>
<p className="truncate text-sm font-medium text-foreground">{userEmail}</p>
</div>
<Link
href="/profile"
onClick={() => setMenuOpen(false)}
className="block w-full px-4 py-2 text-left text-sm text-foreground hover:bg-card-hover"
>
👤 Mon Profil
</Link>
<Link
href="/users"
onClick={() => setMenuOpen(false)}
className="block w-full px-4 py-2 text-left text-sm text-foreground hover:bg-card-hover"
>
👥 Utilisateurs
</Link>
<button
onClick={() => signOut({ callbackUrl: '/' })}
className="w-full px-4 py-2 text-left text-sm text-destructive hover:bg-card-hover"
>
Se déconnecter
</button>
</div>
)}
</div>
);
}