import Link from "next/link"; import { getTranslations } from "next-intl/server"; import { signOut } from "@/server/auth"; import { dbForTenant } from "@/server/db"; import { requireAppAccess } from "@/server/app-access"; import { NAV_ITEMS, visibleNavItems } from "@/lib/nav"; import { resolveTenantBranding } from "@/lib/brand"; import { Button } from "@/components/ui/button"; import { NavLink } from "@/components/nav-link"; import { TenantBrand } from "@/components/brand/tenant-brand"; import { TenantSwitcher } from "@/components/tenant-switcher"; import { UiLocaleSwitcher } from "@/components/ui-locale-switcher"; import { CraftviaLogo } from "@/components/brand/craftvia-logo"; import { NotificationBell } from "@/components/notifications/bell"; import { AccountInactiveNotice } from "@/components/account-inactive-notice"; import { BackofficeFrame } from "@/components/backoffice-frame"; export default async function AppLayout({ children, }: Readonly<{ children: React.ReactNode }>) { // Session-, Konto-, Passwort- und MFA-Prüfungen: gemeinsam mit der Mobile-Shell // (src/server/app-access.ts). const access = await requireAppAccess(); if (access.kind === "inactive") return ; const { session, identity } = access; const t = await getTranslations("nav"); const tc = await getTranslations("common"); // Navigation aus src/lib/nav.ts, gefiltert nach aktiven Modulen + Rechten (Komfort; // Seiten/Actions prüfen serverseitig selbst). const [moduleRows, brandingSettings] = await Promise.all([ dbForTenant(session.user.tenantId).tenantModule.findMany(), dbForTenant(session.user.tenantId).tenantSettings.findUnique({ where: { tenantId: session.user.tenantId }, select: { accent: true }, }), ]); const branding = resolveTenantBranding(brandingSettings); const disabledModules = new Set(moduleRows.filter((m) => !m.enabled).map((m) => m.moduleKey)); const navItems = visibleNavItems(NAV_ITEMS, { disabledModules, permissions: session.user.permissions ?? [], }); const mainNav = navItems.filter((i) => i.section === "main"); const adminNav = navItems.filter((i) => i.section === "admin"); const initials = (session.user.name ?? "?") .split(/\s+/) .map((p) => p[0]) .slice(0, 2) .join("") .toUpperCase(); async function logout() { "use server"; await signOut({ redirectTo: "/login" }); } const sidebar = ( <>
); // L10b: collapsible sidebar below 1024 px (src/components/backoffice-frame.tsx) return (

{session.user.name}

{session.user.tenantSlug}

{initials}
}> {children}
); }