import { Routes, Route, Navigate } from 'react-router'; import { LoginPage } from './auth/LoginPage'; import { CallbackPage } from './auth/CallbackPage'; import { ProtectedRoute } from './auth/ProtectedRoute'; import { OrgResolver } from './auth/OrgResolver'; import { Layout } from './components/Layout'; import { RequireScope } from './components/RequireScope'; import { useScopes } from './auth/useScopes'; import { useOrgStore } from './auth/useOrganization'; import { VendorTenantsPage } from './pages/vendor/VendorTenantsPage'; import { CreateTenantPage } from './pages/vendor/CreateTenantPage'; import { TenantDetailPage } from './pages/vendor/TenantDetailPage'; import { TenantDashboardPage } from './pages/tenant/TenantDashboardPage'; import { TenantLicensePage } from './pages/tenant/TenantLicensePage'; import { OidcConfigPage } from './pages/tenant/OidcConfigPage'; import { TeamPage } from './pages/tenant/TeamPage'; import { SettingsPage } from './pages/tenant/SettingsPage'; function LandingRedirect() { const scopes = useScopes(); const { organizations, currentOrgId } = useOrgStore(); const currentOrg = organizations.find((o) => o.id === currentOrgId); // Wait for scopes to be resolved — they're loaded async by OrgResolver. // An empty set means "not yet loaded" (even viewer gets observe:read). if (scopes.size === 0) { return null; // OrgResolver is still fetching tokens } // Vendor → vendor console if (scopes.has('platform:admin')) { return ; } // Tenant admin → tenant portal if (scopes.has('tenant:manage')) { return ; } // Regular user (operator/viewer) → server dashboard directly const serverUrl = currentOrg?.slug ? `/t/${currentOrg.slug}/` : '/server/'; window.location.href = serverUrl; return null; } export function AppRouter() { return ( } /> } /> }> }> }> {/* Vendor console */} }> } /> }> } /> }> } /> {/* Tenant portal */} } /> } /> } /> } /> } /> {/* Default redirect — vendor goes to /vendor/tenants, customer to /tenant */} } /> ); }