import { getPublicHeaderBannerConfig, isAdminSelfRegistrationEnabled, setAdminSelfRegistrationEnabled, setPublicHeaderBannerConfig, } from "@cms/db" import { Button } from "@cms/ui/button" import { revalidatePath } from "next/cache" import Link from "next/link" import { redirect } from "next/navigation" import { AdminShell } from "@/components/admin-shell" import { translateMessage } from "@/i18n/messages" import { getAdminMessages, resolveAdminLocale } from "@/i18n/server" import { requirePermissionForRoute } from "@/lib/route-guards" type SearchParamsInput = Promise> function toSingleValue(input: string | string[] | undefined): string | null { if (Array.isArray(input)) { return input[0] ?? null } return input ?? null } async function requireSettingsPermission() { await requirePermissionForRoute({ nextPath: "/settings", permission: "users:manage_roles", scope: "global", }) } async function getSettingsTranslator() { const locale = await resolveAdminLocale() const messages = await getAdminMessages(locale) return (key: string, fallback: string) => translateMessage(messages, key, fallback) } async function updateRegistrationPolicyAction(formData: FormData) { "use server" await requireSettingsPermission() const t = await getSettingsTranslator() const enabled = formData.get("enabled") === "on" try { await setAdminSelfRegistrationEnabled(enabled) } catch (error) { const errorMessage = error instanceof Error ? error.message : "" const normalizedMessage = errorMessage.toLowerCase() const isDatabaseUnavailable = errorMessage.includes("P1001") const isSchemaMissing = errorMessage.includes("P2021") || normalizedMessage.includes("system_setting") || normalizedMessage.includes("does not exist") const userMessage = isDatabaseUnavailable ? t( "settings.registration.errors.databaseUnavailable", "Saving settings failed. The database is currently unreachable.", ) : isSchemaMissing ? t( "settings.registration.errors.schemaMissing", "Saving settings failed. Apply the latest database migrations and try again.", ) : t( "settings.registration.errors.updateFailed", "Saving settings failed. Ensure database migrations are applied.", ) redirect(`/settings?error=${encodeURIComponent(userMessage)}`) } revalidatePath("/settings") revalidatePath("/register") redirect( `/settings?notice=${encodeURIComponent( t("settings.registration.success.updated", "Registration policy updated."), )}`, ) } async function updatePublicHeaderBannerAction(formData: FormData) { "use server" await requireSettingsPermission() const t = await getSettingsTranslator() const enabled = formData.get("bannerEnabled") === "on" const message = toSingleValue(formData.get("bannerMessage")?.toString())?.trim() ?? "" const ctaLabel = toSingleValue(formData.get("bannerCtaLabel")?.toString())?.trim() ?? "" const ctaHref = toSingleValue(formData.get("bannerCtaHref")?.toString())?.trim() ?? "" if (enabled && message.length === 0) { redirect( `/settings?error=${encodeURIComponent( t( "settings.banner.errors.messageRequired", "Banner message is required while banner is enabled.", ), )}`, ) } try { await setPublicHeaderBannerConfig({ enabled, message, ctaLabel: ctaLabel || null, ctaHref: ctaHref || null, }) } catch { redirect( `/settings?error=${encodeURIComponent( t( "settings.banner.errors.updateFailed", "Saving banner settings failed. Ensure database migrations are applied.", ), )}`, ) } revalidatePath("/settings") redirect( `/settings?notice=${encodeURIComponent( t("settings.banner.success.updated", "Public header banner settings updated."), )}`, ) } export default async function SettingsPage({ searchParams }: { searchParams: SearchParamsInput }) { const role = await requirePermissionForRoute({ nextPath: "/settings", permission: "users:manage_roles", scope: "global", }) const [params, locale, isRegistrationEnabled, publicBanner] = await Promise.all([ searchParams, resolveAdminLocale(), isAdminSelfRegistrationEnabled(), getPublicHeaderBannerConfig(), ]) const messages = await getAdminMessages(locale) const t = (key: string, fallback: string) => translateMessage(messages, key, fallback) const notice = toSingleValue(params.notice) const error = toSingleValue(params.error) return ( {t("settings.actions.backToDashboard", "Back to dashboard")} } > {notice ? (
{notice}
) : null} {error ? (
{error}
) : null}

{t("settings.registration.title", "Admin self-registration")}

{t( "settings.registration.description", "When enabled, /register can create additional admin accounts after initial owner bootstrap.", )}

{t("settings.registration.currentStatusLabel", "Current status")}:{" "} {isRegistrationEnabled ? t("settings.registration.status.enabled", "Enabled") : t("settings.registration.status.disabled", "Disabled")}

{t("settings.banner.title", "Public header banner")}

{t( "settings.banner.description", "Control the top banner shown on the public app header.", )}

) }