Die sechs noch offenen Typen haben kein fremdes Ziel, auf das man weiterleiten koennte — sie brauchen eine Seite. Dafuer bekommt der Typ-Vertrag `hasLandingPage`: /r/[slug] schickt solche Codes auf /s/[slug], statt `redirectTarget` zu befragen. Die oeffentlichen Seiten duerfen die Navigation der Anwendung nicht zeigen — wer einen Code scannt, hat mit „Verwaltung" nichts zu tun. Deshalb liegt das App-Chrome jetzt in der Routengruppe (app); das Wurzel-Layout traegt nur noch html und body. Die URLs aendern sich dadurch nicht.
40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
|
|
import { DomainAdmin } from "@/components/domain-admin";
|
|
import { Icon } from "@/components/icons";
|
|
import { requirePagePermission } from "@/lib/auth/guard";
|
|
import { baseUrlHostname } from "@/lib/domains";
|
|
|
|
export const metadata: Metadata = { title: "Domains" };
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export default async function DomainsPage() {
|
|
await requirePagePermission("instance:manage");
|
|
|
|
return (
|
|
<div className="mx-auto max-w-3xl px-4 py-8 sm:px-6 sm:py-10">
|
|
<Link
|
|
href="/verwaltung"
|
|
className="mb-5 inline-flex items-center gap-1.5 rounded-lg text-sm font-medium text-slate-600 transition-colors hover:text-slate-900"
|
|
>
|
|
<Icon name="arrowLeft" className="size-4" />
|
|
Verwaltung
|
|
</Link>
|
|
|
|
<div className="mb-7">
|
|
<h1 className="text-2xl font-bold tracking-tight text-slate-900 sm:text-3xl">
|
|
Domains
|
|
</h1>
|
|
<p className="mt-2 text-slate-600">
|
|
Unter welchen Adressen Kurz-URLs ausgeliefert werden. Eine Domain
|
|
kann mehreren Gruppen dienen; der Slug eines Codes ist je Domain
|
|
eindeutig.
|
|
</p>
|
|
</div>
|
|
|
|
<DomainAdmin baseUrlHostname={baseUrlHostname()} />
|
|
</div>
|
|
);
|
|
}
|