148 lines
5 KiB
TypeScript
148 lines
5 KiB
TypeScript
|
|
import React from 'react';
|
||
|
|
import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from 'react-router-dom';
|
||
|
|
import TopBar from './layouts/TopBar';
|
||
|
|
import Dashboard from './pages/Dashboard';
|
||
|
|
import Sourcing from './pages/Sourcing';
|
||
|
|
import Orders from './pages/Orders';
|
||
|
|
import Inventory from './pages/Inventory';
|
||
|
|
import Financial from './pages/Financial';
|
||
|
|
import Customers from './pages/Customers';
|
||
|
|
import Sales from './pages/Sales';
|
||
|
|
import Suppliers from './pages/Suppliers';
|
||
|
|
import Users from './pages/Users';
|
||
|
|
import Login from './pages/Login';
|
||
|
|
import Products from './pages/Products'; // New
|
||
|
|
import Reports from './pages/Reports';
|
||
|
|
import Settings from './pages/Settings';
|
||
|
|
import { CRMProvider, useCRM } from './context/CRMContext';
|
||
|
|
|
||
|
|
import Sidebar from './layouts/Sidebar';
|
||
|
|
import Header from './layouts/Header';
|
||
|
|
import { useTheme } from './context/ThemeContext';
|
||
|
|
|
||
|
|
// Simple Layout Wrapper to handle Sidebar/Header display
|
||
|
|
const AppLayout: React.FC = () => {
|
||
|
|
const location = useLocation();
|
||
|
|
const { session, authLoading } = useCRM();
|
||
|
|
const { theme } = useTheme();
|
||
|
|
const isLoginPage = location.pathname === '/login';
|
||
|
|
|
||
|
|
if (authLoading) {
|
||
|
|
return (
|
||
|
|
<div className="h-screen w-full flex items-center justify-center bg-background text-foreground">
|
||
|
|
<div className="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-primary"></div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!session && !isLoginPage) {
|
||
|
|
return <Navigate to="/login" replace />;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (session && isLoginPage) {
|
||
|
|
return <Navigate to="/" replace />;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isLoginPage) {
|
||
|
|
return (
|
||
|
|
<div className="flex bg-background text-foreground h-screen w-screen relative overflow-hidden">
|
||
|
|
<Routes>
|
||
|
|
<Route path="/login" element={<Login />} />
|
||
|
|
</Routes>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// LAYOUT STRATEGIES
|
||
|
|
|
||
|
|
// 1. SIMPLE / CLEAN (Light) -> Uses TopBar (ERP Style)
|
||
|
|
if (theme === 'light') {
|
||
|
|
return (
|
||
|
|
<div className="min-h-screen bg-background flex flex-col font-sans antialiased text-foreground overflow-x-hidden selection:bg-primary selection:text-primary-foreground">
|
||
|
|
<TopBar />
|
||
|
|
<main className="flex-grow flex flex-col pt-4">
|
||
|
|
<div className="w-full max-w-[1600px] mx-auto p-4 md:p-8 flex-grow space-y-4">
|
||
|
|
<AppRoutes />
|
||
|
|
</div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 2. OCEAN / COMPLEX -> Uses Compact Sidebar (To be refined) or Modified TopBar
|
||
|
|
if (theme === 'ocean') {
|
||
|
|
return (
|
||
|
|
<div className="flex h-screen bg-background text-foreground font-sans antialiased selection:bg-cyan-500/30 selection:text-cyan-200 overflow-hidden">
|
||
|
|
{/* Sidebar for Ocean */}
|
||
|
|
<Sidebar />
|
||
|
|
|
||
|
|
<div className="flex-1 flex flex-col min-w-0 overflow-hidden">
|
||
|
|
<Header />
|
||
|
|
<main className="flex-1 overflow-y-auto p-4 md:p-6 scroll-smooth">
|
||
|
|
<div className="max-w-[1800px] mx-auto space-y-6 pb-20">
|
||
|
|
<AppRoutes />
|
||
|
|
</div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 3. DARK / PRO (Default) -> Sidebar + Header (Glassmorphism)
|
||
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="flex h-screen bg-background text-foreground font-sans antialiased selection:bg-indigo-500/30 selection:text-indigo-200 overflow-hidden">
|
||
|
|
<Sidebar isOpen={isMobileMenuOpen} onClose={() => setIsMobileMenuOpen(false)} />
|
||
|
|
<div className="flex-1 flex flex-col min-w-0 overflow-hidden relative">
|
||
|
|
{/* Background Blob Effect for Pro Theme */}
|
||
|
|
<div className="absolute top-[-20%] left-[-10%] w-[500px] h-[500px] bg-indigo-600/20 rounded-full blur-[120px] pointer-events-none"></div>
|
||
|
|
|
||
|
|
<Header onMenuClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} />
|
||
|
|
<main className="flex-1 overflow-y-auto p-4 md:p-8 scroll-smooth z-10">
|
||
|
|
<AppRoutes />
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
// Extracted Routes to avoid duplication
|
||
|
|
const AppRoutes = () => (
|
||
|
|
<Routes>
|
||
|
|
<Route path="/" element={<Dashboard />} />
|
||
|
|
<Route path="/sourcing" element={<Sourcing />} />
|
||
|
|
<Route path="/orders" element={<Orders />} />
|
||
|
|
<Route path="/sales" element={<Sales />} />
|
||
|
|
<Route path="/products" element={<Products />} />
|
||
|
|
<Route path="/reports" element={<Reports />} />
|
||
|
|
<Route path="/settings" element={<Settings />} />
|
||
|
|
<Route path="/financial" element={<Financial />} />
|
||
|
|
<Route path="/customers" element={<Customers />} />
|
||
|
|
<Route path="/inventory" element={<Inventory />} />
|
||
|
|
<Route path="/suppliers" element={<Suppliers />} />
|
||
|
|
<Route path="/users" element={<Users />} />
|
||
|
|
<Route path="*" element={<Navigate to="/" replace />} />
|
||
|
|
</Routes>
|
||
|
|
);
|
||
|
|
|
||
|
|
import ErrorBoundary from './components/ErrorBoundary';
|
||
|
|
import { ThemeProvider } from './context/ThemeContext';
|
||
|
|
|
||
|
|
const App: React.FC = () => {
|
||
|
|
return (
|
||
|
|
<ErrorBoundary>
|
||
|
|
<ThemeProvider>
|
||
|
|
<CRMProvider>
|
||
|
|
{/* Main Router Setup */}
|
||
|
|
<Router>
|
||
|
|
<AppLayout />
|
||
|
|
</Router>
|
||
|
|
</CRMProvider>
|
||
|
|
</ThemeProvider>
|
||
|
|
</ErrorBoundary>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default App;
|