Files
got-gaming/components/navigation/Navigation.tsx

384 lines
13 KiB
TypeScript

"use client";
import Link from "next/link";
import { useSession, signOut } from "next-auth/react";
import { useState } from "react";
import { usePathname } from "next/navigation";
import PlayerStats from "@/components/profile/PlayerStats";
import { Button, ThemeToggle } from "@/components/ui";
import ChallengeBadge from "./ChallengeBadge";
import InvitationBadge from "./InvitationBadge";
interface UserData {
username: string;
avatar: string | null;
hp: number;
maxHp: number;
xp: number;
maxXp: number;
level: number;
score: number;
}
interface NavigationProps {
initialUserData?: UserData | null;
initialIsAdmin?: boolean;
initialActiveChallengesCount?: number;
initialPendingInvitationsCount?: number;
}
export default function Navigation({
initialUserData,
initialIsAdmin,
initialActiveChallengesCount = 0,
initialPendingInvitationsCount = 0,
}: NavigationProps) {
const { data: session } = useSession();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const pathname = usePathname();
// Ne pas afficher le profil sur les pages login/register
const isAuthPage = pathname === "/login" || pathname === "/register";
// Utiliser initialUserData pour déterminer l'état de connexion pendant l'hydratation
// Cela évite le clignottement au reload
// Vérifier explicitement que initialUserData n'est pas undefined
const isAuthenticated =
(initialUserData !== undefined && initialUserData !== null) ||
session !== null;
const isAdmin = initialIsAdmin ?? session?.user?.role === "ADMIN";
return (
<nav
className="w-full fixed top-0 left-0 z-50 px-4 sm:px-8 py-3 backdrop-blur-sm border-b"
style={{
backgroundColor:
"color-mix(in srgb, var(--background) 80%, transparent)",
borderColor: "color-mix(in srgb, var(--gray-800) 30%, transparent)",
}}
>
<div className="max-w-7xl mx-auto flex items-center justify-between">
{/* Logo - Left */}
<Link
href="/"
className="flex flex-col hover:opacity-80 transition-opacity"
>
<div
className="text-lg sm:text-xl font-gaming font-bold tracking-tight"
style={{ color: "var(--foreground)" }}
>
GAME.OF.TECH
</div>
<div
className="text-[10px] sm:text-xs font-gaming-subtitle font-semibold flex items-center gap-1 tracking-wide"
style={{ color: "var(--accent-color)" }}
>
<span></span>
<span>Peaksys</span>
<span></span>
</div>
</Link>
{/* Navigation Links - Center (Desktop) */}
<div className="hidden md:flex items-center gap-6">
<Link
href="/"
className="transition text-xs font-normal uppercase tracking-widest"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
HOME
</Link>
<Link
href="/events"
className="transition text-xs font-normal uppercase tracking-widest"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
EVENTS
</Link>
<Link
href="/leaderboard"
className="transition text-xs font-normal uppercase tracking-widest"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
LEADERBOARD
</Link>
{isAuthenticated && (
<>
<InvitationBadge initialCount={initialPendingInvitationsCount} />
<ChallengeBadge initialCount={initialActiveChallengesCount} />
</>
)}
{isAdmin && (
<Link
href="/admin"
className="transition text-xs font-normal uppercase tracking-widest"
style={{ color: "var(--accent-color)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
>
ADMIN
</Link>
)}
</div>
{/* Right Side */}
<div className="flex items-center gap-2 sm:gap-4">
{/* Theme Toggle */}
<div className="hidden md:block">
<ThemeToggle />
</div>
{/* PlayerStats - Hidden on mobile */}
{isAuthenticated && !isAuthPage && (
<div className="hidden lg:block">
<PlayerStats initialUserData={initialUserData} />
</div>
)}
{/* Desktop Auth Buttons */}
<div className="hidden md:flex items-center gap-4">
{isAuthenticated ? (
<Button
onClick={() => signOut()}
variant="ghost"
size="sm"
className="text-xs font-normal"
>
Déconnexion
</Button>
) : (
<>
<Link
href="/login"
className="transition text-xs font-normal uppercase tracking-widest"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
Connexion
</Link>
<Link href="/register">
<Button variant="primary" size="sm" className="text-xs">
Inscription
</Button>
</Link>
</>
)}
</div>
{/* Mobile Menu Button */}
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:hidden transition p-2"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
aria-label="Toggle menu"
>
<svg
className="w-6 h-6"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
{isMenuOpen ? (
<path d="M6 18L18 6M6 6l12 12" />
) : (
<path d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
</div>
{/* Mobile Menu */}
{isMenuOpen && (
<div
className="md:hidden absolute top-full left-0 w-full backdrop-blur-sm border-b"
style={{
backgroundColor:
"color-mix(in srgb, var(--background) 95%, transparent)",
borderColor: "color-mix(in srgb, var(--gray-800) 30%, transparent)",
}}
>
<div className="px-4 py-4 flex flex-col gap-4">
{/* Theme Toggle Mobile */}
<div className="md:hidden">
<ThemeToggle />
</div>
{/* Mobile Navigation Links */}
<div className="flex flex-col gap-3">
<Link
href="/"
onClick={() => setIsMenuOpen(false)}
className="transition text-xs font-normal uppercase tracking-widest py-2"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
HOME
</Link>
<Link
href="/events"
onClick={() => setIsMenuOpen(false)}
className="transition text-xs font-normal uppercase tracking-widest py-2"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
EVENTS
</Link>
<Link
href="/leaderboard"
onClick={() => setIsMenuOpen(false)}
className="transition text-xs font-normal uppercase tracking-widest py-2"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
LEADERBOARD
</Link>
{isAuthenticated && (
<>
<InvitationBadge
initialCount={initialPendingInvitationsCount}
onNavigate={() => setIsMenuOpen(false)}
/>
<ChallengeBadge
initialCount={initialActiveChallengesCount}
onNavigate={() => setIsMenuOpen(false)}
/>
</>
)}
{isAdmin && (
<Link
href="/admin"
onClick={() => setIsMenuOpen(false)}
className="transition text-xs font-normal uppercase tracking-widest py-2"
style={{ color: "var(--accent-color)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
>
ADMIN
</Link>
)}
</div>
{/* Mobile PlayerStats */}
{isAuthenticated && !isAuthPage && (
<div
className="lg:hidden pt-2 border-t"
style={{
borderColor:
"color-mix(in srgb, var(--gray-800) 30%, transparent)",
}}
>
<PlayerStats initialUserData={initialUserData} />
</div>
)}
{/* Mobile Auth Buttons */}
<div
className="flex flex-col gap-3 pt-2 border-t"
style={{
borderColor:
"color-mix(in srgb, var(--gray-800) 30%, transparent)",
}}
>
{isAuthenticated ? (
<Button
onClick={() => {
signOut();
setIsMenuOpen(false);
}}
variant="ghost"
size="sm"
className="text-xs font-normal text-left py-2"
>
Déconnexion
</Button>
) : (
<>
<Link
href="/login"
onClick={() => setIsMenuOpen(false)}
className="transition text-xs font-normal uppercase tracking-widest py-2"
style={{ color: "var(--foreground)" }}
onMouseEnter={(e) =>
(e.currentTarget.style.color = "var(--accent-color)")
}
onMouseLeave={(e) =>
(e.currentTarget.style.color = "var(--foreground)")
}
>
Connexion
</Link>
<Link href="/register" onClick={() => setIsMenuOpen(false)}>
<Button
variant="primary"
size="sm"
className="text-xs w-full text-center"
>
Inscription
</Button>
</Link>
</>
)}
</div>
</div>
</div>
)}
</nav>
);
}