initial booking
This commit is contained in:
90
src/app/[locale]/admin/layout.tsx
Normal file
90
src/app/[locale]/admin/layout.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { setRequestLocale, getTranslations } from 'next-intl/server';
|
||||
import { signOut } from '@/auth';
|
||||
import { getSafeSession } from '@/lib/safeAuth';
|
||||
import { Link } from '@/i18n/routing';
|
||||
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
|
||||
|
||||
export default async function AdminLayout({
|
||||
children,
|
||||
params,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
setRequestLocale(locale);
|
||||
const session = await getSafeSession();
|
||||
const t = await getTranslations('admin');
|
||||
|
||||
// Public login page is handled in admin/login/page.tsx — but layout still wraps it.
|
||||
// For non-login admin routes we redirect when not signed in via a route segment guard.
|
||||
// Here we expose `session` to the rendered children via a server util; simpler:
|
||||
// we redirect from this layout only when path is NOT /admin/login. Since segment
|
||||
// info isn't easily accessible, we let each page check itself. Login page will not redirect.
|
||||
// We do the protection by rendering the nav only when signed in; pages must call requireAdmin().
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-ink-50">
|
||||
<header className="border-b border-ink-200 bg-white">
|
||||
<div className="mx-auto flex max-w-6xl items-center justify-between gap-3 px-4 py-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link href="/admin" className="text-base font-semibold text-ink-900">
|
||||
{t('title')}
|
||||
</Link>
|
||||
{session?.user && (
|
||||
<nav className="hidden gap-1 sm:flex">
|
||||
<Link
|
||||
href="/admin"
|
||||
className="rounded-md px-3 py-1.5 text-sm text-ink-600 hover:bg-ink-100"
|
||||
>
|
||||
{t('nav.bookings')}
|
||||
</Link>
|
||||
<Link
|
||||
href="/admin/products"
|
||||
className="rounded-md px-3 py-1.5 text-sm text-ink-600 hover:bg-ink-100"
|
||||
>
|
||||
{t('nav.products')}
|
||||
</Link>
|
||||
<Link
|
||||
href="/admin/pickup-slots"
|
||||
className="rounded-md px-3 py-1.5 text-sm text-ink-600 hover:bg-ink-100"
|
||||
>
|
||||
{t('nav.pickupSlots')}
|
||||
</Link>
|
||||
<Link
|
||||
href="/admin/settings"
|
||||
className="rounded-md px-3 py-1.5 text-sm text-ink-600 hover:bg-ink-100"
|
||||
>
|
||||
{t('nav.settings')}
|
||||
</Link>
|
||||
<Link
|
||||
href="/admin/users"
|
||||
className="rounded-md px-3 py-1.5 text-sm text-ink-600 hover:bg-ink-100"
|
||||
>
|
||||
{t('nav.users')}
|
||||
</Link>
|
||||
</nav>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<LanguageSwitcher />
|
||||
{session?.user && (
|
||||
<form
|
||||
action={async () => {
|
||||
'use server';
|
||||
await signOut({ redirectTo: '/admin/login' });
|
||||
}}
|
||||
>
|
||||
<button type="submit" className="btn-ghost text-xs">
|
||||
{t('nav.signOut')}
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main className="mx-auto max-w-6xl px-4 py-6">{children}</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user