diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index fc3f2d7..12de8d1 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,18 +1,64 @@
-import { BrowserRouter } from 'react-router-dom';
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { App as AntApp } from 'antd';
+import { Suspense, lazy } from 'react';
+import { Spin } from 'antd';
import AppRoutes from './routes';
import AppLayout from './components/layout/AppLayout';
import ProtectedRoute from './components/auth/ProtectedRoute';
+import CompanyGuard from './components/auth/CompanyGuard';
+
+// Lazy load CompanySetupWizard
+const CompanySetupWizard = lazy(() => import('./pages/CompanySetupWizard'));
+
+// Loading fallback component
+function PageLoader() {
+ return (
+
+
+
+ );
+}
function App() {
return (
-
-
-
-
-
+
+ {/* Wizard route OUTSIDE CompanyGuard to prevent navigation loop */}
+
+ }>
+
+
+
+ }
+ />
+
+ {/* All other routes with full guard chain */}
+
+
+
+
+
+
+
+ }
+ />
+
);
diff --git a/frontend/src/components/auth/CompanyGuard.tsx b/frontend/src/components/auth/CompanyGuard.tsx
index c5f1e29..78372e9 100644
--- a/frontend/src/components/auth/CompanyGuard.tsx
+++ b/frontend/src/components/auth/CompanyGuard.tsx
@@ -1,4 +1,4 @@
-import { ReactNode, useEffect } from 'react';
+import { ReactNode, useEffect, useRef } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { Spin, Typography } from 'antd';
import { useMyCompanies } from '@/api/queries/companyQueries';
@@ -17,7 +17,8 @@ interface CompanyGuardProps {
export default function CompanyGuard({ children }: CompanyGuardProps) {
const navigate = useNavigate();
const location = useLocation();
- const { setCompanies, setActiveCompany, activeCompany } = useCompanyStore();
+ const { setCompanies, setActiveCompany } = useCompanyStore();
+ const hasNavigatedRef = useRef(false);
const {
data: companies,
@@ -27,6 +28,8 @@ export default function CompanyGuard({ children }: CompanyGuardProps) {
} = useMyCompanies({
staleTime: 5 * 60 * 1000,
refetchOnMount: true,
+ retry: 1,
+ refetchOnWindowFocus: false,
});
// Sync companies to store when loaded
@@ -34,32 +37,46 @@ export default function CompanyGuard({ children }: CompanyGuardProps) {
if (companies && companies.length > 0) {
setCompanies(companies);
+ // Get current value without adding to dependencies to avoid infinite loop
+ const current = useCompanyStore.getState().activeCompany;
+
// Validate that activeCompany exists in API response
- const validCompany = activeCompany
- ? companies.find((c) => c.id === activeCompany.id)
+ const validCompany = current
+ ? companies.find((c) => c.id === current.id)
: null;
if (!validCompany) {
// Persisted company doesn't exist - set to first
setActiveCompany(companies[0]);
- } else if (JSON.stringify(validCompany) !== JSON.stringify(activeCompany)) {
+ } else if (JSON.stringify(validCompany) !== JSON.stringify(current)) {
// Update with fresh data from API
setActiveCompany(validCompany);
}
}
- }, [companies, activeCompany, setCompanies, setActiveCompany]);
+ }, [companies, setCompanies, setActiveCompany]);
// Redirect to wizard if no companies and not already on wizard page
useEffect(() => {
+ // Guard against multiple navigations to prevent infinite loop
+ if (hasNavigatedRef.current) return;
+
if (!isLoading && companies !== undefined) {
const isOnWizard = location.pathname === '/opret-virksomhed';
if (companies.length === 0 && !isOnWizard) {
+ hasNavigatedRef.current = true;
navigate('/opret-virksomhed', { replace: true });
}
// Note: Users with existing companies CAN access the wizard to create more
}
- }, [companies, isLoading, location.pathname, navigate]);
+ }, [companies, isLoading, navigate, location.pathname]);
+
+ // Reset navigation ref when companies change (user created a company)
+ useEffect(() => {
+ if (companies && companies.length > 0) {
+ hasNavigatedRef.current = false;
+ }
+ }, [companies]);
// Show loading state
if (isLoading) {
diff --git a/frontend/src/routes.tsx b/frontend/src/routes.tsx
index 0d1117d..5341654 100644
--- a/frontend/src/routes.tsx
+++ b/frontend/src/routes.tsx
@@ -13,6 +13,7 @@ const Eksport = lazy(() => import('./pages/Eksport'));
const Settings = lazy(() => import('./pages/Settings'));
const UserSettings = lazy(() => import('./pages/UserSettings'));
const Admin = lazy(() => import('./pages/Admin'));
+// CompanySetupWizard moved to App.tsx (outside CompanyGuard)
// Invoicing pages
const Kunder = lazy(() => import('./pages/Kunder'));
@@ -73,6 +74,8 @@ export default function AppRoutes() {
{/* Admin */}
} />
+ {/* Company setup wizard is now in App.tsx (outside CompanyGuard) */}
+
{/* Fallback redirect */}
} />