EverydayTech Platform - Developer Reference
Complete Source Code Documentation - All Applications
Loading...
Searching...
No Matches
Breadcrumbs.tsx
Go to the documentation of this file.
1"use client";
2
3import { usePathname } from 'next/navigation';
4import Link from 'next/link';
5import { Icon } from '@/contexts/IconContext';
6
7// Navigation-based breadcrumb mapping
8const breadcrumbMap: Record<string, { section: string; subsection?: string; page: string }> = {
9 // Dashboard
10 '/pages/home': { section: 'Dashboard', page: 'Home' },
11 '/pages/start-here': { section: 'Dashboard', page: 'Start Here' },
12 '/advisor': { section: 'Dashboard', page: 'Advisor' },
13
14 // Point of Sale
15 '/sales': { section: 'Point of Sale', page: 'Sales' },
16 '/pages/invoices': { section: 'Point of Sale', page: 'Invoices' },
17 '/pages/sales/picking': { section: 'Point of Sale', page: 'Sales Picking' },
18 '/pages/sales/end-of-day': { section: 'Point of Sale', page: 'End of Day' },
19 '/pages/sales/display': { section: 'Point of Sale', page: 'Customer Display' },
20 '/pages/reports/pos-sales-report': { section: 'Point of Sale', page: 'Sales Report' },
21
22 // Products
23 '/pages/products': { section: 'Products', page: 'Products' },
24 '/purchase-orders': { section: 'Products', page: 'Purchase Orders' },
25 '/pages/products/price-changes': { section: 'Products', page: 'Price Changes' },
26 '/pages/products/signs-labels': { section: 'Products', page: 'Signs and Labels' },
27 '/pages/products/stocktake': { section: 'Products', page: 'Stocktake' },
28 '/pages/products/stock-levels': { section: 'Products', page: 'Stock Levels' },
29
30 // Customers
31 '/pages/customers': { section: 'Customers', page: 'Customers' },
32 '/pages/customers/loyalty': { section: 'Customers', page: 'Loyalty' },
33 '/pages/customers/customer-accounts': { section: 'Customers', page: 'Customer Accounts' },
34
35 // Suppliers
36 '/pages/suppliers': { section: 'Suppliers', page: 'Suppliers' },
37
38 // Reports
39 '/pages/reports': { section: 'Reports', page: 'Reports Library' },
40 '/pages/reports/analytics': { section: 'Reports', page: 'Analytics Dashboard' },
41 '/pages/reports/franchise-report': { section: 'Reports', page: 'Franchise Reports' },
42 '/pages/reports/sales-reports': { section: 'Reports', page: 'Sales Reports' },
43
44 // Marketing
45 '/marketing': { section: 'Marketing', page: 'Marketing Programs' },
46 '/prepay': { section: 'Marketing', page: 'Prepay' },
47
48 // Operations
49 '/pages/settings/operations/sale-processing': { section: 'Operations', page: 'Sale Processing' },
50 '/pages/settings/operations/pricing': { section: 'Operations', page: 'Pricing' },
51 '/pages/settings/operations/stock-control': { section: 'Operations', page: 'Stock Control' },
52 '/pages/settings/operations/accounts': { section: 'Operations', page: 'Customer Accounts' },
53 '/pages/settings/operations/loyalty': { section: 'Operations', page: 'Loyalty Programs' },
54 '/pages/settings/operations/gift-cards': { section: 'Operations', page: 'Gift Cards' },
55 '/pages/settings/operations/end-of-day': { section: 'Operations', page: 'End of Day' },
56
57 // Settings
58 '/pages/settings': { section: 'Settings', page: 'Settings' },
59 '/pages/settings/departments': { section: 'Settings', page: 'Departments' },
60 '/pages/settings/printers-cartridges': { section: 'Settings', page: 'Printers & Cartridges' },
61 '/pages/settings/staff': { section: 'Settings', page: 'Staff' },
62 '/pages/settings/stores': { section: 'Settings', page: 'Stores' },
63 '/pages/settings/stores/lanes': { section: 'Settings', subsection: 'Stores', page: 'Lanes' },
64 '/pages/settings/stores/topology': { section: 'Settings', subsection: 'Stores', page: 'Network Topology' },
65 '/pages/settings/payment-types': { section: 'Settings', page: 'Payment Types' },
66 '/pages/settings/your-details': { section: 'Settings', page: 'Your Details' },
67 '/pages/settings/media/photos': { section: 'Settings', subsection: 'Media', page: 'Photo Management' },
68 '/pages/settings/media/cloud-storage': { section: 'Settings', subsection: 'Media', page: 'Cloud Storage' },
69 '/pages/settings/media/receipt-formats': { section: 'Settings', subsection: 'Media', page: 'Receipt Formats' },
70
71 // Devices
72 '/pages/settings/devices/barcode-scanners': { section: 'Devices', page: 'Barcode Scanners' },
73 '/pages/settings/devices/receipt-printers': { section: 'Devices', page: 'Receipt Printers' },
74 '/pages/settings/devices/cash-drawers': { section: 'Devices', page: 'Cash Drawers' },
75 '/pages/settings/devices/label-formats': { section: 'Devices', page: 'Label Formats' },
76 '/pages/settings/devices/eftpos': { section: 'Devices', page: 'EFTPOS Terminals' },
77 '/pages/settings/devices/cameras': { section: 'Devices', page: 'Cameras' },
78 '/pages/settings/devices/customer-displays': { section: 'Devices', page: 'Customer Displays' },
79 '/pages/settings/devices/scales': { section: 'Devices', page: 'Scales' },
80
81 // Technical
82 '/pages/technical/security': { section: 'Technical', page: 'Security Settings' },
83 '/pages/technical/firewall': { section: 'Technical', page: 'Firewall' },
84 '/pages/technical/gdpr': { section: 'Technical', page: 'GDPR Compliance' },
85 '/pages/technical/pci': { section: 'Technical', page: 'PCI Requirements' },
86 '/pages/technical/network-topology': { section: 'Technical', page: 'Network Topology' },
87 '/pages/technical/database': { section: 'Technical', page: 'Database' },
88 '/pages/technical/api-settings': { section: 'Technical', page: 'API Settings' },
89 '/pages/technical/analytics': { section: 'Technical', page: 'Analytics' },
90 '/pages/technical/internet-services': { section: 'Technical', page: 'Internet Services' },
91 '/pages/technical/code-updates': { section: 'Technical', page: 'Code Updates' },
92 '/pages/technical/support-diagnostics': { section: 'Technical', page: 'Support & Diagnostics' },
93 '/pages/technical/documentation': { section: 'Technical', page: 'Documentation' },
94 '/api': { section: 'Technical', page: 'API' },
95 '/audit': { section: 'Technical', page: 'Audit Logs' },
96
97 // Account
98 '/pages/profile': { section: 'Account', page: 'My Profile' },
99};
100
101export default function Breadcrumbs() {
102 const pathname = usePathname();
103
104 // Don't show breadcrumbs on login, landing, or root pages
105 if (!pathname || pathname === '/' || pathname === '/login' || pathname === '/pages/login' || pathname === '/pages/landing') {
106 return null;
107 }
108
109 // Get breadcrumb structure from mapping
110 const breadcrumbData = breadcrumbMap[pathname];
111
112 if (!breadcrumbData) {
113 // Fallback: use simple path-based breadcrumbs
114 const segments = pathname.split('/').filter(segment => segment);
115 const breadcrumbs = segments.map((segment, index) => {
116 const path = '/' + segments.slice(0, index + 1).join('/');
117 const label = segment
118 .split('-')
119 .map(word => word.charAt(0).toUpperCase() + word.slice(1))
120 .join(' ');
121 return { path, label };
122 });
123
124 breadcrumbs.unshift({ path: '/pages/home', label: 'Dashboard' });
125
126 return (
127 <nav className="flex items-center gap-2 px-6 py-3 text-sm text-muted bg-surface border-b border-border">
128 {breadcrumbs.map((crumb, index) => (
129 <div key={crumb.path} className="flex items-center gap-2">
130 {index > 0 && <Icon name="chevron_right" size={16} className="text-muted/50" />}
131 {index === breadcrumbs.length - 1 ? (
132 <span className="font-medium text-text">{crumb.label}</span>
133 ) : (
134 <Link href={crumb.path} className="hover:text-brand transition-colors">
135 {crumb.label}
136 </Link>
137 )}
138 </div>
139 ))}
140 </nav>
141 );
142 }
143
144 // Build breadcrumbs from navigation structure
145 const breadcrumbs: Array<{ label: string; path?: string }> = [];
146
147 // Add section (not clickable)
148 breadcrumbs.push({ label: breadcrumbData.section });
149
150 // Add subsection if exists (not clickable)
151 if (breadcrumbData.subsection) {
152 breadcrumbs.push({ label: breadcrumbData.subsection });
153 }
154
155 // Add current page (not clickable, shown in bold)
156 breadcrumbs.push({ label: breadcrumbData.page });
157
158 return (
159 <nav className="flex items-center gap-2 px-6 py-3 text-sm text-muted bg-surface border-b border-border">
160 {breadcrumbs.map((crumb, index) => (
161 <div key={`${crumb.label}-${index}`} className="flex items-center gap-2">
162 {index > 0 && <Icon name="chevron_right" size={16} className="text-muted/50" />}
163 {index === breadcrumbs.length - 1 ? (
164 <span className="font-medium text-text">{crumb.label}</span>
165 ) : (
166 <span className="text-muted">{crumb.label}</span>
167 )}
168 </div>
169 ))}
170 </nav>
171 );
172}