feat(frontend): unified warehouse UI, calendar fix, partial receipts, RBAC views, admin panel, dev-mode 3-step

- header: icon box + dynamic subheader '[user] | [role] – [project/همه پروژهها]'
  on every warehouse page; module context kept in the hamburger (items 1-2)
- project manager view: office button + inline logout removed; hamburger
  contains only «خروج از حساب»; sub-views get «بازگشت به داشبورد» (Header
  backTo/goBack); «افزایش موجود» primary button on the dashboard (item 8)
- daily control: cells render the day-of-month (was the Jalali year),
  month nav uses real Jalali months, header is pure Jalali
  «امروز ۸ شهریور ۱۴۰۵», today gets a blue accent (item 3)
- arrivals: partial (item/qty) receipt — any valid item is enough to submit,
  ceiling + allocation-sum validation with inline errors, Received/In-Transit
  badges; ledger shows «رسیده X از Y» / «در راه Z» + «رسید جزیی» badge (item 4)
- api client: multipart uploads no longer send Content-Type json (fixes the
  invoice/proforma 400 «دادهی ارسالشده نامعتبر است»); undefined query
  params are dropped (fixes empty admin project filter, item 5)
- organization: user-creation card removed, role column read-only for
  procurement manager, Casdoor sync button (item 6)
- admin panel (/admin): Casdoor user sync + grant/revoke «مدیر تدارکات»;
  Developer Mode is a 3-step admin-gated flow on the login page (item 7)
This commit is contained in:
ali_mohaghegh
2026-09-01 17:28:19 +03:30
parent 83f4fb0747
commit c5997ac243
17 changed files with 648 additions and 228 deletions
+25 -5
View File
@@ -1,11 +1,12 @@
import { useMemo, useState } from "react";
import { useLocation, useSearchParams } from "react-router-dom";
import { Link, useLocation, useSearchParams } from "react-router-dom";
import { Plus, Warehouse as WarehouseIcon } from "lucide-react";
import { Header, PageLayout } from "../../components/layout/Header";
import { EmptyState } from "../../components/EmptyState";
import { Badge } from "../../components/ui/badge";
import { useAuthStore } from "../../store/auth";
import { PanelMenu } from "../../components/PanelMenu";
import { panelMenuItems, accountMenuItems, useLogout } from "./panelMenu";
import { accountMenuItems, inventorySubheader, panelMenuItems, pmMenuItems, useLogout } from "./panelMenu";
import { InventoryTopNav } from "./InventoryTopNav";
import { useInventoryData, brandName, catName, materialName, unitName, whName } from "./useInventoryData";
import type { InventoryRow, InventoryTransaction, TransactionType } from "../../lib/types";
@@ -137,9 +138,28 @@ export function InventoryPage() {
<div className="min-h-screen">
<Header
title="سامانه مدیریت انبار"
sub={isAdmin ? "مدیر تدارکات — همه پروژه‌ها" : user?.project_name ? `مدیر پروژه — ${user.project_name}` : "مدیر پروژه"}
menu={isAdmin ? <PanelMenu title="پنل مدیریت انبار" items={accountMenuItems(logout)} /> : undefined}
actions={isAdmin || isPM ? <InventoryTopNav pathname={location.pathname} onLogout={logout} variant={isAdmin ? "admin" : "pm"} /> : undefined}
sub={inventorySubheader(user)}
icon={<WarehouseIcon className="h-4.5 w-4.5" strokeWidth={2} />}
menu={
<PanelMenu
title="پنل مدیریت انبار"
items={isAdmin ? accountMenuItems(logout) : pmMenuItems(logout)}
/>
}
actions={
<>
<InventoryTopNav pathname={location.pathname} variant={isAdmin ? "admin" : "pm"} />
{isPM && (
<Link
to="/inventory/change?type=PURCHASE"
className="btn-line-file no-underline bg-accent text-white hover:bg-accent-dark"
>
<Plus className="h-3.5 w-3.5" />
افزایش موجود
</Link>
)}
</>
}
/>
<PageLayout className="flex flex-col gap-3">
{/* فیلترها */}