Improve enterprise tier child tenants access
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import React, { useState, useCallback, forwardRef } from 'react';
|
||||
import React, { useState, useCallback, forwardRef, useEffect } from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useTheme } from '../../../contexts/ThemeContext';
|
||||
import { useHasAccess } from '../../../hooks/useAccessControl';
|
||||
import { useTenant } from '../../../stores/tenant.store';
|
||||
import { Header } from '../Header';
|
||||
import { Sidebar } from '../Sidebar';
|
||||
import { Footer } from '../Footer';
|
||||
@@ -77,10 +79,29 @@ export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
|
||||
const authLoading = false; // Since we're in a protected route, auth loading should be false
|
||||
const { resolvedTheme } = useTheme();
|
||||
const hasAccess = useHasAccess(); // Check both authentication and demo mode
|
||||
const location = useLocation();
|
||||
const { parentTenant, restoreParentTenant } = useTenant();
|
||||
|
||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(initialSidebarCollapsed);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [isRestoringTenant, setIsRestoringTenant] = useState(false);
|
||||
|
||||
// Auto-restore parent tenant context when navigating away from premises detail view
|
||||
useEffect(() => {
|
||||
// If we have a parent tenant stored (meaning we switched to a child premise)
|
||||
// and we're NOT on the premises page, restore the parent tenant
|
||||
if (parentTenant && !location.pathname.includes('/enterprise/premises')) {
|
||||
console.log('[AppShell] Restoring parent tenant context - navigated away from premises');
|
||||
setIsRestoringTenant(true);
|
||||
restoreParentTenant().finally(() => {
|
||||
// Small delay to ensure all components have the updated tenant context
|
||||
setTimeout(() => {
|
||||
setIsRestoringTenant(false);
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}, [location.pathname, parentTenant, restoreParentTenant]);
|
||||
|
||||
// Sidebar control functions
|
||||
const toggleSidebar = useCallback(() => {
|
||||
@@ -188,6 +209,24 @@ export const AppShell = forwardRef<AppShellRef, AppShellProps>(({
|
||||
);
|
||||
}
|
||||
|
||||
// Show loading state during tenant restoration to prevent race condition
|
||||
// CRITICAL: Also check if parentTenant exists and we're NOT on premises page
|
||||
// This catches the case where navigation happens before the useEffect runs
|
||||
const isNavigatingAwayFromChild = parentTenant && !location.pathname.includes('/enterprise/premises');
|
||||
|
||||
if (isRestoringTenant || isNavigatingAwayFromChild) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-[var(--bg-primary)]">
|
||||
{loadingComponent || (
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[var(--color-primary)]"></div>
|
||||
<p className="text-[var(--text-secondary)]">Restaurando contexto...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Show error state
|
||||
if (error && ErrorBoundary) {
|
||||
return <ErrorBoundary error={error}>{children}</ErrorBoundary>;
|
||||
|
||||
@@ -50,7 +50,8 @@ import {
|
||||
Layers,
|
||||
Lightbulb,
|
||||
Activity,
|
||||
List
|
||||
List,
|
||||
Building
|
||||
} from 'lucide-react';
|
||||
|
||||
export interface SidebarProps {
|
||||
@@ -138,6 +139,7 @@ const iconMap: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||
events: Activity,
|
||||
list: List,
|
||||
distribution: Truck,
|
||||
premises: Building,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -196,6 +198,7 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
|
||||
const pathMappings: Record<string, string> = {
|
||||
'/app/dashboard': 'navigation.dashboard',
|
||||
'/app/enterprise/premises': 'navigation.premises',
|
||||
'/app/operations': 'navigation.operations',
|
||||
'/app/operations/procurement': 'navigation.procurement',
|
||||
'/app/operations/production': 'navigation.production',
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { useState, useRef, useEffect } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTenant } from '../../stores/tenant.store';
|
||||
import { useSubscription } from '../../api/hooks/subscription';
|
||||
import { showToast } from '../../utils/toast';
|
||||
import { ChevronDown, Building2, Check, AlertCircle, Plus, X } from 'lucide-react';
|
||||
|
||||
@@ -36,6 +37,8 @@ export const TenantSwitcher: React.FC<TenantSwitcherProps> = ({
|
||||
clearError,
|
||||
} = useTenant();
|
||||
|
||||
const { subscriptionInfo } = useSubscription();
|
||||
|
||||
// NOTE: Removed duplicate loadUserTenants() useEffect
|
||||
// Tenant loading is already handled by useTenantInitializer at app level (stores/useTenantInitializer.ts)
|
||||
// This was causing duplicate /tenants API calls on every dashboard load
|
||||
@@ -167,6 +170,11 @@ export const TenantSwitcher: React.FC<TenantSwitcherProps> = ({
|
||||
navigate('/app/onboarding?new=true');
|
||||
};
|
||||
|
||||
// Don't render for enterprise tier users (they use Premises page instead)
|
||||
if (subscriptionInfo?.plan === 'enterprise') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Don't render if no tenants available
|
||||
if (!availableTenants || availableTenants.length === 0) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user