Replace demo pages with live app data
This commit is contained in:
@@ -1,28 +1,116 @@
|
||||
import { AppShell } from "@/components/app-shell";
|
||||
import { RoomConsole } from "@/components/room-console";
|
||||
import { StatusBadge } from "@/components/status-badge";
|
||||
import { canEnterRoom } from "@/lib/access";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { requireCurrentUser, userIsAdmin } from "@/lib/session";
|
||||
import { requireInitialSetup } from "@/lib/setup";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default async function RoomPage({ params }: { params: Promise<{ slug: string }> }) {
|
||||
await requireInitialSetup();
|
||||
const user = await requireCurrentUser();
|
||||
const isAdmin = userIsAdmin(user);
|
||||
const { slug } = await params;
|
||||
const roomSlug = decodeURIComponent(slug);
|
||||
const room = await prisma.room.findUnique({
|
||||
where: { slug: roomSlug },
|
||||
include: {
|
||||
owner: true,
|
||||
members: { include: { user: true } },
|
||||
mediaSources: { include: { submitter: true }, orderBy: { createdAt: "desc" }, take: 20 }
|
||||
}
|
||||
});
|
||||
|
||||
if (!room) {
|
||||
redirect("/dashboard");
|
||||
}
|
||||
|
||||
const isOwner = room.ownerId === user.id;
|
||||
const explicitMember = room.members.some((member) => member.userId === user.id);
|
||||
const isFriend = room.ownerId
|
||||
? Boolean(
|
||||
await prisma.friendship.findFirst({
|
||||
where: {
|
||||
status: "ACCEPTED",
|
||||
OR: [
|
||||
{ requesterId: user.id, receiverId: room.ownerId },
|
||||
{ requesterId: room.ownerId, receiverId: user.id }
|
||||
]
|
||||
},
|
||||
select: { id: true }
|
||||
})
|
||||
)
|
||||
: false;
|
||||
|
||||
if (
|
||||
!canEnterRoom({
|
||||
visibility: room.visibility,
|
||||
isOwner,
|
||||
isAdmin,
|
||||
isFriend,
|
||||
explicitMember,
|
||||
hasRoomRole: explicitMember
|
||||
})
|
||||
) {
|
||||
redirect("/dashboard");
|
||||
}
|
||||
|
||||
const personalRoom = await prisma.room.findFirst({ where: { ownerId: user.id }, select: { slug: true } });
|
||||
|
||||
return (
|
||||
<AppShell active="Rooms" isAdmin={userIsAdmin(user)}>
|
||||
<AppShell
|
||||
active="Rooms"
|
||||
isAdmin={isAdmin}
|
||||
roomHref={personalRoom ? `/rooms/${encodeURIComponent(personalRoom.slug)}` : "/dashboard"}
|
||||
userName={user.displayName || user.username}
|
||||
>
|
||||
<header className="topbar">
|
||||
<div className="title-block">
|
||||
<h1>{roomSlug}</h1>
|
||||
<p>Stable room address with shared playback for authorized users.</p>
|
||||
<h1>{room.name}</h1>
|
||||
<p>{room.owner ? `Owned by ${room.owner.displayName || room.owner.username}` : "Shared watch room"}</p>
|
||||
</div>
|
||||
<div className="status-row">
|
||||
<StatusBadge tone="good">Online</StatusBadge>
|
||||
<StatusBadge>All participants may control</StatusBadge>
|
||||
<StatusBadge>{room.visibility}</StatusBadge>
|
||||
</div>
|
||||
</header>
|
||||
<RoomConsole roomSlug={roomSlug} />
|
||||
<RoomConsole
|
||||
roomId={room.id}
|
||||
roomSlug={room.slug}
|
||||
currentUser={user.displayName || user.username}
|
||||
queue={room.mediaSources.map((item) => ({
|
||||
id: item.id,
|
||||
title: item.title || item.originalUrl,
|
||||
provider: item.provider,
|
||||
originalUrl: item.originalUrl,
|
||||
playbackUrl: item.playbackUrl,
|
||||
by: item.submitter?.displayName || item.submitter?.username || "Unknown",
|
||||
createdAt: formatDate(item.createdAt)
|
||||
}))}
|
||||
participants={[
|
||||
...(room.owner
|
||||
? [
|
||||
{
|
||||
id: room.owner.id,
|
||||
name: room.owner.displayName || room.owner.username,
|
||||
role: "Owner",
|
||||
status: room.owner.id === user.id ? "Online" : "Available"
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...room.members.map((member) => ({
|
||||
id: member.userId,
|
||||
name: member.user.displayName || member.user.username,
|
||||
role: member.canManage ? "Manager" : "Member",
|
||||
status: member.userId === user.id ? "Online" : "Allowed"
|
||||
}))
|
||||
]}
|
||||
/>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
|
||||
function formatDate(date: Date) {
|
||||
return new Intl.DateTimeFormat("en", { month: "short", day: "numeric" }).format(date);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user