feat(frontend): add React UI — procurement office, wizard, suppliers, inventory panel (dash port), role-based login

This commit is contained in:
ali_mohaghegh
2026-08-25 19:08:15 +03:30
parent 170aed66ea
commit 4e105c5cd5
103 changed files with 16352 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
import type { ReactNode } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { ChevronRight, ClipboardList } from "lucide-react";
import { cn } from "../../lib/utils";
interface HeaderProps {
title: string;
sub?: string;
backTo?: string; // مسیر بازگشتِ جایگزین (وقتی سابقه‌ای در برنامه نیست)
backLabel?: string;
actions?: ReactNode; // دکمه‌های سمت چپ
brand?: boolean; // نمایش آیکون دفتر کنار عنوان
menu?: ReactNode; // منوی همبرگری بالای راست (ناوبری بین پنل‌ها)
}
// نوار بالای هر صفحه: منو (همبرگری) + دکمه‌ی برگشت (یک مرحله‌ی قبل) + عنوان + اکشن‌ها
export function Header({ title, sub, backTo, backLabel = "بازگشت", actions, brand, menu }: HeaderProps) {
const navigate = useNavigate();
const location = useLocation();
// اگر کاربر از داخل برنامه به این صفحه آمده، یک قدم برمی‌گردیم؛
// اگر مستقیم باز شده (بدون سابقه‌ی داخلی)، به backTo می‌رویم.
const goBack = () => {
if (location.key !== "default") navigate(-1);
else if (backTo) navigate(backTo);
};
return (
<header className="flex flex-wrap items-center gap-3 border-b border-line bg-panel px-5 py-2.5">
{menu && <div className="flex shrink-0 items-center">{menu}</div>}
{backTo && (
<button
type="button"
onClick={goBack}
className="inline-flex cursor-pointer items-center gap-0.5 rounded-md px-2 py-1 text-[13px] text-muted transition-colors hover:bg-slate-bg hover:text-ink"
>
<ChevronRight className="h-4 w-4" />
{backLabel}
</button>
)}
<div className="flex min-w-0 items-center gap-2.5">
{brand && (
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-accent-bg text-accent">
<ClipboardList className="h-4.5 w-4.5" strokeWidth={2} />
</span>
)}
<div className="min-w-0">
<h1 className="text-[17px] font-extrabold leading-6">{title}</h1>
{sub && <div className="text-[11px] text-muted">{sub}</div>}
</div>
</div>
<div className="ms-auto flex flex-wrap items-center gap-2">{actions}</div>
</header>
);
}
// بدنه‌ی صفحه با عرض محدود و چینش مرکزی
export function PageLayout({
children,
className,
}: {
children: ReactNode;
className?: string;
}) {
return (
<div className={cn("mx-auto w-full max-w-[1200px] px-4 py-4", className)}>{children}</div>
);
}