Files
void-sentinel/web/components/ServerSwitcher.tsx

90 lines
4.3 KiB
TypeScript

"use client";
import React, { useState, useRef, useEffect } from "react";
import Link from "next/link";
import { ChevronDown, Check } from "lucide-react";
import { Guild } from "@/lib/discord";
interface ServerSwitcherProps {
currentGuild: Guild;
guilds: Guild[];
}
export default function ServerSwitcher({ currentGuild, guilds }: ServerSwitcherProps) {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
return (
<div className="relative" ref={dropdownRef}>
<button
onClick={() => setIsOpen(!isOpen)}
className="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-white/5 transition-colors border border-transparent hover:border-white/10 group"
>
{currentGuild.icon ? (
<img
src={`https://cdn.discordapp.com/icons/${currentGuild.id}/${currentGuild.icon}.png`}
alt={currentGuild.name}
className="w-10 h-10 rounded-full bg-gray-800"
/>
) : (
<div className="w-10 h-10 rounded-full bg-gray-700 flex items-center justify-center text-sm font-semibold text-gray-300">
{currentGuild.name.substring(0, 2)}
</div>
)}
<div className="text-left hidden md:block">
<div className="font-semibold text-white flex items-center gap-2">
{currentGuild.name}
<ChevronDown className={`w-4 h-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`} />
</div>
</div>
</button>
{isOpen && (
<div className="absolute top-full left-0 mt-2 w-72 max-h-96 overflow-y-auto no-scrollbar bg-[#1e1e24] border border-white/10 rounded-xl shadow-2xl z-50 animate-in fade-in slide-in-from-top-2">
<div className="p-2 sticky top-0 bg-[#1e1e24] border-b border-white/5">
<p className="text-xs font-semibold text-gray-400 uppercase px-2 py-1">Switch Server</p>
</div>
<div className="p-2 space-y-1">
{guilds.map((guild) => (
<Link
key={guild.id}
href={`/dashboard/${guild.id}`}
onClick={() => setIsOpen(false)}
className={`flex items-center gap-3 w-full p-2 rounded-lg hover:bg-white/5 transition-all ${guild.id === currentGuild.id ? "bg-blue-500/10" : ""}`}
>
{guild.icon ? (
<img
src={`https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png`}
alt={guild.name}
className="w-8 h-8 rounded-full"
/>
) : (
<div className="w-8 h-8 rounded-full bg-gray-700 flex items-center justify-center text-xs font-bold text-gray-400">
{guild.name.substring(0, 2)}
</div>
)}
<span className={`flex-1 truncate ${guild.id === currentGuild.id ? "text-blue-300 font-medium" : "text-gray-300"}`}>
{guild.name}
</span>
{guild.id === currentGuild.id && (
<Check className="w-4 h-4 text-blue-400" />
)}
</Link>
))}
</div>
</div>
)}
</div>
);
}