- Responsive sidebar: collapses on mobile with hamburger menu, slide-in animation - Skeleton loaders: dashboard cards, case table, case detail page - Empty states: friendly messages with icons for cases, deadlines, parties, documents - Error states: retry button on dashboard, proper error message on case not found - Form validation: inline error messages on case creation form - German language: fix all missing umlauts (Zurück, wählen, Anhängig, Verfügung, etc.) - Status labels: display German translations instead of raw status values - Transitions: fade-in animations on page load, hover/transition-colors on all interactive elements - Focus states: focus-visible ring for keyboard accessibility - Mobile layout: stacking for filters, forms, tabs; horizontal scroll for tables - Extraction results: card layout on mobile, table on desktop - Missing types: add DashboardData, DeadlineSummary, CaseSummary, ExtractedDeadline etc. - Fix QuickActions links to use correct routes (/cases/new, /ai/extract) - Consistent input focus styles across all forms
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { createClient } from "@/lib/supabase/client";
|
|
import { TenantSwitcher } from "./TenantSwitcher";
|
|
import { LogOut } from "lucide-react";
|
|
import { useRouter } from "next/navigation";
|
|
import { useEffect, useState } from "react";
|
|
|
|
export function Header() {
|
|
const [email, setEmail] = useState<string | null>(null);
|
|
const router = useRouter();
|
|
const supabase = createClient();
|
|
|
|
useEffect(() => {
|
|
supabase.auth.getUser().then(({ data: { user } }) => {
|
|
setEmail(user?.email ?? null);
|
|
});
|
|
}, [supabase.auth]);
|
|
|
|
async function handleLogout() {
|
|
await supabase.auth.signOut();
|
|
router.push("/login");
|
|
router.refresh();
|
|
}
|
|
|
|
return (
|
|
<header className="flex h-14 items-center justify-between border-b border-neutral-200 bg-white px-4">
|
|
{/* Spacer for mobile hamburger */}
|
|
<div className="w-8 lg:w-0" />
|
|
<div className="flex items-center gap-2 sm:gap-3">
|
|
<TenantSwitcher />
|
|
{email && (
|
|
<span className="hidden text-sm text-neutral-500 sm:inline">
|
|
{email}
|
|
</span>
|
|
)}
|
|
<button
|
|
onClick={handleLogout}
|
|
title="Abmelden"
|
|
className="rounded-md p-1.5 text-neutral-400 transition-colors hover:bg-neutral-100 hover:text-neutral-600"
|
|
>
|
|
<LogOut className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|