import { lazy, Suspense, useCallback, useEffect, useState } from 'react' import { BrowserRouter, Routes, Route, Navigate, Link, useLocation } from 'react-router-dom' import { AuthProvider, useAuth } from './context/AuthContext' import Sidebar from './components/Navbar' import Logo from './components/Logo' import LoginPage from './pages/LoginPage' import TicketsPage from './pages/TicketsPage' import TicketPage from './pages/TicketPage' import PlanboardPage from './pages/PlanboardPage' import ProjectsPage from './pages/ProjectsPage' import AdminPage from './pages/AdminPage' import CustomersPage from './pages/CustomersPage' import CustomerDetailPage from './pages/CustomerDetailPage' import CustomerChatPage from './pages/CustomerChatPage' import StorageTasksPage from './pages/StorageTasksPage' import CreditsPage from './pages/CreditsPage' import OffersPage from './pages/OffersPage' import FinancePage from './pages/FinancePage' import FinanceSettingsPage from './pages/FinanceSettingsPage' import LegalPage from './pages/LegalPage' import AssignProjectPage from './pages/AssignProjectPage' import ServicesPage from './pages/ServicesPage' import ServerpulsPage from './pages/ServerpulsPage' import BankCallbackPage from './pages/BankCallbackPage' import AdminRoute from './components/AdminRoute' import RouteErrorBoundary from './components/RouteErrorBoundary' import { safeReturnPath } from './lib/returnPath' // Hochhaus der Hustler: erst beim Öffnen laden, damit Engine und Schrift nicht im Haupt-Bundle liegen const WorkersPage = lazy(() => import('./pages/WorkersPage')) function ProtectedRoute({ children }) { const { user, loading } = useAuth() const location = useLocation() if (loading) { return
Wird geladen …
} if (!user) { return } return children } // Alte Adressen /leads und /workers führen auf /hustler, die Query bleibt (/workers?tab=botleads&bot= wird /hustler?tab=botleads&bot=) function HustlerRedirect() { const { search } = useLocation() return } function AppRoutes() { const { user } = useAuth() const location = useLocation() return ( : } /> } /> } /> } /> } /> {/* Messenger (Kunden -> Chat); statische Pfade gehen in react-router vor /customers/:id */} } /> } /> } /> } /> } /> Wird geladen …}>} /> } /> } /> {/* Finanzen: nur Admins, alle anderen gehen zu /tickets */} } /> } /> } /> } /> } /> } /> } /> } /> } /> } /> {/* Alte Links (z. B. die entfernten Seiten Assets, Reports, Docs, Roadmaps) landen bei den Tickets */} } /> ) } function AppContent() { const { user } = useAuth() const location = useLocation() // Schublade des Menues auf dem Handy; auf dem Desktop steht das Menue fest und menuOpen bleibt ohne Wirkung const [menuOpen, setMenuOpen] = useState(false) const open = useCallback(() => setMenuOpen(true), []) const close = useCallback(() => setMenuOpen(false), []) // Seitenwechsel (nur der Pfad, nicht ?woid= oder ?tab=): Schublade zu und wieder nach oben useEffect(() => { setMenuOpen(false) window.scrollTo(0, 0) }, [location.pathname]) // Esc schliesst die Schublade, nur solange sie offen ist und nur, wenn kein anderer Baustein die Taste schon behandelt hat useEffect(() => { if (!menuOpen) return undefined const onKey = (e) => { if (e.defaultPrevented) return if (e.key === 'Escape') setMenuOpen(false) } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [menuOpen]) if (!user) { return } return (
WEBklar
{/* Fängt u. a. einen fehlenden lazy-Chunk ab (alter Tab nach einem Deploy): Menü bleibt, Knopf lädt neu */}
) } export default function App() { return ( ) }