waveform/app/(app)/layout.tsx
Chneemann 3a119c5891
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 1m4s
refactor(members): introduce UserProvider to eliminate prop drilling for member profile popovers
2026-09-10 10:20:41 +02:00

87 lines
2.7 KiB
TypeScript

/**
* @file app/(app)/layout.tsx
* @description Main application layout component that handles authentication, parallel data fetching for servers and conversations, and global sidebar state.
*/
import { auth } from "@/auth";
import { db } from "@/db";
import { users, conversations } from "@/db/schema";
import { eq, or } from "drizzle-orm";
import { getUserServers } from "@/lib/services/server.service";
import { AppSidebar } from "@/components/layout/AppSidebar";
import { MemberSidebar } from "@/components/layout/MemberSidebar";
import { ServerProvider } from "@/lib/context/ServerContext";
import { redirect } from "next/navigation";
import { getUserFriendships } from "@/lib/services/friends.service";
import { UserProvider } from "@/lib/context/UserContext";
/** Renders the primary application layout with authentication checks, database fetching, and sidebar structure. */
export default async function AppLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await auth();
const currentUserId = session?.user?.id;
// Single Auth Guard
if (!currentUserId) {
redirect("/login");
}
// Parallel Loading: User Details, Servers & DM-Conversations
const [[currentUser], userServers, userConversations] = await Promise.all([
db.select().from(users).where(eq(users.id, currentUserId)).limit(1),
getUserServers(currentUserId),
db.query.conversations.findMany({
where: or(
eq(conversations.userOneId, currentUserId),
eq(conversations.userTwoId, currentUserId),
),
with: {
userOne: true,
userTwo: true,
},
}),
]);
if (!currentUser) {
redirect("/login");
}
// Transform conversations to isolate the respective conversation partner
const formattedConversations = userConversations.map((c) => {
const partner = c.userOne.id === currentUserId ? c.userTwo : c.userOne;
return {
id: c.id,
partner: {
id: partner.id,
username: partner.username,
color: partner.color,
status: partner.status,
},
};
});
// Loading Friendships data
const [friendships] = await Promise.all([
getUserFriendships(session.user.id),
]);
return (
<UserProvider currentUser={currentUser} friendships={friendships}>
<ServerProvider>
<div className="flex h-screen w-full overflow-hidden bg-background text-foreground">
<AppSidebar
servers={userServers}
conversations={formattedConversations}
user={currentUser}
/>
<div className="flex-1 flex min-w-0">{children}</div>
<MemberSidebar />
</div>
</ServerProvider>
</UserProvider>
);
}