Files
ERP/frontend/src/components/layout/Header.tsx
T
ZCode 253c922280 revert: restore production to the state before 730d0bd (PM/RBAC work moved to 'pm')
Their three commits (730d0bd, 5a9b543, 387edfb) reached production by push and
auto-deployed. 387edfb expects a users.username column that the live database does
not have, so POST /api/v1/auth/login was returning HTTP 500. Their schema changes
never applied either (projects still has only id, name, description, start_date,
pm_user_id, created_at), so nothing depends on the reverted code.

This commit sets the tree back to exactly a02b3ea — verified with git diff against
it — while keeping history linear: the work itself is preserved on 'pm' at 387edfb.
2026-09-26 17:41:07 +00:00

69 lines
2.8 KiB
TypeScript

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; // نمایش آیکون دفتر کنار عنوان
icon?: ReactNode; // آیکون سفارشی جعبه‌ی کنار منو (پیش‌فرض: ClipboardList)
menu?: ReactNode; // منوی همبرگری بالای راست (ناوبری بین پنل‌ها)
}
// نوار بالای هر صفحه: منو (همبرگری) + جعبه‌ی آیکون + عنوان + اکشن‌ها
export function Header({ title, sub, backTo, backLabel = "بازگشت", actions, brand, icon, 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 max-md:sticky max-md:top-0 max-md:z-40">
{menu && <div className="flex shrink-0 items-center">{menu}</div>}
{(icon || brand) && (
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-accent-bg text-accent">
{icon || <ClipboardList className="h-4.5 w-4.5" strokeWidth={2} />}
</span>
)}
{backTo && (
<button
type="button"
onClick={goBack}
className="hidden md: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">
<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 max-md:pb-24", className)}>{children}</div>
);
}