83 lines
3.2 KiB
TypeScript
83 lines
3.2 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { NextIntlClientProvider } from "next-intl";
|
|
import { getLocale, getMessages } from "next-intl/server";
|
|
import { Nunito } from "next/font/google";
|
|
import { headers } from "next/headers";
|
|
import type { ReactNode } from "react";
|
|
import { Navigation } from "@/components/navigation";
|
|
import { PwaRegister } from "@/components/pwa-register";
|
|
import RadioPlayerGate from "@/components/public/radio-player-gate";
|
|
import { SiteFooter } from "@/components/site-footer";
|
|
import { SiteHeader } from "@/components/site-header";
|
|
import { ThemeVars } from "@/components/theme-vars";
|
|
import { TopHeader } from "@/components/top-header";
|
|
import { enforceSiteAccess } from "@/lib/access-guard";
|
|
import { siteSettings } from "@/lib/services/site-settings";
|
|
import "./globals.css";
|
|
|
|
const nunito = Nunito({
|
|
subsets: ["latin"],
|
|
weight: ["400", "600", "700", "800"],
|
|
display: "swap",
|
|
variable: "--font-nunito",
|
|
});
|
|
|
|
export async function generateMetadata(): Promise<Metadata> {
|
|
const hotel = (await siteSettings.get("hotel_name", "Atom")) ?? "Atom";
|
|
return {
|
|
title: { default: hotel, template: `%s · ${hotel}` },
|
|
description: `${hotel} — a Habbo retro hotel. Hang out, collect furni and meet friends.`,
|
|
};
|
|
}
|
|
|
|
export default async function RootLayout({ children }: { children: ReactNode }) {
|
|
await enforceSiteAccess();
|
|
const locale = await getLocale();
|
|
const messages = await getMessages();
|
|
// "Dusk" / dark-by-default: the site starts dark unless the visitor has picked
|
|
// light. The saved choice always wins over the default.
|
|
const defaultDark = await siteSettings.getBool("default_dark", false);
|
|
|
|
const headersList = await headers();
|
|
const pathname = headersList.get("x-pathname") || "";
|
|
const isClient = pathname === "/client" || pathname.startsWith("/client/");
|
|
return (
|
|
<html lang={locale} className={`app ${nunito.variable}`}>
|
|
<head>
|
|
{/* Apply the saved/default theme before first paint to avoid a flash. */}
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `try{var s=localStorage.getItem('theme');if(s==='dark'||(!s&&${defaultDark}))document.documentElement.classList.add('dark');var nc=localStorage.getItem('navbarColor'),nt=localStorage.getItem('navbarTextColor');if(nc)document.documentElement.style.setProperty('--color-navbar',nc);if(nt)document.documentElement.style.setProperty('--color-navbar-text',nt);}catch(e){}`,
|
|
}}
|
|
/>
|
|
</head>
|
|
<body
|
|
className="flex min-h-screen flex-col site-bg"
|
|
style={{ backgroundColor: "var(--color-background)" }}
|
|
>
|
|
<NextIntlClientProvider locale={locale} messages={messages}>
|
|
<ThemeVars />
|
|
{isClient ? (
|
|
children
|
|
) : (
|
|
<>
|
|
<TopHeader />
|
|
<SiteHeader />
|
|
<Navigation />
|
|
<main className="overflow-hidden">
|
|
<div className="mx-auto mt-10 grid max-w-7xl grid-cols-12 gap-x-3 gap-y-8 p-6 md:mt-0">
|
|
<div className="col-span-12">{children}</div>
|
|
</div>
|
|
</main>
|
|
<SiteFooter />
|
|
<RadioPlayerGate />
|
|
</>
|
|
)}
|
|
<PwaRegister />
|
|
</NextIntlClientProvider>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|
|
|