diff --git a/app/(main)/(routes)/servers/[serverId]/layout.tsx b/app/(main)/(routes)/servers/[serverId]/layout.tsx
new file mode 100644
index 0000000..584ca09
--- /dev/null
+++ b/app/(main)/(routes)/servers/[serverId]/layout.tsx
@@ -0,0 +1,51 @@
+
+import { redirectToSignIn } from "@clerk/nextjs";
+import { redirect } from "next/navigation";
+
+import { currentProfile } from "@/lib/current-profile";
+import { db } from "@/lib/db";
+
+import { ServerSidebar } from "@/components/server/server-sidebar";
+
+const ServerIdLayout = async ({
+ children,
+ params,
+}: {
+children: React.ReactNode;
+params: { serverId: string};
+}) => {
+ const profile = await currentProfile();
+
+ if (!profile) {
+ return redirectToSignIn();
+ }
+
+ const server = await db.server.findUnique({
+ where: {
+ id: params.serverId,
+ members: {
+ some: {
+ profileId: profile.id,
+ }
+ }
+ },
+ })
+
+ if (!server) {
+ return redirect("/");
+ }
+
+ return (
+
+
+
+
+
+ {children}
+
+
+
+ );
+}
+export default ServerIdLayout;
\ No newline at end of file
diff --git a/components/server/server-header.tsx b/components/server/server-header.tsx
new file mode 100644
index 0000000..c9ff9d7
--- /dev/null
+++ b/components/server/server-header.tsx
@@ -0,0 +1,85 @@
+"use client";
+
+import { ServerWithMembersWithProfiles } from "@/types";
+import { MemberRole } from "@prisma/client";
+import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
+import { ChevronDown, LogOutIcon, Plus, PlusCircle, Settings, Trash, Users } from "lucide-react";
+
+interface ServerHeaderProps {
+ server: ServerWithMembersWithProfiles;
+ role?: MemberRole;
+}
+
+export const SeverHeader = ({server, role}: ServerHeaderProps) => {
+ const isAdmin = role === MemberRole.ADMIN;
+ const isModerator = isAdmin || role === MemberRole.MODERATOR;
+
+ return (
+
+
+
+ {server.name}
+
+
+
+
+ {isModerator && (
+
+ Invite People
+
+
+ )}
+ {isAdmin && (
+
+ Server Settings
+
+
+ )}
+ {isModerator && (
+
+ Manager Members
+
+
+ )}
+ {isModerator && (
+
+ Create Channel
+
+
+ )}
+ {isModerator && (
+
+ )}
+ {isAdmin && (
+
+ Delete Server
+
+
+ )}
+ {!isAdmin && (
+
+ Delete Server
+
+
+ )}
+
+
+ )
+}
\ No newline at end of file
diff --git a/components/server/server-sidebar.tsx b/components/server/server-sidebar.tsx
new file mode 100644
index 0000000..399261d
--- /dev/null
+++ b/components/server/server-sidebar.tsx
@@ -0,0 +1,62 @@
+import { ChannelType } from "@prisma/client";
+import { redirect } from "next/navigation";
+
+import { currentProfile } from "@/lib/current-profile";
+import { db } from "@/lib/db";
+
+import { SeverHeader } from "./server-header";
+
+interface ServerSidebarProps {
+ serverId: string;
+}
+
+export const ServerSidebar = async ({
+ serverId
+}: ServerSidebarProps) => {
+ const profile = await currentProfile();
+
+ if (!profile) {
+ return redirect("/");
+ }
+
+ const server = await db.server.findUnique({
+ where: {
+ id: serverId,
+ },
+ include: {
+ channels: {
+ orderBy: {
+ createdAt: "asc",
+ },
+ },
+ members: {
+ include: {
+ profile: true,
+ },
+ orderBy: {
+ role: "asc",
+ }
+ },
+ }
+ });
+
+ const textChannels = server?.channels.filter((channel) => channel.type === ChannelType.TEXT)
+ const audioChannels = server?.channels.filter((channel) => channel.type === ChannelType.AUDIO)
+ const videoChannels = server?.channels.filter((channel) => channel.type === ChannelType.VIDEO)
+ const members = server?.members.filter((member) => member.profileId !== profile.id)
+
+ if (!server) {
+ return redirect("/");
+ }
+
+ const role = server.members.find((member) => member.profileId === profile.id)?.role;
+
+ return (
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/types.ts b/types.ts
new file mode 100644
index 0000000..ff3ad09
--- /dev/null
+++ b/types.ts
@@ -0,0 +1,5 @@
+import { Server, Member, Profile } from '@prisma/client';
+
+export type ServerWithMembersWithProfiles = Server & {
+ members: (Member & { profile: Profile })[];
+}
\ No newline at end of file