Rooms made on the website (hosted_room, migration 0005), the REST routes in docs/hosted-rooms.md, and the realtime room.* protocol: joining with the capacity, adult and linked-account rules, seats, numbered messages with forged senders dropped and a rate limit, closing. The Rooms page lists them, with a form to make one and the owner's edit and close. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
0c67232425
commit
2a1fc94df6
18 files changed
+3138
-52
No files matched your search
@@ -0,0 +1,67 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { ActionForm, SubmitButton } from "@/components/forms";
|
||||
import { PageHeader } from "@/components/status";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { FieldGroup } from "@/components/ui/field";
|
||||
import { api, getMe, unwrap } from "@/lib/api";
|
||||
import { closeRoom, saveRoom } from "../../actions";
|
||||
import { RoomFields } from "../../room-fields";
|
||||
|
||||
export const metadata: Metadata = { title: "Edit room" };
|
||||
|
||||
export default async function EditRoom({ params }: { params: Promise<{ n: string }> }) {
|
||||
const { n } = await params;
|
||||
if (!/^[0-9]{1,9}$/.test(n)) notFound();
|
||||
const me = await getMe();
|
||||
if (!me) redirect(`/signin?next=/rooms/${n}/edit`);
|
||||
const [{ rooms }, { links }] = await Promise.all([
|
||||
api["hosted-rooms"].get({ query: { mine: "1" } }).then(unwrap),
|
||||
api.account.get().then(unwrap),
|
||||
]);
|
||||
const room = rooms.find((r) => String(r.n) === n);
|
||||
if (!room) notFound();
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<PageHeader title={`Edit ${room.name}`}>
|
||||
<Link href="/rooms" className="underline-offset-4 hover:underline">
|
||||
Back to rooms
|
||||
</Link>
|
||||
</PageHeader>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardDescription>
|
||||
Owned by {room.ownerName} · {room.occupancy} here now
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ActionForm action={saveRoom} fields={{ n: room.n }}>
|
||||
<FieldGroup>
|
||||
<RoomFields room={room} canAdult={links.some((l) => l.adult)} />
|
||||
<div>
|
||||
<SubmitButton pendingLabel="Saving…">Save</SubmitButton>
|
||||
</div>
|
||||
</FieldGroup>
|
||||
</ActionForm>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Close room</CardTitle>
|
||||
<CardDescription>Everyone in it is sent out. It can't be opened again.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<ActionForm action={closeRoom} fields={{ n: room.n }}>
|
||||
<SubmitButton variant="destructive" pendingLabel="Closing…" confirm={`Close ${room.name}?`}>
|
||||
Close room
|
||||
</SubmitButton>
|
||||
</ActionForm>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user