import { useEffect, useState } from "react"; import { DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, } from "@/components/ds/ui/dropdown-menu"; import { Database, Settings, User, Webhook, ArrowLeft, Cpu, } from "lucide-react"; import { CanAccess, useTranslate } from "ra-core"; import { Link, matchPath, useLocation, useNavigate } from "react-router"; import { RefreshButton } from "@/components/ds/admin/refresh-button"; import { ThemeModeToggle } from "@/components/ds/admin/theme-mode-toggle"; import { UserMenu } from "@/components/ds/admin/user-menu"; import { LocalesMenuButton } from "@/components/ds/admin/locales-menu-button"; import { useUserMenu } from "@/hooks/user-menu-context"; import { MigrationPulseIndicator } from "@/components/atomic-crm/migration"; import { useMigrationContextSafe } from "@/contexts/MigrationContext"; import { Button } from "@/components/ds/ui/button"; import { ChangelogModal } from "./ChangelogModal"; import { AISettingsModal } from "./AISettingsModal"; import { useConfigurationContext } from "../root/ConfigurationContext"; const Header = () => { const { darkModeLogo, lightModeLogo, title } = useConfigurationContext(); const location = useLocation(); const migrationContext = useMigrationContextSafe(); const translate = useTranslate(); const [isDialogOpen, setIsDialogOpen] = useState(false); const [changelogOpen, setChangelogOpen] = useState(false); const [isAISettingsOpen, setIsAISettingsOpen] = useState(false); // Simplified path matching logic const navPaths = [ { path: "/", pattern: "/" }, { path: "/contacts", pattern: "/contacts/*" }, { path: "/companies", pattern: "/companies/*" }, { path: "/deals", pattern: "/deals/*" }, { path: "/invoices", pattern: "/invoices/*" }, { path: "/tasks", pattern: "/tasks/*" }, { path: "/ai", pattern: "/ai/*" }, ]; const currentPath = navPaths.find((nav) => matchPath(nav.pattern, location.pathname))?.path || false; // Show pulse indicator when migration is needed but banner is dismissed const showPulseIndicator = migrationContext?.migrationStatus?.needsMigration && !migrationContext?.showMigrationBanner; // Check if a dialog is currently open (synchronous check to prevent flash) const checkDialogSync = () => { const dialogOpen = document.querySelector( '[role="dialog"][data-state="open"]', ); return !!dialogOpen; }; // Detect if a dialog/modal is currently open useEffect(() => { const checkDialog = () => { // Check if a dialog overlay exists in the DOM // We look for role="dialog" which covers both Dialog and Sheet components // and ensure it is in the open state const dialogOpen = checkDialogSync(); setIsDialogOpen(dialogOpen); }; // Check on mount and when location changes checkDialog(); // Use MutationObserver to detect dialog state changes const observer = new MutationObserver(checkDialog); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-state"], }); return () => observer.disconnect(); }, [location.pathname]); // Determine if back button should be shown // Use whitelist approach: show only on specific non-modal pages const backButtonPages = ["/settings", "/database", "/integrations", "/sales"]; const isBackButtonPage = backButtonPages.some((page) => location.pathname.startsWith(page)) || /\/show$/.test(location.pathname); // Check dialog state synchronously during render to prevent flash const isDialogCurrentlyOpen = isDialogOpen || checkDialogSync(); const showBackButton = isBackButtonPage && !isDialogCurrentlyOpen; return (
{showBackButton && }
{showPulseIndicator && ( migrationContext?.openMigrationModal()} /> )}
); }; const Logo = ({ darkLogo, lightLogo, title, }: { darkLogo: string; lightLogo: string; title: string; }) => ( {`${title} {`${title}

{title}

); const BackButton = () => { const navigate = useNavigate(); const translate = useTranslate(); return ( ); }; const NavigationTab = ({ label, to, isActive, }: { label: string; to: string; isActive: boolean; }) => ( {label} ); const UsersMenu = () => { const { onClose } = useUserMenu() ?? {}; const translate = useTranslate(); return ( {translate("crm.nav.users")} ); }; const ConfigurationMenu = () => { const { onClose } = useUserMenu() ?? {}; const translate = useTranslate(); return ( {translate("crm.nav.settings")} ); }; const DatabaseMenu = () => { const { onClose } = useUserMenu() ?? {}; const translate = useTranslate(); return ( {translate("crm.nav.database")} ); }; const IntegrationsMenu = () => { const { onClose } = useUserMenu() ?? {}; const translate = useTranslate(); return ( {translate("crm.nav.integrations")} ); }; export default Header;