import { useState, useEffect } from 'react'; import { AppShell, Burger, Group, Text, Menu, UnstyledButton, Avatar, Alert, Button, ActionIcon, Tooltip } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconLogout, IconSwitchHorizontal, IconChevronDown, IconSettings, IconUserCog, IconUsersGroup, IconEyeOff, IconSun, IconMoon, } from '@tabler/icons-react'; import { Outlet, useNavigate, useLocation } from 'react-router-dom'; import { useAuthStore } from '../../stores/authStore'; import { usePreferencesStore } from '../../stores/preferencesStore'; import { Sidebar } from './Sidebar'; import { AppTour } from '../onboarding/AppTour'; import { OnboardingWizard } from '../onboarding/OnboardingWizard'; import logoSrc from '../../assets/logo.png'; export function AppLayout() { const [opened, { toggle, close }] = useDisclosure(); const { user, currentOrg, logout, impersonationOriginal, stopImpersonation } = useAuthStore(); const { colorScheme, toggleColorScheme } = usePreferencesStore(); const navigate = useNavigate(); const location = useLocation(); const isImpersonating = !!impersonationOriginal; // ── Onboarding State ── const [showTour, setShowTour] = useState(false); const [showWizard, setShowWizard] = useState(false); useEffect(() => { // Only run for non-impersonating users with an org selected, on dashboard if (isImpersonating || !currentOrg || !user) return; if (!location.pathname.startsWith('/dashboard')) return; // Read-only users (viewers) skip onboarding entirely if (currentOrg.role === 'viewer') return; if (user.hasSeenIntro === false || user.hasSeenIntro === undefined) { // Delay to ensure DOM elements are rendered for tour targeting const timer = setTimeout(() => setShowTour(true), 800); return () => clearTimeout(timer); } else if (currentOrg.settings?.onboardingComplete !== true) { setShowWizard(true); } }, [user?.hasSeenIntro, currentOrg?.id, currentOrg?.role, currentOrg?.settings?.onboardingComplete, isImpersonating, location.pathname]); const handleTourComplete = () => { setShowTour(false); // After tour, check if onboarding wizard should run if (currentOrg && currentOrg.settings?.onboardingComplete !== true) { // Small delay before showing wizard setTimeout(() => setShowWizard(true), 500); } }; const handleWizardComplete = () => { setShowWizard(false); }; const handleLogout = () => { logout(); navigate('/login'); }; const handleStopImpersonation = () => { stopImpersonation(); navigate('/admin'); }; // Tenant admins (president role) can manage org members const isTenantAdmin = currentOrg?.role === 'president' || currentOrg?.role === 'admin'; return ( {isImpersonating && ( Impersonating {user?.firstName} {user?.lastName} ({user?.email}) )} HOA LedgerIQ {currentOrg && ( {currentOrg.name} )} {colorScheme === 'dark' ? : } {user?.firstName?.[0]}{user?.lastName?.[0]} {user?.firstName} {user?.lastName} {isImpersonating && ( <> } onClick={handleStopImpersonation} > Stop Impersonating )} Account } onClick={() => navigate('/preferences')} > User Preferences } onClick={() => navigate('/settings')} > Settings {isTenantAdmin && ( } onClick={() => navigate('/org-members')} > Manage Members )} } onClick={() => navigate('/select-org')} > Switch Organization } onClick={handleLogout} > Logout {/* ── Onboarding Components ── */} ); }