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 ( + + + + + + {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