GUI ans Mockup-Design angepasst (GEFIM-Branding)
- GEFIM-Farbwelt aus dem Mockup als shadcn-Theme: Violett #5d52a3 als Primärfarbe, Magenta/Hellblau-Akzente, Ink-Text, #f5f6fa-Hintergrund, Verlaufs-Utilities (bg-grad, bg-grad-soft), Karten-Schatten - Fonts Poppins (Überschriften/Buttons) + Open Sans (Text), self-hosted über next/font — kein Google-CDN-Aufruf zur Laufzeit (DSGVO) - Sidebar mit extrahiertem GEFIM-Logo (public/gefim-logo.png), aktive Navigation in Violett wie im Prototyp - Sticky Topbar mit globaler Suche (leitet vorerst auf die Asset-Suche), Nutzer-Info und Verlaufs-Avatar mit Initialen; Logout in die Topbar - Primär-Buttons mit Verlaufshintergrund, Level-Badges als Pillen in Mockup-Farben, Login-Seite im GEFIM-Look - Dashboard im Mockup-Stil: KPI-Karten (Assets, Prozesse, kritische Prozesse, Risiken-Platzhalter) und Letzte-Aktivitäten-Feed aus dem echten Audit-Log Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+52
-16
@@ -1,4 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { redirect } from "next/navigation";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import {
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
FolderCheck,
|
||||
Truck,
|
||||
LineChart,
|
||||
Search,
|
||||
} from "lucide-react";
|
||||
import { auth, signOut } from "@/server/auth";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -43,6 +45,13 @@ export default async function AppLayout({
|
||||
{ href: "/review", label: t("review"), icon: LineChart, enabled: false },
|
||||
];
|
||||
|
||||
const initials = (session.user.name ?? "?")
|
||||
.split(/\s+/)
|
||||
.map((p) => p[0])
|
||||
.slice(0, 2)
|
||||
.join("")
|
||||
.toUpperCase();
|
||||
|
||||
async function logout() {
|
||||
"use server";
|
||||
await signOut({ redirectTo: "/login" });
|
||||
@@ -50,42 +59,69 @@ export default async function AppLayout({
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen">
|
||||
<aside className="flex w-60 shrink-0 flex-col border-r bg-sidebar">
|
||||
<div className="flex h-14 items-center border-b px-4">
|
||||
<Link href="/dashboard" className="font-semibold tracking-tight">
|
||||
{tc("appName")}
|
||||
<aside className="flex w-60 shrink-0 flex-col border-r border-sidebar-border bg-sidebar">
|
||||
<div className="border-b border-sidebar-border px-4 pt-5 pb-3.5">
|
||||
<Link href="/dashboard">
|
||||
<Image
|
||||
src="/gefim-logo.png"
|
||||
alt="GEFIM — Informationssicherheit im Mittelstand"
|
||||
width={150}
|
||||
height={53}
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
<nav className="flex-1 space-y-0.5 overflow-y-auto p-2">
|
||||
<nav className="flex-1 space-y-0.5 overflow-y-auto px-2.5 py-3">
|
||||
{nav.map((item) =>
|
||||
item.enabled ? (
|
||||
<NavLink key={item.href} href={item.href} match={item.match}>
|
||||
<item.icon className="size-4" />
|
||||
<item.icon className="size-[18px] opacity-85" />
|
||||
{item.label}
|
||||
</NavLink>
|
||||
) : (
|
||||
<span
|
||||
key={item.href}
|
||||
title={tc("comingSoon")}
|
||||
className="flex cursor-not-allowed items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground/50"
|
||||
className="flex cursor-not-allowed items-center gap-2.5 rounded-lg px-3 py-2 text-[13.5px] font-semibold text-muted-foreground/50"
|
||||
>
|
||||
<item.icon className="size-4" />
|
||||
<item.icon className="size-[18px]" />
|
||||
{item.label}
|
||||
</span>
|
||||
)
|
||||
)}
|
||||
</nav>
|
||||
<div className="border-t p-3 text-xs text-muted-foreground">
|
||||
<p className="truncate font-medium text-foreground">{session.user.name}</p>
|
||||
<p className="truncate">{session.user.tenantSlug}</p>
|
||||
<form action={logout} className="mt-2">
|
||||
<Button type="submit" variant="outline" size="sm" className="w-full">
|
||||
</aside>
|
||||
|
||||
<div className="flex min-w-0 flex-1 flex-col">
|
||||
<header className="sticky top-0 z-10 flex items-center gap-4 border-b bg-white/90 px-6 py-2.5 backdrop-blur-md">
|
||||
<form
|
||||
method="GET"
|
||||
action="/assets"
|
||||
className="flex w-full max-w-105 items-center gap-2 rounded-lg border bg-muted px-3 py-2 text-muted-foreground"
|
||||
>
|
||||
<Search className="size-4 shrink-0" />
|
||||
<input
|
||||
name="q"
|
||||
placeholder={tc("search")}
|
||||
className="w-full border-0 bg-transparent text-[13px] text-foreground outline-none placeholder:text-muted-foreground"
|
||||
/>
|
||||
</form>
|
||||
<div className="flex-1" />
|
||||
<div className="text-right leading-tight">
|
||||
<p className="text-[13px] font-semibold">{session.user.name}</p>
|
||||
<p className="text-xs text-muted-foreground">{session.user.tenantSlug}</p>
|
||||
</div>
|
||||
<div className="bg-grad-soft grid size-9.5 shrink-0 place-items-center rounded-full font-heading text-sm font-bold text-white">
|
||||
{initials}
|
||||
</div>
|
||||
<form action={logout}>
|
||||
<Button type="submit" variant="ghost" size="sm">
|
||||
{tc("logout")}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</aside>
|
||||
<div className="flex min-w-0 flex-1 flex-col">{children}</div>
|
||||
</header>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user