360 lines
12 KiB
React
360 lines
12 KiB
React
import React from 'react';
|
|
import { Routes, Route, Navigate, useLocation } from 'react-router-dom';
|
|
import { useAuth } from './context/AuthContext';
|
|
import Layout from './components/Layout';
|
|
import Login from './pages/Login';
|
|
import Landing from './pages/Landing';
|
|
import Dashboard from './pages/Dashboard';
|
|
import Maps from './pages/Maps';
|
|
import AdminSchedule from './pages/AdminSchedule';
|
|
import CustomerProfile from './pages/CustomerProfile';
|
|
import LeaderboardPage from './pages/LeaderboardPage';
|
|
import ErrorBoundary from './components/ErrorBoundary';
|
|
import SmoothScroll from './components/SmoothScroll';
|
|
import { Toaster } from 'sonner';
|
|
import NotFound from './pages/NotFound';
|
|
import OwnerSnapshot from './pages/owner/OwnerSnapshot';
|
|
import PeopleDirectory from './pages/owner/PeopleDirectory';
|
|
import VendorDirectory from './pages/owner/VendorDirectory';
|
|
import DocumentManagement from './pages/owner/DocumentManagement';
|
|
import OwnerProjectList from './pages/owner/OwnerProjectList';
|
|
import OwnerProjectDetail from './pages/owner/OwnerProjectDetail';
|
|
import OrgSettings from './pages/owner/OrgSettings';
|
|
import PlaceholderDashboard from './pages/PlaceholderDashboard';
|
|
import ProCanvas from './pages/ProCanvas';
|
|
import ProjectList from './pages/contractor/ProjectList';
|
|
import AiAssistantPage from './pages/AiAssistantPage';
|
|
import EstimateBuilder from './pages/EstimateBuilder';
|
|
// New Dashboards
|
|
import VendorDashboard from './pages/vendor/VendorDashboard';
|
|
import VendorOrders from './pages/vendor/VendorOrders';
|
|
import ContractorDashboard from './pages/contractor/ContractorDashboard';
|
|
import SubContractorDashboard from './pages/subcontractor/SubContractorDashboard';
|
|
import CreateLeadPage from './pages/CreateLeadPage';
|
|
import LeadsListPage from './pages/LeadsListPage';
|
|
import LynkDispatchPage from './pages/LynkDispatchPage';
|
|
import EstimatesPage from './pages/EstimatesPage';
|
|
import KanbanPage from './pages/KanbanPage';
|
|
import LeadProjectPage from './pages/LeadProjectPage';
|
|
|
|
// ... (existing imports)
|
|
const ProtectedRoute = ({ children, allowedRoles }) => {
|
|
const { user, isAuthenticated } = useAuth();
|
|
const location = useLocation();
|
|
|
|
if (!isAuthenticated) {
|
|
return <Navigate to="/login" state={{ from: location }} replace />;
|
|
}
|
|
|
|
if (allowedRoles && !allowedRoles.includes(user.role)) {
|
|
// If user is employee but wrong role, go to their default dashboard
|
|
// For now, just redirect to home or show unauthorized
|
|
return <Navigate to="/" replace />;
|
|
}
|
|
|
|
return children;
|
|
};
|
|
|
|
function App() {
|
|
return (
|
|
<ErrorBoundary>
|
|
<Toaster position="top-right" richColors closeButton expand={true} />
|
|
<SmoothScroll>
|
|
<Routes>
|
|
<Route element={<Layout />}>
|
|
{/* Public Routes */}
|
|
<Route path="/" element={<Landing />} />
|
|
<Route path="/login" element={<Login />} />
|
|
<Route
|
|
path="/chat-assistant"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['OWNER', 'ADMIN', 'FIELD_AGENT', 'CONTRACTOR', 'SUBCONTRACTOR', 'CUSTOMER']}>
|
|
<AiAssistantPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
{/* Protected Field Agent Routes */}
|
|
<Route path="/portal/profile" element={
|
|
<ProtectedRoute allowedRoles={['CUSTOMER']}>
|
|
<CustomerProfile />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
<Route
|
|
path="/emp/fa/dashboard"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<Dashboard />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/maps"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<Maps />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/pro-canvas"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<ProCanvas />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/estimates"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<EstimatesPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/kanban"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<KanbanPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/leads/:leadId"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<LeadProjectPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/estimate"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<EstimateBuilder />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/leads"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<LeadsListPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/emp/fa/leads/new"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['FIELD_AGENT', 'ADMIN', 'OWNER']}>
|
|
<CreateLeadPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
{/* Owner Routes */}
|
|
<Route path="/owner/snapshot" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<OwnerSnapshot />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/people" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<PeopleDirectory />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/vendors" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<VendorDirectory />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/documents" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<DocumentManagement />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/projects" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<OwnerProjectList />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/projects/:projectId" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<OwnerProjectDetail />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/maps" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<Maps />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/pro-canvas" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<ProCanvas />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/estimates" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<EstimatesPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/kanban" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<KanbanPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/leads/:leadId" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<LeadProjectPage />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/estimate" element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<EstimateBuilder />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/owner/settings" element={
|
|
<ProtectedRoute allowedRoles={['OWNER','ADMIN']}>
|
|
<OrgSettings />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
{/* Protected Admin Routes — Owner has full admin access */}
|
|
<Route
|
|
path="/admin/dashboard"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<Dashboard />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/schedule"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<AdminSchedule />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/admin/leaderboard"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<LeaderboardPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/dispatch"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<LynkDispatchPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/owner/dispatch"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['OWNER']}>
|
|
<LynkDispatchPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/maps"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<Maps />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/pro-canvas"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<ProCanvas />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/estimates"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<EstimatesPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/kanban"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<KanbanPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/leads/:leadId"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<LeadProjectPage />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/admin/estimate"
|
|
element={
|
|
<ProtectedRoute allowedRoles={['ADMIN', 'OWNER']}>
|
|
<EstimateBuilder />
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
{/* Contractor Routes */}
|
|
<Route path="/contractor/dashboard" element={
|
|
<ProtectedRoute allowedRoles={['CONTRACTOR']}>
|
|
<ContractorDashboard />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/contractor/projects" element={
|
|
<ProtectedRoute allowedRoles={['CONTRACTOR']}>
|
|
<ProjectList />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
{/* Vendor Routes */}
|
|
<Route path="/vendor/dashboard" element={
|
|
<ProtectedRoute allowedRoles={['VENDOR']}>
|
|
<VendorDashboard />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/vendor/orders" element={
|
|
<ProtectedRoute allowedRoles={['VENDOR']}>
|
|
<VendorOrders />
|
|
</ProtectedRoute>
|
|
} />
|
|
|
|
{/* Subcontractor Routes */}
|
|
<Route path="/subcontractor/dashboard" element={
|
|
<ProtectedRoute allowedRoles={['SUBCONTRACTOR']}>
|
|
<SubContractorDashboard />
|
|
</ProtectedRoute>
|
|
} />
|
|
<Route path="/subcontractor/projects" element={
|
|
<ProtectedRoute allowedRoles={['SUBCONTRACTOR']}>
|
|
<ProjectList />
|
|
</ProtectedRoute>
|
|
} />
|
|
</Route>
|
|
|
|
{/* Catch all */}
|
|
<Route path="*" element={<NotFound />} />
|
|
</Routes>
|
|
</SmoothScroll>
|
|
</ErrorBoundary >
|
|
);
|
|
}
|
|
|
|
export default App;
|