/** * Application Breadcrumbs * Displays navigation breadcrumb trail for application pages * Supports dynamic breadcrumb items and project context */ 'use client'; import { Link } from '@/lib/i18n/routing'; import { usePathname } from '@/lib/i18n/routing'; import { ChevronRight, Home } from 'lucide-react'; import { cn } from '@/lib/utils'; export interface BreadcrumbItem { /** Display label */ label: string; /** Navigation href */ href: string; /** If true, this is the current page */ current?: boolean; } interface AppBreadcrumbsProps { /** Custom breadcrumb items (overrides auto-generation) */ items?: BreadcrumbItem[]; /** Show home icon as first item */ showHome?: boolean; /** Additional className */ className?: string; } /** Path segment to label mappings */ const pathLabels: Record = { projects: 'Projects', issues: 'Issues', sprints: 'Sprints', agents: 'Agents', settings: 'Settings', dashboard: 'Dashboard', admin: 'Admin', 'agent-types': 'Agent Types', users: 'Users', organizations: 'Organizations', }; /** * Generate breadcrumb items from the current pathname */ function generateBreadcrumbs(pathname: string): BreadcrumbItem[] { const segments = pathname.split('/').filter(Boolean); const breadcrumbs: BreadcrumbItem[] = []; let currentPath = ''; segments.forEach((segment, index) => { currentPath += `/${segment}`; // Skip locale segments (2-letter codes) if (segment.length === 2 && /^[a-z]{2}$/i.test(segment)) { return; } // Check if segment is a dynamic ID/slug (not in pathLabels) const label = pathLabels[segment] || segment; const isLast = index === segments.length - 1; breadcrumbs.push({ label, href: currentPath, current: isLast, }); }); return breadcrumbs; } export function AppBreadcrumbs({ items, showHome = true, className, }: AppBreadcrumbsProps) { const pathname = usePathname(); // Use provided items or generate from pathname const breadcrumbs = items ?? generateBreadcrumbs(pathname); // Don't render if no breadcrumbs or only home if (breadcrumbs.length === 0) { return null; } return ( ); }