Files
void-sentinel/web/app/dashboard/[guildId]/layout.tsx

118 lines
5.1 KiB
TypeScript

import { auth } from "@/auth";
import { redirect, notFound } from "next/navigation";
import { getUserGuilds } from "@/lib/discord";
import ServerSwitcher from "@/components/ServerSwitcher";
import DashboardSidebar from "@/components/DashboardSidebar";
import UserProfile from "@/components/UserProfile";
export default async function DashboardLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ guildId: string }>;
}) {
const session = await auth();
const { guildId } = await params;
if (!session?.accessToken) {
redirect("/");
}
const guilds = await getUserGuilds(session.accessToken as string);
const currentGuild = guilds.find((g) => g.id === guildId);
if (!currentGuild) {
notFound();
}
// If bot is not in guild, show the invite page
if (!currentGuild.botInGuild) {
return (
<div className="min-h-screen bg-black/50 relative flex flex-col">
{/* Header */}
<header className="fixed top-0 left-0 right-0 p-2 sm:p-4 flex justify-between items-start z-50 pointer-events-none">
<div className="pointer-events-auto">
<ServerSwitcher currentGuild={currentGuild} guilds={guilds} />
</div>
<UserProfile user={session.user} />
</header>
{/* Bot Not In Guild Content */}
<div className="container mx-auto px-4 py-24 sm:py-32 flex flex-col items-center justify-center flex-1 text-center">
{currentGuild.icon ? (
<img
src={`https://cdn.discordapp.com/icons/${currentGuild.id}/${currentGuild.icon}.png`}
alt={currentGuild.name}
className="w-24 h-24 sm:w-32 sm:h-32 rounded-full mx-auto shadow-[0_0_30px_rgba(59,130,246,0.5)]"
/>
) : (
<div className="w-24 h-24 sm:w-32 sm:h-32 rounded-full mx-auto bg-gray-800 flex items-center justify-center text-3xl sm:text-4xl font-bold text-gray-400 shadow-[0_0_30px_rgba(59,130,246,0.2)]">
{currentGuild.name.substring(0, 2)}
</div>
)}
<div className="space-y-2 mt-6">
<h1 className="text-3xl sm:text-5xl font-bold text-white tracking-tight">{currentGuild.name}</h1>
<p className="text-blue-300/80 text-sm sm:text-base">
Void Sentinel is not in this server
</p>
</div>
<div className="mt-6 sm:mt-8">
<div className="mt-6 sm:mt-8">
{currentGuild.isBetaServer ? (
<a
href={`https://discord.com/oauth2/authorize?client_id=${process.env.AUTH_DISCORD_ID}&permissions=8&scope=bot&guild_id=${currentGuild.id}&disable_guild_select=true`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 px-6 sm:px-8 py-2.5 sm:py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-full font-bold text-base sm:text-lg transition-all hover:scale-105 shadow-[0_0_20px_rgba(37,99,235,0.5)] hover:shadow-[0_0_40px_rgba(37,99,235,0.6)]"
>
Add to Server
</a>
) : (
<button
disabled
className="inline-flex items-center gap-2 px-6 sm:px-8 py-2.5 sm:py-3 bg-white/5 text-gray-400 rounded-full font-bold text-base sm:text-lg cursor-not-allowed border border-white/10"
>
Request Access
</button>
)}
</div>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-black/50 relative flex flex-col">
{/* Header */}
<header className="fixed top-0 left-0 right-0 p-2 sm:p-4 flex justify-between items-start z-50 pointer-events-none">
<div className="pointer-events-auto">
<ServerSwitcher currentGuild={currentGuild} guilds={guilds} />
</div>
<UserProfile user={session.user} />
</header>
{/* Dashboard Content with Sidebar */}
<div className="flex flex-1 pt-16 sm:pt-20 h-screen overflow-hidden">
<DashboardSidebar guildId={guildId} />
{/* Main Area */}
<div className="flex-1 overflow-y-auto bg-transparent p-4 sm:p-6 lg:p-8 lg:ml-64">
<div className="max-w-5xl mx-auto">
{children}
</div>
</div>
</div>
</div>
);
}