feat(frontend): add React UI — procurement office, wizard, suppliers, inventory panel (dash port), role-based login
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user