diff --git a/backend/app/routers/users.py b/backend/app/routers/users.py index 702484d..f6517e6 100644 --- a/backend/app/routers/users.py +++ b/backend/app/routers/users.py @@ -41,6 +41,8 @@ USER_ROLE_LABELS = { "pm": "مدیر پروژه", "procurement_manager": "مدیر تدارکات", "admin": "ادمین", + # کاربر فقطِ پنل مدیریت پروژه (PM) — به انبار/تدارکات دسترسی ندارد + "supervisor": "سرپرست پروژه", } diff --git a/backend/app/schemas/procurement.py b/backend/app/schemas/procurement.py index 2d6f0b6..143c125 100644 --- a/backend/app/schemas/procurement.py +++ b/backend/app/schemas/procurement.py @@ -209,7 +209,7 @@ class UserCreate(APIModel): class UserRoleUpdate(APIModel): """role=None revokes the role (and any project assignment).""" - role: Literal["pm", "procurement_manager", "admin"] | None = None + role: Literal["pm", "procurement_manager", "admin", "supervisor"] | None = None class UserProjectUpdate(APIModel): diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4c1b872..93e3d4b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,5 @@ import { lazy, Suspense } from "react"; -import { Navigate, Route, Routes } from "react-router-dom"; +import { Navigate, Route, Routes, useLocation } from "react-router-dom"; import { useAuthStore } from "./store/auth"; import { ErrorBoundary } from "./components/ErrorBoundary"; import { RequirePmProjects } from "./components/RequirePmProjects"; @@ -53,9 +53,14 @@ function Loading() { } // همه‌ی صفحات پشت ورود هستند — بدون نشست، به صفحه‌ی ورود می‌رویم. +// سرپرست پروژه (فقطِ پنل PM) از هر مسیری به پنل PM هدایت می‌شود. function RequireAuth({ children }: { children: React.ReactNode }) { const user = useAuthStore((s) => s.user); + const { pathname } = useLocation(); if (!user) return ; + if (user.role === "supervisor" && pathname !== "/panel/pm") { + return ; + } return <>{children}; } @@ -66,6 +71,26 @@ function HomeRoute() { return ; } +// پنل «مدیریت پروژه (PM)» — اپ PM روی همان دامنه زیر مسیر /pm سرو می‌شود و +// اینجا به‌صورت iframe تمام‌صفحه داخل پوسته ERP نمایش داده می‌شود. +function PmPanelPage() { + return ( +