Files
ERP/frontend/src/pages/Inventory/useInventoryData.ts
T
MMD 0ea0322967 Revert 253c922: restore the PM/RBAC work to the integration
Reverting the production revert so the pm branch can merge cleanly on
top of the restored RBAC base. Conflicts against newer integration work
resolved by combining:
- App.tsx: v7's bot-draft wizard bypass + login returnUrl kept alongside
  the supervisor gating (no-project block screen, panel scoping)
- LoginPage: returnUrl navigation kept, supervisor routing added
- migration.sql: bot_drafts table kept, unified-projects ALTERs restored
2026-10-01 15:24:56 +03:30

118 lines
4.1 KiB
TypeScript

// ============================================================
// Inventory data hook — loads all dash data (scoped by role/project)
// ============================================================
import { useCallback, useEffect, useMemo, useState } from "react";
import { apiV26 } from "../../lib/api";
import { useAuthStore } from "../../store/auth";
import { useDataChanged } from "../../lib/crossTab";
import type { InventoryRow, InventoryTransaction, Warehouse } from "../../lib/types";
export interface LookupData {
units: { id: number; code: string; name_fa: string | null }[];
brands: { id: string; name: string }[];
materials: { id: string; name: string; canonical_unit: { id: number; code: string; name_fa: string | null } | null }[];
projects: { id: string; name: string; pm_user_id: string | null; pm_name?: string | null }[];
}
export interface InventoryData {
warehouses: Warehouse[];
inventory: InventoryRow[];
transactions: InventoryTransaction[];
lookup: LookupData;
loading: boolean;
refresh: () => Promise<void>;
}
export function useInventoryData(): InventoryData {
const user = useAuthStore((s) => s.user);
const isSupervisor = user?.role === "supervisor";
const projectId = isSupervisor || user?.role === "pm" ? user?.project_id || undefined : undefined;
const [warehouses, setWarehouses] = useState<Warehouse[]>([]);
const [inventory, setInventory] = useState<InventoryRow[]>([]);
const [transactions, setTransactions] = useState<InventoryTransaction[]>([]);
const [lookup, setLookup] = useState<LookupData>({
units: [], brands: [], materials: [], projects: [],
});
const [loading, setLoading] = useState(true);
const load = useCallback(async () => {
try {
const [units, brands, mats, projs, whs, inv, txs] = await Promise.all([
apiV26.lookup.units(),
apiV26.lookup.brands(),
apiV26.lookup.materials(),
apiV26.lookup.projects(),
apiV26.warehouses.list(projectId),
apiV26.inventory.list({ project_id: projectId }),
apiV26.inventory.transactions({ project_id: projectId }),
]);
setLookup({ units, brands, materials: mats, projects: projs });
setWarehouses(whs);
setInventory(inv);
setTransactions(txs);
} catch {
// پروژه‌ی فعال ممکن است همین حالا باطل شده باشد — گیتِ پروژه در سطح مسیر
// (RequirePmProjects) پروژه‌ی جایگزین/صفحه‌ی خالی را نشان می‌دهد.
} finally {
setLoading(false);
}
}, [projectId]);
useEffect(() => {
setLoading(true);
void load();
}, [load]);
// تب‌های دیگر (ثبت تراکنش/رسید در تب دوم) → بازخوانی خودکار همین صفحه
useDataChanged(
useCallback(() => {
void load();
}, [load]),
["quotes", "inventory"],
);
const scopedWarehouses = useMemo(
() =>
user?.role === "admin" || user?.role === "procurement_manager"
? warehouses
: warehouses.filter((w) => String(w.project_id) === String(user?.project_id || "")),
[warehouses, user?.role, user?.project_id],
);
return {
warehouses: scopedWarehouses,
inventory,
transactions,
lookup,
loading,
refresh: load,
};
}
export function unitName(units: LookupData["units"], id: number | null | undefined): string {
const u = units.find((x) => x.id === id);
return u ? u.name_fa || u.code : "—";
}
export function brandName(brands: LookupData["brands"], id: string | null | undefined): string {
const b = brands.find((x) => x.id === id);
return b ? b.name : "—";
}
export function materialName(materials: LookupData["materials"], id: string): string {
const m = materials.find((x) => x.id === id);
return m ? m.name : "—";
}
export function projName(projects: LookupData["projects"], id: string | null | undefined): string {
const p = projects.find((x) => x.id === id);
return p ? p.name : "—";
}
export function whName(warehouses: Warehouse[], id: string | null | undefined): string {
const w = warehouses.find((x) => x.id === id);
return w ? w.name : "—";
}