turash/bugulma/frontend/components/admin/PageHeader.tsx

123 lines
3.5 KiB
TypeScript

import React from 'react';
import { clsx } from 'clsx';
import { ArrowLeft, MoreVertical } from 'lucide-react';
import { Button, Breadcrumbs, DropdownMenu } from '@/components/ui';
import { useNavigate } from 'react-router-dom';
export interface PageHeaderAction {
label: string;
icon?: React.ReactNode;
onClick: () => void;
variant?: 'primary' | 'outline' | 'ghost' | 'destructive';
disabled?: boolean;
}
export interface PageHeaderProps {
title: string;
subtitle?: string;
breadcrumbs?: Array<{ label: string; href?: string; icon?: React.ReactNode }>;
actions?: PageHeaderAction[];
onBack?: () => void;
backLabel?: string;
className?: string;
}
/**
* Enhanced page header component for admin pages
*/
export const PageHeader = ({
title,
subtitle,
breadcrumbs,
actions = [],
onBack,
backLabel = 'Back',
className,
}: PageHeaderProps) => {
const navigate = useNavigate();
const handleBack = () => {
if (onBack) {
onBack();
} else {
navigate(-1);
}
};
const primaryActions = actions.filter((a) => a.variant === 'primary' || !a.variant);
const secondaryActions = actions.filter((a) => a.variant !== 'primary' && a.variant !== 'destructive');
const destructiveActions = actions.filter((a) => a.variant === 'destructive');
const menuActions = [...secondaryActions, ...destructiveActions];
return (
<div className={clsx('mb-6 space-y-4', className)}>
{/* Breadcrumbs */}
{breadcrumbs && breadcrumbs.length > 0 && (
<Breadcrumbs items={breadcrumbs} showHome={false} />
)}
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4">
<div className="flex-1">
<div className="flex items-center gap-3">
{onBack && (
<Button
variant="ghost"
size="sm"
onClick={handleBack}
className="shrink-0"
aria-label={backLabel}
>
<ArrowLeft className="h-4 w-4 mr-2" />
{backLabel}
</Button>
)}
<div>
<h1 className="text-2xl font-bold tracking-tight">{title}</h1>
{subtitle && (
<p className="mt-1 text-sm text-muted-foreground">{subtitle}</p>
)}
</div>
</div>
</div>
{/* Actions */}
{actions.length > 0 && (
<div className="flex items-center gap-2 flex-shrink-0">
{primaryActions.map((action, index) => (
<Button
key={index}
variant={action.variant || 'primary'}
onClick={action.onClick}
disabled={action.disabled}
>
{action.icon && <span className="mr-2">{action.icon}</span>}
{action.label}
</Button>
))}
{menuActions.length > 0 && (
<DropdownMenu
trigger={
<Button variant="outline" size="sm" className="h-9 w-9 p-0">
<MoreVertical className="h-4 w-4" />
</Button>
}
items={menuActions.map((action, index) => ({
label: action.label,
value: `action-${index}`,
icon: action.icon,
onClick: action.onClick,
disabled: action.disabled,
}))}
align="right"
/>
)}
</div>
)}
</div>
</div>
);
};