feat(org,rbac): dedicate organization panel, enforce role permissions, subheader info, and fix supervisor project sync
This commit is contained in:
+76
-17
@@ -38,7 +38,7 @@ const WarehousesPage = lazy(() =>
|
||||
import("./pages/Inventory/WarehousesPage").then((m) => ({ default: m.WarehousesPage })),
|
||||
);
|
||||
const OrganizationPage = lazy(() =>
|
||||
import("./pages/Inventory/OrganizationPage").then((m) => ({ default: m.OrganizationPage })),
|
||||
import("./pages/Organization/OrganizationPage").then((m) => ({ default: m.OrganizationPage })),
|
||||
);
|
||||
const AdminPanelPage = lazy(() =>
|
||||
import("./pages/Admin/AdminPanel").then((m) => ({ default: m.AdminPanel })),
|
||||
@@ -53,35 +53,60 @@ function Loading() {
|
||||
}
|
||||
|
||||
// همهی صفحات پشت ورود هستند — بدون نشست، به صفحهی ورود میرویم.
|
||||
// سرپرست پروژه (فقطِ پنل PM) از هر مسیری به پنل PM هدایت میشود.
|
||||
function RequireAuth({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const { pathname } = useLocation();
|
||||
if (!user) return <Navigate to="/login" replace />;
|
||||
if (user.role === "supervisor" && pathname !== "/panel/pm") {
|
||||
return <Navigate to="/panel/pm" replace />;
|
||||
if (user.role === "supervisor") {
|
||||
// اگر سرپرست پروژهای نداشته باشد، دسترسی مسدود میشود
|
||||
if (!user.projects || user.projects.length === 0) {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-bg px-4">
|
||||
<div className="w-full max-w-md rounded-2xl border border-line bg-panel p-8 text-center shadow-sm">
|
||||
<h1 className="text-[16px] font-extrabold text-red">پروژه تخصیص داده نشده است</h1>
|
||||
<p className="mt-2 text-[12.5px] leading-6 text-muted">
|
||||
شما به عنوان سرپرست پروژه در سیستم ثبت شدهاید اما هنوز هیچ پروژهای به شما تخصیص داده نشده است.
|
||||
تا زمان تخصیص پروژه توسط مدیر سیستم، اجازه ورود به سامانه را ندارید.
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
useAuthStore.getState().logout();
|
||||
window.location.href = "/login";
|
||||
}}
|
||||
className="mt-5 inline-flex h-10 w-full cursor-pointer items-center justify-center rounded-lg bg-accent px-4 text-[13px] font-bold text-white transition-colors hover:bg-accent-dark"
|
||||
>
|
||||
خروج از حساب
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// سرپرست پروژه فقط به انبار و PM دسترسی دارد
|
||||
if (!pathname.startsWith("/inventory") && pathname !== "/panel/pm") {
|
||||
return <Navigate to="/panel/pm" replace />;
|
||||
}
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// صفحهی اصلی بر اساس نقش: مدیر پروژه → پنل انبار؛ مدیر تدارکات/ادمین → دفتر
|
||||
// صفحهی اصلی بر اساس نقش: سرپرست پروژه → پنل مدیریت پروژه (PM)؛ مدیران و ادمین → دفتر تدارکات
|
||||
function HomeRoute() {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
if (user?.role === "pm") return <Navigate to="/inventory" replace />;
|
||||
if (user?.role === "supervisor") return <Navigate to="/panel/pm" replace />;
|
||||
return <DashboardPage />;
|
||||
}
|
||||
|
||||
// دسترسی ایجاد استعلام/پیشنهاد (ویزارد) فقط برای مدیر تدارکات و ادمین
|
||||
// دسترسی ایجاد استعلام/پیشنهاد (ویزارد): مدیر تدارکات، مدیر پروژه و ادمین
|
||||
function RequireProcurementWrite({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
if (user?.role !== "admin" && user?.role !== "procurement_manager") {
|
||||
return <Navigate to={user?.role === "pm" ? "/inventory" : "/"} replace />;
|
||||
if (user?.role !== "admin" && user?.role !== "procurement_manager" && user?.role !== "pm") {
|
||||
return <Navigate to={user?.role === "supervisor" ? "/inventory" : "/"} replace />;
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// پنل «مدیریت پروژه (PM)» — اپ PM روی همان دامنه زیر مسیر /pm سرو میشود و
|
||||
// اینجا بهصورت iframe تمامصفحه داخل پوسته ERP نمایش داده میشود.
|
||||
// پنل «مدیریت پروژه (PM)» — اپ PM روی همان دامنه زیر مسیر /pm سرو میشود
|
||||
function PmPanelPage() {
|
||||
return (
|
||||
<iframe
|
||||
@@ -92,14 +117,40 @@ function PmPanelPage() {
|
||||
);
|
||||
}
|
||||
|
||||
// دسترسی پنل PM: ادمین، مدیر پروژه و سرپرست پروژه — مدیر تدارکات ندارد
|
||||
// دسترسی پنل PM: همه نقشها دسترسی دارند
|
||||
function RequirePmPanel({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const allowed = user?.role === "admin" || user?.role === "pm" || user?.role === "supervisor";
|
||||
const allowed = user?.role === "admin" || user?.role === "procurement_manager" || user?.role === "pm" || user?.role === "supervisor";
|
||||
if (!allowed) return <Navigate to="/" replace />;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// دسترسی پنل سازماندهی: فقط ادمین، مدیر تدارکات و مدیر پروژه
|
||||
function RequireOrganization({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const allowed = user?.role === "admin" || user?.role === "procurement_manager" || user?.role === "pm";
|
||||
if (!allowed) return <Navigate to={user?.role === "supervisor" ? "/inventory" : "/"} replace />;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// دسترسی تغییر موجودی انبار: فقط سرپرست پروژه و ادمین (مدیر تدارکات و مدیر پروژه نمیتوانند موجودی تغییر دهند)
|
||||
function RequireInventoryChange({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
if (user?.role !== "admin" && user?.role !== "supervisor") {
|
||||
return <Navigate to="/inventory" replace />;
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
// دسترسی مدیریت انبارها: فقط مدیران و ادمین (سرپرست پروژه فقط میتواند موجودی تغییر دهد)
|
||||
function RequireWarehouseManage({ children }: { children: React.ReactNode }) {
|
||||
const user = useAuthStore((s) => s.user);
|
||||
if (user?.role === "supervisor") {
|
||||
return <Navigate to="/inventory" replace />;
|
||||
}
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
@@ -200,7 +251,9 @@ export default function App() {
|
||||
element={
|
||||
<RequireAuth>
|
||||
<RequirePmProjects>
|
||||
<ChangeInventoryPage />
|
||||
<RequireInventoryChange>
|
||||
<ChangeInventoryPage />
|
||||
</RequireInventoryChange>
|
||||
</RequirePmProjects>
|
||||
</RequireAuth>
|
||||
}
|
||||
@@ -220,18 +273,24 @@ export default function App() {
|
||||
element={
|
||||
<RequireAuth>
|
||||
<RequirePmProjects>
|
||||
<WarehousesPage />
|
||||
<RequireWarehouseManage>
|
||||
<WarehousesPage />
|
||||
</RequireWarehouseManage>
|
||||
</RequirePmProjects>
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/inventory/org"
|
||||
element={<Navigate to="/organization" replace />}
|
||||
/>
|
||||
<Route
|
||||
path="/organization"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<RequirePmProjects>
|
||||
<RequireOrganization>
|
||||
<OrganizationPage />
|
||||
</RequirePmProjects>
|
||||
</RequireOrganization>
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user