L10b Betrieb & Aufräumen: einklappbare Backoffice-Sidebar, Berichtseditor mit Offline-Entwurf

- Aufräumpunkt g (L1 offener Punkt 10): components/backoffice-frame.tsx – unter 1024 px ist die
  Sidebar ein Drawer hinter einem Menü-Button (44 px, aria-expanded, schließt bei Navigation,
  Hintergrund, Escape); ab 1024 px statisch wie bisher. Header kompakter auf schmalen Screens.
- Aufräumpunkt i (L7 offener Punkt 7): mobiler Berichtseditor speichert ungesicherte Eingaben
  über useOfflineDraft (IndexedDB je Mandant/Nutzer). Ein Entwurf wird nur wiederhergestellt,
  solange die Servertexte unverändert sind (sonst gewinnt der Server, z. B. nach Übernahme eines
  Lotse-Vorschlags); nach Speichern/Absenden gelöscht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 18:19:19 +02:00
co-authored by Claude Opus 5
parent b0aedb5d23
commit 21d6dc016a
5 changed files with 133 additions and 19 deletions
+15 -12
View File
@@ -13,6 +13,7 @@ import { UiLocaleSwitcher } from "@/components/ui-locale-switcher";
import { CraftviaLogo } from "@/components/brand/craftvia-logo";
import { NotificationBell } from "@/components/notifications/bell";
import { AccountInactiveNotice } from "@/components/account-inactive-notice";
import { BackofficeFrame } from "@/components/backoffice-frame";
export default async function AppLayout({
children,
@@ -56,9 +57,8 @@ export default async function AppLayout({
await signOut({ redirectTo: "/login" });
}
return (
<div className="flex min-h-screen">
<aside className="flex w-60 shrink-0 flex-col border-r border-sidebar-border bg-sidebar">
const sidebar = (
<>
<div className="border-b border-sidebar-border px-4 pt-5 pb-3.5">
<Link href="/dashboard" aria-label={branding.productName}>
<TenantBrand branding={branding} height={34} />
@@ -84,15 +84,18 @@ export default async function AppLayout({
</div>
)}
</nav>
</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-[var(--panel)] px-6 py-2.5 backdrop-blur-md">
<form action="/search" role="search" className="flex-1"><input type="search" name="q" aria-label={tc("search")} placeholder={tc("search")} className="h-10 w-full max-w-md rounded-lg border border-input bg-background px-3 text-sm" /></form>
// L10b: collapsible sidebar below 1024 px (src/components/backoffice-frame.tsx)
return (
<BackofficeFrame sidebar={sidebar} labels={{ open: t("openMenu"), close: t("closeMenu") }} header={
<>
<form action="/search" role="search" className="min-w-0 flex-1"><input type="search" name="q" aria-label={tc("search")} placeholder={tc("search")} className="h-10 w-full max-w-md rounded-lg border border-input bg-background px-3 text-sm" /></form>
<NotificationBell />
<UiLocaleSwitcher current={identity.uiLocale} />
<Link href="/account" className="flex items-center gap-3">
<div className="text-right leading-tight">
<div className="hidden text-right leading-tight sm:block">
<p className="text-[13px] font-semibold">{session.user.name}</p>
<p className="text-xs text-muted-foreground">{session.user.tenantSlug}</p>
</div>
@@ -105,9 +108,9 @@ export default async function AppLayout({
{tc("logout")}
</Button>
</form>
</header>
{children}
</div>
</div>
</>
}>
{children}
</BackofficeFrame>
);
}