Fix layout: hide site chrome for unauthenticated users, match magic-hotel layout exactly
Local Build and Deploy / deploy (push) Successful in 55s

This commit is contained in:
openhands committed 2026-07-16 20:13:04 +02:00
1 parent 9889131b03
commit 008e7d921b
3 files changed
+151 -176

No files matched your search

+19 -8
View File
@@ -4,24 +4,35 @@ import RadioPlayerGate from "@/components/public/radio-player-gate";
import { SiteFooter } from "@/components/site-footer";
import { SiteHeader } from "@/components/site-header";
import { TopHeader } from "@/components/top-header";
import { auth } from "@/lib/auth";
/**
* Public site chrome. Route group `(site)` keeps this off `/admin` and `/client`,
* so housekeeping is never constrained by the public max-w-7xl grid.
*
* When the user is not authenticated, the header/nav chrome is hidden so that
* the login page acts as a full-screen landing page (magic-hotel style).
*/
export default function SiteLayout({ children }: { children: ReactNode }) {
export default async function SiteLayout({ children }: { children: ReactNode }) {
const session = await auth();
const authenticated = !!session?.user;
return (
<>
<TopHeader />
<SiteHeader />
<Navigation />
{authenticated && (
<>
<TopHeader />
<SiteHeader />
<Navigation />
</>
)}
<main>
<div className="mx-auto mt-6 grid max-w-7xl grid-cols-12 gap-x-3 gap-y-6 px-4 py-4 md:mt-0 md:p-6">
<div className="col-span-12 min-w-0">{children}</div>
<div className={authenticated ? "mx-auto mt-6 grid max-w-7xl grid-cols-12 gap-x-3 gap-y-6 px-4 py-4 md:mt-0 md:p-6" : ""}>
<div className={authenticated ? "col-span-12 min-w-0" : ""}>{children}</div>
</div>
</main>
<SiteFooter />
<RadioPlayerGate />
{authenticated && <SiteFooter />}
{authenticated && <RadioPlayerGate />}
</>
);
}
+62 -68
View File
@@ -1,6 +1,6 @@
"use client";
import { LogIn, UserPlus } from "lucide-react";
import { LogIn, UserPlus, ArrowRight, User, Lock } from "lucide-react";
import Link from "next/link";
import { signIn } from "next-auth/react";
import { type FormEvent, useState } from "react";
@@ -49,100 +49,94 @@ export function HomeLoginForm() {
}
return (
<form onSubmit={onSubmit} className="space-y-4">
<form onSubmit={onSubmit} className="w-full flex flex-col justify-center space-y-5">
{error && (
<div className="rounded-lg bg-red-500/10 border border-red-500/20 px-4 py-2.5">
<div className="rounded-md bg-red-500/10 border border-red-500/20 px-4 py-2.5">
<p className="text-xs font-bold text-red-400 text-center m-0">
{error}
</p>
</div>
)}
<div className="space-y-3.5">
<div>
<label className="block text-gray-500 text-[10px] font-black uppercase tracking-widest mb-1.5 ml-1">
Username
</label>
<div className="relative group">
<div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-600 group-focus-within:text-[#5AB4C6] transition-colors">
<User size={16} />
</div>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
className="w-full pl-10 pr-3 px-4 py-3 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
required
disabled={needs2fa}
/>
</div>
</div>
<div>
<label className="block text-gray-500 text-[10px] font-black uppercase tracking-widest mb-1.5 ml-1">
Password
</label>
<div className="relative group">
<div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-600 group-focus-within:text-[#5AB4C6] transition-colors">
<Lock size={16} />
</div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
className="w-full pl-10 pr-3 px-4 py-3 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
required
disabled={needs2fa}
/>
</div>
</div>
{needs2fa && (
<div>
<label className="block text-gray-500 text-[10px] font-black uppercase tracking-widest mb-1.5 ml-1">
Username
2FA Code
</label>
<div className="relative group">
<div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-600 group-focus-within:text-[#5AB4C6] transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" />
<circle cx="12" cy="7" r="4" />
</svg>
<Lock size={16} />
</div>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
className="w-full pl-10 pr-4 py-3 bg-white/5 border border-white/10 rounded-lg focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
required
disabled={needs2fa}
value={code}
onChange={(e) => setCode(e.target.value)}
placeholder="Enter your 2FA code"
inputMode="numeric"
autoFocus
className="w-full pl-10 pr-3 px-4 py-3 bg-white/5 border border-white/10 rounded-md focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
/>
</div>
</div>
<div>
<label className="block text-gray-500 text-[10px] font-black uppercase tracking-widest mb-1.5 ml-1">
Password
</label>
<div className="relative group">
<div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-600 group-focus-within:text-[#5AB4C6] transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect width="18" height="11" x="3" y="11" rx="2" ry="2" />
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
</div>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
className="w-full pl-10 pr-4 py-3 bg-white/5 border border-white/10 rounded-lg focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
required
disabled={needs2fa}
/>
</div>
</div>
{needs2fa && (
<div>
<label className="block text-gray-500 text-[10px] font-black uppercase tracking-widest mb-1.5 ml-1">
2FA Code
</label>
<div className="relative group">
<div className="absolute left-3.5 top-1/2 -translate-y-1/2 text-gray-600 group-focus-within:text-[#5AB4C6] transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect width="18" height="11" x="3" y="11" rx="2" ry="2" />
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
</div>
<input
type="text"
value={code}
onChange={(e) => setCode(e.target.value)}
placeholder="Enter your 2FA code"
inputMode="numeric"
autoFocus
className="w-full pl-10 pr-4 py-3 bg-white/5 border border-white/10 rounded-lg focus:outline-none focus:border-[#5AB4C6]/50 focus:bg-[#5AB4C6]/5 text-sm text-white placeholder-gray-500 transition-all font-medium"
/>
</div>
</div>
)}
</div>
)}
<button
type="submit"
disabled={pending}
className="w-full group relative flex items-center justify-center gap-2 bg-[#5AB4C6] hover:bg-[#5AB4C6]/90 text-white font-black text-xs py-3.5 rounded-lg transition-all disabled:opacity-50 active:scale-[0.98] uppercase tracking-widest"
className="w-full group relative flex items-center justify-center gap-2 bg-[#5AB4C6] hover:bg-[#5AB4C6] text-white font-black text-sm py-3.5 rounded-md transition-all disabled:opacity-50 active:scale-[0.98]"
>
<LogIn size={14} />
{pending ? "Please wait..." : needs2fa ? "Verify" : "Login"}
<LogIn size={16} />
<span className="uppercase tracking-widest">
{pending ? "Please wait..." : needs2fa ? "Verify" : "Sign In"}
</span>
<ArrowRight size={16} className="group-hover:translate-x-1 transition-transform" />
</button>
<div className="pt-4 border-t border-white/5 text-center">
<div className="pt-5 border-t border-white/5 text-center">
<Link href="/register">
<div className="flex items-center justify-center gap-2 w-full py-3 rounded-lg bg-white/5 border border-white/10 text-white text-[11px] font-black hover:bg-white/10 transition-all active:scale-95 uppercase tracking-wider">
<div className="flex items-center justify-center gap-2 w-full py-3 rounded-md bg-white/5 border border-white/10 text-white text-xs font-black hover:bg-white/10 transition-all active:scale-95 uppercase tracking-wider">
<UserPlus size={14} className="text-[#5AB4C6]" />
Create account
<span>No account yet? Register now</span>
</div>
</Link>
</div>
+70 -100
View File
@@ -1,4 +1,4 @@
import { ArrowRight, Newspaper, Users } from "lucide-react";
import { ArrowRight, Newspaper, Users, User } from "lucide-react";
import Image from "next/image";
import Link from "next/link";
import { getTranslations } from "next-intl/server";
@@ -10,6 +10,12 @@ import { siteSettings } from "@/lib/services/site-settings";
export default async function GuestView() {
const t = await getTranslations("pages.home");
const hotelName = await siteSettings.get("hotel_name", "Atom");
const header = await siteSettings.get("cms_header", "/assets/images/banner.png");
const logo = await siteSettings.get("cms_logo", "");
const bannerUrl = header && header !== "/assets/images/background.png"
? header
: "/assets/images/banner.png";
const imager =
(await siteSettings.get(
"habbo_imaging_url",
@@ -39,109 +45,73 @@ export default async function GuestView() {
});
} catch {}
let onlineCount = 0;
try {
onlineCount = await prisma.user.count({ where: { online: "1" } });
} catch {}
return (
<div className="flex flex-col gap-10">
{/* Hero Section */}
<div className="relative overflow-hidden rounded-3xl bg-[#09090b] border border-white/[0.06] shadow-2xl">
<div className="absolute inset-0 bg-gradient-to-br from-[#5AB4C6]/5 via-transparent to-transparent" />
<div className="absolute top-0 left-1/4 w-[600px] h-[600px] bg-[#5AB4C6]/5 rounded-full blur-[120px]" />
<div className="absolute -bottom-20 -right-20 w-80 h-80 bg-white/[0.03] rounded-full blur-[80px]" />
<div className="relative flex flex-col items-center gap-8 px-6 py-10 md:flex-row md:px-10 md:py-12">
{/* Left: Welcome */}
<div className="flex-1 text-center md:text-left">
<div className="inline-flex items-center gap-2 rounded-full border border-[#5AB4C6]/20 bg-[#5AB4C6]/10 px-4 py-1.5 mb-5">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[#5AB4C6] opacity-80" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-[#5AB4C6]" />
</span>
<span className="text-[10px] font-black uppercase tracking-widest text-[#5AB4C6]">
Online
</span>
</div>
<div className="flex flex-col items-center gap-8">
{/* Logo + Online Count */}
<div className="flex items-center gap-3">
{logo ? (
<Image
src={logo}
alt={hotelName ?? "Hotel"}
width={250}
height={80}
className="block"
unoptimized
/>
) : (
<h1 className="text-3xl font-black text-white tracking-tight m-0">
{hotelName}
</h1>
)}
<div className="flex items-center gap-2 px-4 py-4 border border-[#5AB4C6]/50 bg-[#5AB4C6]/20 rounded-md">
<div className="w-2 h-2 bg-[#5AB4C6] rounded-full animate-pulse" />
<span className="text-white font-black text-xs uppercase tracking-wider">
{onlineCount} Online
</span>
</div>
</div>
<h1 className="m-0 text-3xl font-black tracking-tight text-white md:text-4xl">
Welcome to{" "}
<span className="text-[#5AB4C6]">{hotelName}</span>
</h1>
<p className="mt-3 max-w-md text-sm text-white/50 leading-relaxed">
Connect with friends, explore the hotel, and create unforgettable
memories. Your adventure starts here.
</p>
<div className="mt-7 flex flex-wrap gap-3">
<Link href="/register">
<div className="inline-flex items-center gap-2 bg-[#5AB4C6] hover:bg-[#5AB4C6]/90 text-white font-black text-xs py-3.5 px-7 rounded-lg transition-all active:scale-[0.98] uppercase tracking-widest shadow-lg shadow-[#5AB4C6]/20">
Get Started <ArrowRight size={14} />
</div>
</Link>
<Link href="/news">
<div className="inline-flex items-center gap-2 bg-white/5 hover:bg-white/10 text-white font-black text-xs py-3.5 px-7 rounded-lg transition-all active:scale-[0.98] uppercase tracking-widest border border-white/10">
Latest News
</div>
</Link>
</div>
{/* Stats */}
<div className="mt-8 flex gap-6">
<div>
<p className="text-lg font-black text-white m-0">
{articles.length}
</p>
<p className="text-[10px] font-black uppercase tracking-widest text-white/30 m-0 mt-0.5">
Articles
</p>
</div>
<div>
<p className="text-lg font-black text-white m-0">
{recentUsers.length}+
</p>
<p className="text-[10px] font-black uppercase tracking-widest text-white/30 m-0 mt-0.5">
Active Users
</p>
</div>
</div>
{/* Main Card: 900x500 split layout */}
<div className="w-[900px] h-[500px] overflow-hidden rounded-md bg-white/5 backdrop-blur-2xl flex max-w-full">
{/* Left: Login Form */}
<div className="w-1/2 flex flex-col justify-center px-10">
<div className="mb-6 text-center">
<h2 className="text-xl font-black text-white mb-1.5 tracking-tight uppercase">
Sign In
</h2>
<div className="h-1 w-full bg-[#5AB4C6] rounded-full" />
</div>
<HomeLoginForm />
</div>
{/* Right: Login Form */}
<div className="w-full max-w-sm shrink-0">
<div
className="rounded-2xl border border-white/10 p-6"
style={{
background:
"linear-gradient(135deg, rgba(255,255,255,0.05) 0%, rgba(255,255,255,0.02) 100%)",
backdropFilter: "blur(32px)",
WebkitBackdropFilter: "blur(32px)",
}}
>
<div className="flex items-center gap-2.5 mb-5">
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-[#5AB4C6]/10">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="#5AB4C6"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<rect width="18" height="11" x="3" y="11" rx="2" ry="2" />
<path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
</div>
<span className="text-sm font-black text-white tracking-wide">
Sign In
</span>
{/* Right: Hotel Image with Overlay */}
<div className="w-1/2 relative overflow-hidden">
<Image
src={bannerUrl}
alt={hotelName ?? "Hotel"}
fill
className="object-cover object-center scale-110"
unoptimized
/>
<div className="absolute inset-0 bg-gradient-to-br from-[#5AB4C6] via-transparent to-[#5AB4C6]" />
<div className="absolute inset-0 bg-black/30" />
<div className="absolute inset-0 flex flex-col items-center justify-center z-20">
<div className="w-[140px] h-[140px] rounded-md bg-white/10 border border-white/20 backdrop-blur-xl overflow-hidden flex items-center justify-center shadow-[0_0_60px_rgba(130,204,221,0.35)]">
<div className="text-white/40">
<User size={64} strokeWidth={1.5} />
</div>
<HomeLoginForm />
</div>
</div>
</div>
</div>
{/* Articles + Sidebar */}
<div className="grid gap-6 lg:grid-cols-3">
<div className="w-full max-w-[900px] grid gap-6 lg:grid-cols-3 mt-6">
{/* Latest News */}
<div className="lg:col-span-2 animate-slide-up">
<div className="mb-5 flex items-center justify-between">
@@ -172,7 +142,7 @@ export default async function GuestView() {
<Link
key={a.slug}
href={`/news/${a.slug}`}
className="group relative overflow-hidden rounded-2xl border border-white/10 bg-white/[0.03] transition-all duration-300 hover:bg-white/[0.06] hover:-translate-y-1"
className="group relative overflow-hidden rounded-md border border-white/10 bg-white/[0.03] transition-all duration-300 hover:bg-white/[0.06] hover:-translate-y-1"
style={{ animationDelay: `${i * 100}ms` }}
>
<div className="relative aspect-[16/9] overflow-hidden">
@@ -201,9 +171,9 @@ export default async function GuestView() {
<Link
key={a.slug}
href={`/news/${a.slug}`}
className="group flex items-center gap-3 rounded-xl border border-white/10 bg-white/[0.03] p-3 transition-all duration-200 hover:bg-white/[0.06] hover:-translate-y-0.5"
className="group flex items-center gap-3 rounded-md border border-white/10 bg-white/[0.03] p-3 transition-all duration-200 hover:bg-white/[0.06] hover:-translate-y-0.5"
>
<div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-lg">
<div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-md">
<Image
src={a.image}
alt={a.title}
@@ -236,7 +206,7 @@ export default async function GuestView() {
>
{/* Recent Users */}
{recentUsers.length > 0 && (
<div className="rounded-2xl border border-white/10 bg-white/[0.03] overflow-hidden">
<div className="rounded-md border border-white/10 bg-white/[0.03] overflow-hidden">
<div className="flex items-center gap-2.5 px-5 py-3.5 border-b border-white/[0.06]">
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-[#5AB4C6]/10">
<Users className="h-3.5 w-3.5 text-[#5AB4C6]" />
@@ -252,7 +222,7 @@ export default async function GuestView() {
href={`/u/${u.username}`}
className="group relative flex items-center justify-center transition-all duration-200 hover:scale-110"
>
<div className="relative h-14 w-14 overflow-hidden rounded-xl border-2 border-transparent bg-white/5 transition-all duration-200 group-hover:border-[#5AB4C6]/30 group-hover:shadow-lg">
<div className="relative h-14 w-14 overflow-hidden rounded-md border-2 border-transparent bg-white/5 transition-all duration-200 group-hover:border-[#5AB4C6]/30 group-hover:shadow-lg">
<Image
src={avatarImageUrl(imager, u.look, {
headOnly: true,
@@ -282,7 +252,7 @@ export default async function GuestView() {
{/* Quick Register CTA */}
<Link href="/register" className="group block">
<div className="relative overflow-hidden rounded-2xl border border-white/10 bg-white/[0.03] px-6 py-8 text-center transition-all duration-300 hover:bg-white/[0.06] hover:-translate-y-1">
<div className="relative overflow-hidden rounded-md border border-white/10 bg-white/[0.03] px-6 py-8 text-center transition-all duration-300 hover:bg-white/[0.06] hover:-translate-y-1">
<div className="absolute -top-10 -right-10 h-32 w-32 rounded-full bg-[#5AB4C6]/10 blur-3xl" />
<div className="absolute -bottom-10 -left-10 h-24 w-24 rounded-full bg-[#5AB4C6]/10 blur-3xl" />
<div className="relative">
@@ -309,7 +279,7 @@ export default async function GuestView() {
<p className="mt-1 text-xs text-white/40">
Create your free account and start your adventure!
</p>
<div className="mt-5 inline-flex items-center gap-2 bg-[#5AB4C6] hover:bg-[#5AB4C6]/90 text-white font-black text-xs py-3 px-6 rounded-lg transition-all active:scale-[0.98] uppercase tracking-widest shadow-lg shadow-[#5AB4C6]/20">
<div className="mt-5 inline-flex items-center gap-2 bg-[#5AB4C6] hover:bg-[#5AB4C6]/90 text-white font-black text-xs py-3 px-6 rounded-md transition-all active:scale-[0.98] uppercase tracking-widest shadow-lg shadow-[#5AB4C6]/20">
Register Now <ArrowRight className="h-3.5 w-3.5" />
</div>
</div>