From 730d0bd496ec86749248f5ce4de6310461df519b Mon Sep 17 00:00:00 2001 From: Milad Date: Sat, 26 Sep 2026 01:39:48 +0330 Subject: [PATCH] feat: PM panel under ERP shell + project-supervisor role MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - /panel/pm: the PM app (served on the same origin under /pm) is embedded as a full-height iframe; supervisors are funneled there from every route, ERP MobileTabBar hidden on that route - Panels menu: «مدیریت پروژه (PM)» is an internal route (admin/pm/supervisor only — procurement managers do not see it); PM link is no longer external - New system role 'supervisor' (user_role enum): label in users router, allowed in UserRoleUpdate schema, deny-by-default on all ERP routers; admin panel can grant/revoke it alongside procurement manager - Removed the obsolete VITE_PM_URL build plumbing (same-origin now) --- backend/app/routers/users.py | 2 + backend/app/schemas/procurement.py | 2 +- frontend/src/App.tsx | 38 +++++++++++- frontend/src/components/AppSwitcherMenu.tsx | 29 ++++++--- frontend/src/components/PanelMenu.tsx | 17 ++++++ .../src/components/layout/MobileTabBar.tsx | 4 ++ frontend/src/lib/api.ts | 4 +- frontend/src/pages/Admin/AdminPanel.tsx | 59 +++++++++++++++---- frontend/src/store/auth.ts | 2 +- 9 files changed, 132 insertions(+), 25 deletions(-) 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 ( +