2026-06-11 19:56:20 +05:30

151 lines
9.3 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { bootstrapFrappeUserFromSession } from './utils/bootstrapFrappeUserFromSession';
import Login from './pages/Login';
import Sidebar from './components/Sidebar';
import Header from './components/Header';
import UserProfilePage from './pages/UserProfilePage';
import ProjectModulePage from './pages/ProjectModulePage';
import ProjectReportsDashboard from './pages/ProjectReportsDashboard';
import ProjectList from './pages/ProjectList';
import ProjectDetail from './pages/ProjectDetail';
import TaskList from './pages/TaskList';
import TaskDetail from './pages/TaskDetail';
import TimesheetList from './pages/TimesheetList';
import TimesheetDetail from './pages/TimesheetDetail';
import ActivityTypeList from './pages/ActivityTypeList';
import ActivityTypeDetail from './pages/ActivityTypeDetail';
import ProjectTemplateList from './pages/ProjectTemplateList';
import ProjectTemplateDetail from './pages/ProjectTemplateDetail';
import CustomerList from './pages/CustomerList';
import CustomerDetail from './pages/CustomerDetail';
import EmployeeList from './pages/EmployeeList';
import EmployeeDetail from './pages/EmployeeDetail';
import SalesInvoiceList from './pages/SalesInvoiceList';
import SalesInvoiceDetail from './pages/SalesInvoiceDetail';
import SalesOrderList from './pages/SalesOrderList';
import SalesOrderDetail from './pages/SalesOrderDetail';
import PurchaseOrderList from './pages/PurchaseOrderList';
import PurchaseOrderDetail from './pages/PurchaseOrderDetail';
import DeliveryNoteList from './pages/DeliveryNoteList';
import DeliveryNoteDetail from './pages/DeliveryNoteDetail';
import MaterialRequestList from './pages/MaterialRequestList';
import MaterialRequestDetail from './pages/MaterialRequestDetail';
import PurchaseReceiptList from './pages/PurchaseReceiptList';
import PurchaseReceiptDetail from './pages/PurchaseReceiptDetail';
import PaymentEntryList from './pages/PaymentEntryList';
import PaymentEntryDetail from './pages/PaymentEntryDetail';
import { SidebarLayoutProvider } from './contexts/SidebarLayoutContext';
const LayoutWithSidebar: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const user = localStorage.getItem('user');
const userEmail = user ? JSON.parse(user).email : '';
return (
<SidebarLayoutProvider>
<div className="flex h-screen overflow-hidden bg-gray-50 dark:bg-gray-900">
<Sidebar userEmail={userEmail} />
<div className="pm-app-main flex min-w-0 flex-1 flex-col overflow-hidden">
<Header userEmail={userEmail} />
<div className="flex-1 overflow-y-auto bg-gray-50 dark:bg-gray-900">{children}</div>
</div>
</div>
</SidebarLayoutProvider>
);
};
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [status, setStatus] = useState<'loading' | 'authed' | 'guest'>('loading');
useEffect(() => {
let cancelled = false;
(async () => {
if (localStorage.getItem('user')) {
if (!cancelled) setStatus('authed');
return;
}
const result = await bootstrapFrappeUserFromSession();
if (!cancelled) setStatus(result.ok ? 'authed' : 'guest');
})();
return () => {
cancelled = true;
};
}, []);
if (status === 'loading') {
return (
<div className="flex h-screen items-center justify-center bg-gray-50 dark:bg-gray-900">
<div className="flex flex-col items-center gap-3 text-gray-600 dark:text-gray-400">
<svg
className="h-10 w-10 animate-spin text-indigo-600"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
aria-hidden
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<span className="text-sm">Loading</span>
</div>
</div>
);
}
if (status === 'guest') {
return <Navigate to="/login" replace />;
}
return <>{children}</>;
};
const App: React.FC = () => (
<Router basename="/project_management">
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/user-profile" element={<ProtectedRoute><LayoutWithSidebar><UserProfilePage /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects" element={<ProtectedRoute><LayoutWithSidebar><ProjectModulePage /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/reports" element={<ProtectedRoute><LayoutWithSidebar><ProjectReportsDashboard /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/project-updates" element={<Navigate to="/projects" replace />} />
<Route path="/projects/project-updates/:updateName" element={<Navigate to="/projects" replace />} />
<Route path="/projects/list" element={<ProtectedRoute><LayoutWithSidebar><ProjectList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/list/:projectName" element={<ProtectedRoute><LayoutWithSidebar><ProjectDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/tasks" element={<ProtectedRoute><LayoutWithSidebar><TaskList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/tasks/:taskName" element={<ProtectedRoute><LayoutWithSidebar><TaskDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/timesheets" element={<ProtectedRoute><LayoutWithSidebar><TimesheetList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/timesheets/:timesheetName" element={<ProtectedRoute><LayoutWithSidebar><TimesheetDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/activity-types" element={<ProtectedRoute><LayoutWithSidebar><ActivityTypeList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/activity-types/:activityTypeName" element={<ProtectedRoute><LayoutWithSidebar><ActivityTypeDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/templates" element={<ProtectedRoute><LayoutWithSidebar><ProjectTemplateList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/projects/templates/:templateName" element={<ProtectedRoute><LayoutWithSidebar><ProjectTemplateDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/customers" element={<ProtectedRoute><LayoutWithSidebar><CustomerList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/customers/:customerName" element={<ProtectedRoute><LayoutWithSidebar><CustomerDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/employees" element={<ProtectedRoute><LayoutWithSidebar><EmployeeList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/employees/:employeeName" element={<ProtectedRoute><LayoutWithSidebar><EmployeeDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/invoices" element={<ProtectedRoute><LayoutWithSidebar><SalesInvoiceList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/invoices/:invoiceName" element={<ProtectedRoute><LayoutWithSidebar><SalesInvoiceDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/sales-orders" element={<ProtectedRoute><LayoutWithSidebar><SalesOrderList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/sales-orders/:soName" element={<ProtectedRoute><LayoutWithSidebar><SalesOrderDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/purchase-orders" element={<ProtectedRoute><LayoutWithSidebar><PurchaseOrderList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/purchase-orders/:poName" element={<ProtectedRoute><LayoutWithSidebar><PurchaseOrderDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/delivery-notes" element={<ProtectedRoute><LayoutWithSidebar><DeliveryNoteList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/delivery-notes/:dnName" element={<ProtectedRoute><LayoutWithSidebar><DeliveryNoteDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/material-requests" element={<ProtectedRoute><LayoutWithSidebar><MaterialRequestList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/material-requests/:mrName" element={<ProtectedRoute><LayoutWithSidebar><MaterialRequestDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/purchase-receipts" element={<ProtectedRoute><LayoutWithSidebar><PurchaseReceiptList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/purchase-receipts/:prName" element={<ProtectedRoute><LayoutWithSidebar><PurchaseReceiptDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/payment-entries" element={<ProtectedRoute><LayoutWithSidebar><PaymentEntryList /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/payment-entries/:peName" element={<ProtectedRoute><LayoutWithSidebar><PaymentEntryDetail /></LayoutWithSidebar></ProtectedRoute>} />
<Route path="/" element={<Navigate to="/projects" replace />} />
<Route path="*" element={<Navigate to="/projects" replace />} />
</Routes>
</Router>
);
export default App;