Navigation: gemeinsamer Kopfbereich statt getrennter Bereiche
Eine Leiste für alles: Gruppe "Speiseplan" (Wochenplan, Gerichte, Allergene & Zusatzstoffe) und für Admins zusätzlich Gruppe "Verwaltung" (Benutzer, Design). Aktiver Menüpunkt wird hervorgehoben, die Konto-Seite nutzt denselben Header – kein Hin- und Herspringen mehr zwischen Kantinen-Bereich und Verwaltung.
This commit is contained in:
+5
-30
@@ -1,6 +1,6 @@
|
|||||||
import Link from "next/link";
|
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { createClient } from "@/lib/supabase/server";
|
import { createClient } from "@/lib/supabase/server";
|
||||||
|
import AppHeader from "@/components/AppHeader";
|
||||||
|
|
||||||
export default async function AdminLayout({
|
export default async function AdminLayout({
|
||||||
children,
|
children,
|
||||||
@@ -22,35 +22,10 @@ export default async function AdminLayout({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
<header className="bg-[var(--c-primary-dark)] text-white">
|
<AppHeader
|
||||||
<div className="max-w-[1600px] mx-auto w-full px-4 py-3 flex flex-wrap items-center gap-x-5 gap-y-2">
|
role="admin"
|
||||||
<span className="font-bold">Verwaltung</span>
|
displayName={profile.full_name || user.email || ""}
|
||||||
<nav className="flex flex-wrap gap-x-4 gap-y-1 text-sm">
|
/>
|
||||||
<Link href="/admin" className="hover:underline">
|
|
||||||
Benutzer
|
|
||||||
</Link>
|
|
||||||
<Link href="/admin/design" className="hover:underline">
|
|
||||||
Design
|
|
||||||
</Link>
|
|
||||||
<Link href="/intern" className="hover:underline">
|
|
||||||
Kantinen-Bereich
|
|
||||||
</Link>
|
|
||||||
<Link href="/" className="hover:underline">
|
|
||||||
Zur Speisekarte
|
|
||||||
</Link>
|
|
||||||
</nav>
|
|
||||||
<div className="ml-auto flex items-center gap-3 text-sm">
|
|
||||||
<Link href="/konto" className="text-white/70 hover:underline">
|
|
||||||
{profile.full_name || user.email}
|
|
||||||
</Link>
|
|
||||||
<form action="/logout" method="post">
|
|
||||||
<button type="submit" className="btn btn-del">
|
|
||||||
Abmelden
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
+5
-35
@@ -1,6 +1,6 @@
|
|||||||
import Link from "next/link";
|
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { createClient } from "@/lib/supabase/server";
|
import { createClient } from "@/lib/supabase/server";
|
||||||
|
import AppHeader from "@/components/AppHeader";
|
||||||
|
|
||||||
export default async function InternLayout({
|
export default async function InternLayout({
|
||||||
children,
|
children,
|
||||||
@@ -22,40 +22,10 @@ export default async function InternLayout({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
<header className="bg-[var(--c-primary-dark)] text-white">
|
<AppHeader
|
||||||
<div className="max-w-[1600px] mx-auto w-full px-4 py-3 flex flex-wrap items-center gap-x-5 gap-y-2">
|
role={profile.role}
|
||||||
<span className="font-bold">Kantinen-Bereich</span>
|
displayName={profile.full_name || user.email || ""}
|
||||||
<nav className="flex flex-wrap gap-x-4 gap-y-1 text-sm">
|
/>
|
||||||
<Link href="/intern" className="hover:underline">
|
|
||||||
Wochenplan
|
|
||||||
</Link>
|
|
||||||
<Link href="/intern/gerichte" className="hover:underline">
|
|
||||||
Gerichte
|
|
||||||
</Link>
|
|
||||||
<Link href="/intern/kennzeichnung" className="hover:underline">
|
|
||||||
Allergene & Zusatzstoffe
|
|
||||||
</Link>
|
|
||||||
{profile.role === "admin" && (
|
|
||||||
<Link href="/admin" className="hover:underline">
|
|
||||||
Verwaltung
|
|
||||||
</Link>
|
|
||||||
)}
|
|
||||||
<Link href="/" className="hover:underline">
|
|
||||||
Zur Speisekarte
|
|
||||||
</Link>
|
|
||||||
</nav>
|
|
||||||
<div className="ml-auto flex items-center gap-3 text-sm">
|
|
||||||
<Link href="/konto" className="text-white/70 hover:underline">
|
|
||||||
{profile.full_name || user.email}
|
|
||||||
</Link>
|
|
||||||
<form action="/logout" method="post">
|
|
||||||
<button type="submit" className="btn btn-del">
|
|
||||||
Abmelden
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
+5
-14
@@ -1,6 +1,6 @@
|
|||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import Link from "next/link";
|
|
||||||
import { createClient } from "@/lib/supabase/server";
|
import { createClient } from "@/lib/supabase/server";
|
||||||
|
import AppHeader from "@/components/AppHeader";
|
||||||
import AccountManager from "@/components/AccountManager";
|
import AccountManager from "@/components/AccountManager";
|
||||||
|
|
||||||
export default async function KontoPage() {
|
export default async function KontoPage() {
|
||||||
@@ -19,19 +19,10 @@ export default async function KontoPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 flex flex-col">
|
<div className="flex-1 flex flex-col">
|
||||||
<header className="bg-[var(--c-primary-dark)] text-white">
|
<AppHeader
|
||||||
<div className="max-w-[1600px] mx-auto w-full px-4 py-3 flex flex-wrap items-center gap-x-5 gap-y-2">
|
role={profile.role}
|
||||||
<span className="font-bold">Mein Konto</span>
|
displayName={profile.full_name || user.email || ""}
|
||||||
<nav className="ml-auto flex flex-wrap gap-x-4 gap-y-1 text-sm">
|
/>
|
||||||
<Link
|
|
||||||
href={profile.role === "admin" ? "/admin" : "/intern"}
|
|
||||||
className="hover:underline"
|
|
||||||
>
|
|
||||||
← Zurück
|
|
||||||
</Link>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
<main className="max-w-[1600px] mx-auto w-full px-4 py-6 flex-1">
|
||||||
<AccountManager
|
<AccountManager
|
||||||
role={profile.role}
|
role={profile.role}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
// Gemeinsamer Kopfbereich für alle internen Seiten. Statt zweier
|
||||||
|
// getrennter Bereiche (Kantine/Verwaltung) gibt es eine Navigation:
|
||||||
|
// Admins sehen zusätzlich die Verwaltungs-Links, der aktive Punkt
|
||||||
|
// wird hervorgehoben.
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import type { Role } from "@/lib/types";
|
||||||
|
|
||||||
|
const MENU_LINKS = [
|
||||||
|
{ href: "/intern", label: "Wochenplan" },
|
||||||
|
{ href: "/intern/gerichte", label: "Gerichte" },
|
||||||
|
{ href: "/intern/kennzeichnung", label: "Allergene & Zusatzstoffe" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const ADMIN_LINKS = [
|
||||||
|
{ href: "/admin", label: "Benutzer" },
|
||||||
|
{ href: "/admin/design", label: "Design" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AppHeader({
|
||||||
|
role,
|
||||||
|
displayName,
|
||||||
|
}: {
|
||||||
|
role: Role;
|
||||||
|
displayName: string;
|
||||||
|
}) {
|
||||||
|
const pathname = usePathname();
|
||||||
|
|
||||||
|
const linkClass = (href: string) =>
|
||||||
|
`rounded px-2 py-0.5 transition-colors hover:bg-white/10 ${
|
||||||
|
pathname === href ? "bg-white/20 font-semibold" : "text-white/90"
|
||||||
|
}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="bg-[var(--c-primary-dark)] text-white">
|
||||||
|
<div className="max-w-[1600px] mx-auto w-full px-4 py-3 flex flex-wrap items-center gap-x-6 gap-y-2 text-sm">
|
||||||
|
<span className="font-bold text-base">Kantine</span>
|
||||||
|
|
||||||
|
<nav
|
||||||
|
className="flex flex-wrap items-center gap-x-1 gap-y-1"
|
||||||
|
aria-label="Speiseplan"
|
||||||
|
>
|
||||||
|
<span className="mr-1 text-xs uppercase tracking-wider text-white/50">
|
||||||
|
Speiseplan
|
||||||
|
</span>
|
||||||
|
{MENU_LINKS.map((l) => (
|
||||||
|
<Link key={l.href} href={l.href} className={linkClass(l.href)}>
|
||||||
|
{l.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{role === "admin" && (
|
||||||
|
<nav
|
||||||
|
className="flex flex-wrap items-center gap-x-1 gap-y-1"
|
||||||
|
aria-label="Verwaltung"
|
||||||
|
>
|
||||||
|
<span className="mr-1 text-xs uppercase tracking-wider text-white/50">
|
||||||
|
Verwaltung
|
||||||
|
</span>
|
||||||
|
{ADMIN_LINKS.map((l) => (
|
||||||
|
<Link key={l.href} href={l.href} className={linkClass(l.href)}>
|
||||||
|
{l.label}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="rounded px-2 py-0.5 text-white/70 hover:bg-white/10"
|
||||||
|
>
|
||||||
|
Speisekarte ansehen
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<div className="ml-auto flex items-center gap-3">
|
||||||
|
<Link
|
||||||
|
href="/konto"
|
||||||
|
title="Mein Konto"
|
||||||
|
className={`rounded px-2 py-0.5 hover:bg-white/10 ${
|
||||||
|
pathname === "/konto"
|
||||||
|
? "bg-white/20 font-semibold"
|
||||||
|
: "text-white/80"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{displayName}
|
||||||
|
</Link>
|
||||||
|
<form action="/logout" method="post">
|
||||||
|
<button type="submit" className="btn btn-del">
|
||||||
|
Abmelden
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user