import { lazy, Suspense } from "react"; import { Navigate, Route, Routes, useLocation } from "react-router-dom"; import { useAuthStore } from "./store/auth"; import { ErrorBoundary } from "./components/ErrorBoundary"; import { RequirePmProjects } from "./components/RequirePmProjects"; import { MobileTabBar } from "./components/layout/MobileTabBar"; // هر صفحه با React.lazy لود می‌شود (code splitting) const DashboardPage = lazy(() => import("./pages/Dashboard/DashboardPage").then((m) => ({ default: m.DashboardPage })), ); const WizardPage = lazy(() => import("./pages/Wizard/WizardPage").then((m) => ({ default: m.WizardPage }))); const SuppliersPage = lazy(() => import("./pages/Suppliers/SuppliersPage").then((m) => ({ default: m.SuppliersPage })), ); const CategoryPage = lazy(() => import("./pages/Suppliers/CategoryPage").then((m) => ({ default: m.CategoryPage })), ); const SupplierDetailPage = lazy(() => import("./pages/Suppliers/SupplierDetailPage").then((m) => ({ default: m.SupplierDetailPage })), ); const ProjectsPage = lazy(() => import("./pages/Projects/ProjectsPage").then((m) => ({ default: m.ProjectsPage })), ); const UnitsPage = lazy(() => import("./pages/Units/UnitsPage").then((m) => ({ default: m.UnitsPage }))); const LoginPage = lazy(() => import("./pages/Auth/LoginPage").then((m) => ({ default: m.LoginPage }))); const InventoryPage = lazy(() => import("./pages/Inventory/InventoryPage").then((m) => ({ default: m.InventoryPage })), ); const ArrivalsPage = lazy(() => import("./pages/Inventory/ArrivalsPage").then((m) => ({ default: m.ArrivalsPage }))); const ChangeInventoryPage = lazy(() => import("./pages/Inventory/ChangeInventoryPage").then((m) => ({ default: m.ChangeInventoryPage })), ); const DailyControlPage = lazy(() => import("./pages/Inventory/DailyControlPage").then((m) => ({ default: m.DailyControlPage })), ); const WarehousesPage = lazy(() => import("./pages/Inventory/WarehousesPage").then((m) => ({ default: m.WarehousesPage })), ); const OrganizationPage = lazy(() => import("./pages/Organization/OrganizationPage").then((m) => ({ default: m.OrganizationPage })), ); const AdminPanelPage = lazy(() => import("./pages/Admin/AdminPanel").then((m) => ({ default: m.AdminPanel })), ); const RequesterHome = lazy(() => import("./pages/Dashboard/RequesterHome").then((m) => ({ default: m.RequesterHome })), ); // داشبورد تحلیلی MVP (انبار + بازرگانی) — ویجت‌های Power-BI-style const MvpDashboardPage = lazy(() => import("./pages/Dashboard/MvpDashboardPage").then((m) => ({ default: m.MvpDashboardPage })), ); function Loading() { return (
در حال بارگذاری...
); } // همه‌ی صفحات پشت ورود هستند — به جز پیش‌نویس‌های ویزارد از ربات یا بدون نشست که به صفحه‌ی ورود می‌روند. function RequireAuth({ children }: { children: React.ReactNode }) { const user = useAuthStore((s) => s.user); const location = useLocation(); const pathname = location.pathname; // در صورت داشتن شناسه پیش‌نویس (از ربات بله)، دسترسی مستقیم به ویزارد بدون لاگین مجاز است const searchParams = new URLSearchParams(location.search); const hasDraft = searchParams.has("draft") || searchParams.has("draft_id"); if (location.pathname === "/wizard" && hasDraft) { return <>{children}; } if (!user) { const returnUrl = encodeURIComponent(location.pathname + location.search); return ; } if (user.role === "supervisor") { // اگر سرپرست پروژه‌ای نداشته باشد، دسترسی مسدود می‌شود const hasProjects = (Boolean(user.projects && user.projects.length > 0)) || (Boolean(user.member_project_ids && user.member_project_ids.length > 0)); if (!hasProjects) { return (

پروژه تخصیص داده نشده است

شما به عنوان سرپرست پروژه در سیستم ثبت شدهاید اما هنوز هیچ پروژه‌ای به شما تخصیص داده نشده است. تا زمان تخصیص پروژه توسط مدیر سیستم، اجازه ورود به سامانه را ندارید.

); } } // بررسی دسترسی به مسیرها بر اساس ترکیب نقش سازمانی و پنل‌های تخصیصی: const panels = user.panels ?? {}; const isAdmin = user.role === "admin"; const hasPanelsConfig = Boolean(user.panels && Object.keys(user.panels).length > 0); const hasProcurement = isAdmin || (hasPanelsConfig ? Boolean(panels.procurement) : user.role === "procurement_manager"); const hasInventory = isAdmin || (hasPanelsConfig ? Boolean(panels.inventory) : user.role === "pm" || user.role === "supervisor"); const hasPm = isAdmin || (hasPanelsConfig ? Boolean(panels.pm) : user.role === "pm" || user.role === "supervisor"); const isProcurementRoute = pathname === "/" || pathname.startsWith("/wizard") || pathname.startsWith("/suppliers") || pathname.startsWith("/projects") || pathname.startsWith("/units") || pathname.startsWith("/requester"); if (isProcurementRoute && !hasProcurement) { if (hasInventory) return ; if (hasPm) return ; return ; } if (pathname.startsWith("/inventory") && !hasInventory) { if (hasProcurement) return ; if (hasPm) return ; return ; } return <>{children}; } // صفحه‌ی اصلی بر اساس لایه پنل‌ها (جایگزین نقش‌ها): function HomeRoute() { const user = useAuthStore((s) => s.user); const panels = user?.panels ?? {}; const isAdmin = user?.role === "admin"; const hasPanelsConfig = Boolean(user?.panels && Object.keys(user.panels).length > 0); const hasProcurement = isAdmin || (hasPanelsConfig ? Boolean(panels.procurement) : user?.role === "procurement_manager"); const hasInventory = isAdmin || (hasPanelsConfig ? Boolean(panels.inventory) : user?.role === "pm" || user?.role === "supervisor"); const hasPm = isAdmin || (hasPanelsConfig ? Boolean(panels.pm) : user?.role === "pm" || user?.role === "supervisor"); // ۱. اگر پنل تدارکات دارد: if (hasProcurement) { if (panels.procurement === "limited" && !isAdmin) { return ; } return ; } // ۲. اگر پنل انبار دارد: if (hasInventory) return ; // ۳. اگر پنل PM دارد: if (hasPm) return ; // در صورتی که کاربر به هیچ پنلی دسترسی ندارد: return (

عدم دسترسی به پنل‌های سامانه

حساب کاربری شما فعال است اما در حال حاضر به هیچ‌یک از پنل‌های سامانه دسترسی ندارد. لطفاً با مدیر سیستم تماس بگیرید.

); } // دسترسی ایجاد استعلام/پیشنهاد (ویزارد): ادمین، نقش‌های تدارکات و پنل‌های تدارکات (full یا limited) function RequireProcurementWrite({ children }: { children: React.ReactNode }) { const user = useAuthStore((s) => s.user); const panels = user?.panels ?? {}; const isAdmin = user?.role === "admin"; const hasPanelsConfig = Boolean(user?.panels && Object.keys(user.panels).length > 0); const hasProcurement = isAdmin || (hasPanelsConfig ? Boolean(panels.procurement) : user?.role === "procurement_manager" || user?.role === "pm"); if (hasProcurement) { return <>{children}; } const hasInventory = isAdmin || (hasPanelsConfig ? Boolean(panels.inventory) : user?.role === "pm" || user?.role === "supervisor"); if (hasInventory) return ; const hasPm = isAdmin || (hasPanelsConfig ? Boolean(panels.pm) : user?.role === "pm" || user?.role === "supervisor"); if (hasPm) return ; return ; } // پنل «مدیریت پروژه (PM)» — اپ PM روی همان دامنه زیر مسیر /pm سرو می‌شود function PmPanelPage() { return (