yiekheng 7697ea5fcb feat(web): PageShell narrow variant for dense single-column tabs
Adds a 'narrow' prop that wraps the body in 'max-w-2xl mx-auto'
while keeping the header chrome at the standard 5xl. Settings is
the first consumer — its rows are dense text and look adrift at
full width. The header still aligns with the other tabs so the
title position stays consistent.

Covered by 2 SSR tests (narrow path adds the inner wrapper, default
path doesn't).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 15:23:06 +08:00

66 lines
2.2 KiB
TypeScript

import { getSeededOperator } from "@/lib/operator";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { ThemeToggle } from "@/components/theme-toggle";
import { NotificationsToggle } from "@/components/notifications-toggle";
import { PageShell } from "@/components/page-shell";
export default async function SettingsPage() {
const op = await getSeededOperator();
return (
<PageShell title="Settings" narrow>
<Card>
<CardHeader>
<CardTitle>Operator</CardTitle>
</CardHeader>
<CardContent className="space-y-3 text-sm">
<Row label="Display name" value={op.displayName} />
<Separator />
<Row label="Operator ID" value={String(op.telegramUserId)} mono />
<Separator />
<Row label="Default timezone" value={op.defaultTimezone} mono />
<Separator />
<Row label="Role" value={op.role} mono />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Notifications</CardTitle>
<CardDescription>
Browser notifications when a reminder fires successfully or a
test message is sent. Uses the in-tab Notification API works
while the app is open. Background push is on the roadmap.
</CardDescription>
</CardHeader>
<CardContent>
<NotificationsToggle />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Appearance</CardTitle>
</CardHeader>
<CardContent className="flex items-center justify-between">
<div className="text-sm text-muted-foreground">Theme</div>
<ThemeToggle />
</CardContent>
</Card>
<p className="text-center text-xs text-muted-foreground">
cm WhatsApp Bot · self-hosted
</p>
</PageShell>
);
}
function Row({ label, value, mono }: { label: string; value: string; mono?: boolean }) {
return (
<div className="flex items-center justify-between gap-3">
<dt className="text-muted-foreground">{label}</dt>
<dd className={mono ? "font-mono text-xs" : ""}>{value}</dd>
</div>
);
}