added frontend + securing beta server invites
This commit is contained in:
89
web/components/ServerSwitcher.tsx
Normal file
89
web/components/ServerSwitcher.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
"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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user