import { Settings } from "lucide-react"; import { NavLink, useLocation } from "react-router-dom"; import { useEffect, useMemo, useState } from "react"; import type { AuthInfo, PlatformNavItem } from "../types"; import { hasAnyScope, hasScope } from "../utils/permissions"; const MODULE_NAV_STORAGE_KEY = "govoplan.lastModuleNav"; function visibleNavItems(auth: AuthInfo | null | undefined, navItems: PlatformNavItem[]): PlatformNavItem[] { return [...navItems] .sort((left, right) => (left.order ?? 100) - (right.order ?? 100)) .filter((item) => { if (item.allOf?.length && !item.allOf.every((scope) => hasScope(auth, scope))) return false; if (item.anyOf?.length && !hasAnyScope(auth, item.anyOf)) return false; return true; }); } export default function IconRail({ compact = false, auth = null, navItems = [] }: { compact?: boolean; auth?: AuthInfo | null; navItems?: PlatformNavItem[]; }) { const location = useLocation(); const items = visibleNavItems(auth, navItems); const [rememberedTargets, setRememberedTargets] = useState>(() => loadRememberedTargets()); const topLevelItems = useMemo(() => items.map((item) => item.to), [items]); useEffect(() => { const currentRoot = topLevelItems.find((root) => modulePathActive(location.pathname, root)); if (!currentRoot || location.pathname === currentRoot) return; const target = `${location.pathname}${location.search}${location.hash}`; setRememberedTargets((current) => { if (current[currentRoot] === target) return current; const next = { ...current, [currentRoot]: target }; saveRememberedTargets(next); return next; }); }, [location.hash, location.pathname, location.search, topLevelItems]); return ( ); } function modulePathActive(pathname: string, root: string): boolean { if (root === "/") return pathname === "/"; return pathname === root || pathname.startsWith(`${root}/`); } function loadRememberedTargets(): Record { if (typeof window === "undefined") return {}; try { const raw = window.localStorage.getItem(MODULE_NAV_STORAGE_KEY); const parsed = raw ? JSON.parse(raw) : {}; if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {}; return Object.fromEntries( Object.entries(parsed).filter((entry): entry is [string, string] => { const [root, target] = entry; return typeof root === "string" && typeof target === "string" && root.startsWith("/") && target.startsWith(`${root}/`); }), ); } catch { return {}; } } function saveRememberedTargets(targets: Record): void { if (typeof window === "undefined") return; try { window.localStorage.setItem(MODULE_NAV_STORAGE_KEY, JSON.stringify(targets)); } catch { // Remembered navigation is a convenience only. } }