initial booking

This commit is contained in:
Ola Malmgren
2026-05-22 10:50:48 +02:00
commit 4d705a1005
77 changed files with 13827 additions and 0 deletions

View 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>
);
}