diff --git a/web-ui/src/components/app-shell.tsx b/web-ui/src/components/app-shell.tsx index 8852f08..a416df8 100644 --- a/web-ui/src/components/app-shell.tsx +++ b/web-ui/src/components/app-shell.tsx @@ -3,7 +3,7 @@ import type { ReactNode } from "react"; import Link from "next/link"; import { usePathname } from "next/navigation"; -import { ChevronDown } from "lucide-react"; +import { ChevronDown, Settings } from "lucide-react"; import { DropdownMenu, @@ -14,49 +14,59 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { GlobalSearch } from "@/components/global-search"; +import { headerSubtitle } from "@/components/header-context"; -type AgentBoard = { - prefix: string; - label: string; - hint: string; -}; +/** + * Ezer Mishpati navigation shell — two-row header. + * + * Row 1 (brand): logo + dynamic context subtitle · global search · agent boards + * Row 2 (nav): work group · knowledge group · admin dropdown + * + * Editorial/judicial aesthetic preserved: + * - Navy background with a gold hairline rule (border-b-3) + * - Parchment text, gold accents on hover/active + * - Hebrew RTL throughout (set on in layout.tsx) + * - Active item gets `aria-current="page"` and a gold underline anchored + * to the bottom border, so screen readers announce the section and + * sighted users see where they are. + */ + +type NavItem = { href: string; label: string }; +type NavGroup = { id: string; items: NavItem[] }; + +const NAV_GROUPS: NavGroup[] = [ + { + id: "work", + items: [ + { href: "/", label: "בית" }, + { href: "/archive", label: "ארכיון" }, + ], + }, + { + id: "knowledge", + items: [ + { href: "/precedents", label: "ספריית פסיקה" }, + { href: "/training", label: "אימון סגנון" }, + { href: "/methodology", label: "מתודולוגיה" }, + ], + }, +]; + +const ADMIN_ITEMS: NavItem[] = [ + { href: "/skills", label: "מיומנויות" }, + { href: "/diagnostics", label: "אבחון" }, + { href: "/settings", label: "הגדרות" }, +]; + +type AgentBoard = { prefix: string; label: string; hint: string }; const AGENT_BOARDS: AgentBoard[] = [ - { prefix: "CMP", label: "רישוי ובניה", hint: "תיקי 1xxx" }, - { prefix: "CMPA", label: "היטלי השבחה", hint: "תיקי 8xxx / 9xxx" }, + { prefix: "CMP", label: "רישוי ובניה", hint: "תיקי 1xxx" }, + { prefix: "CMPA", label: "היטלי השבחה", hint: "תיקי 8xxx / 9xxx" }, ]; const PAPERCLIP_BASE = "https://pc.nautilus.marcusgroup.org"; -/** - * Ezer Mishpati navigation shell. - * - * Editorial/judicial aesthetic: - * - Navy header with a gold hairline rule (border-b-3) - * - Parchment/cream body background (set on via globals.css) - * - Hebrew RTL throughout (set on in layout.tsx) - * - * Nav items pick up an `aria-current="page"` and a gold underline when - * the current route matches, so screen readers announce the active - * section and sighted users can see where they are. - */ - -type NavItem = { - href: string; - label: string; -}; - -const NAV_ITEMS: NavItem[] = [ - { href: "/", label: "בית" }, - { href: "/archive", label: "ארכיון" }, - { href: "/training", label: "אימון סגנון" }, - { href: "/precedents", label: "ספריית פסיקה" }, - { href: "/methodology", label: "מתודולוגיה" }, - { href: "/skills", label: "מיומנויות" }, - { href: "/diagnostics", label: "אבחון" }, - { href: "/settings", label: "הגדרות" }, -]; - function isActive(pathname: string, href: string): boolean { if (href === "/") return pathname === "/"; return pathname === href || pathname.startsWith(`${href}/`); @@ -64,104 +74,140 @@ function isActive(pathname: string, href: string): boolean { export function AppShell({ children }: { children: ReactNode }) { const pathname = usePathname(); + const subtitle = headerSubtitle(pathname); + const adminActive = ADMIN_ITEMS.some((i) => isActive(pathname, i.href)); return ( <>
- - - עוזר משפטי - - ניהול תיקים - + {/* ─── Row 1 — brand bar ─── */} +
+ + + עוזר משפטי + + + {subtitle} + + -
+ + {/* ─── Row 2 — section nav ─── */} +
+ - -
- -
- - - - - ניהול סוכנים - - - - - - פתח דאשבורד Paperclip - - - {AGENT_BOARDS.map((board) => ( - - - {board.label} - - {board.prefix} · {board.hint} - - - +
+ {group.items.map((item) => ( + + ))} +
+
))} - - + + + + + + + + + מערכת + + + {ADMIN_ITEMS.map((item) => { + const active = isActive(pathname, item.href); + return ( + + + {item.label} + + + ); + })} + + +
); } + +function NavLink({ item, active }: { item: NavItem; active: boolean }) { + return ( + + {item.label} + {active && ( +