From 15b50a74c654e9294fc2d802ff69817ed1ad1ab6 Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Fri, 12 Dec 2025 21:22:01 -0800 Subject: [PATCH] feat: global breadcrumbs + walkthrough photo upload Breadcrumbs: - Added Breadcrumbs to main Layout (appears on ALL pages) - Dynamic route support (/batches/:id, /rooms/:id) - Proper navigation hierarchy Daily Walkthrough: - Enhanced layout with progress bar - Photo capture from camera or file upload - Notes fields for each check - Improved touch targets and mobile UX Removed inline breadcrumbs from individual pages since they now come from the global Layout. --- frontend/src/components/Layout.tsx | 3 + frontend/src/components/ui/Breadcrumbs.tsx | 43 +- frontend/src/pages/DailyWalkthroughPage.tsx | 504 ++++++++++++++------ 3 files changed, 385 insertions(+), 165 deletions(-) diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index 8f40beb..acdafd1 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -12,6 +12,7 @@ import { SessionTimeoutWarning } from './ui/SessionTimeoutWarning'; import { PageTitleUpdater } from '../hooks/usePageTitle'; import AnnouncementBanner from './AnnouncementBanner'; import { DevTools } from './dev/DevTools'; +import { Breadcrumbs } from './ui/Breadcrumbs'; export default function Layout() { const { user } = useAuth(); @@ -136,6 +137,8 @@ export default function Layout() {
+ {/* Global Breadcrumbs - appears on all pages */} +
diff --git a/frontend/src/components/ui/Breadcrumbs.tsx b/frontend/src/components/ui/Breadcrumbs.tsx index 8847bb2..1a661c2 100644 --- a/frontend/src/components/ui/Breadcrumbs.tsx +++ b/frontend/src/components/ui/Breadcrumbs.tsx @@ -33,14 +33,34 @@ const ROUTE_CONFIG: Record = { '/settings/walkthrough': { label: 'Walkthrough Settings', parent: '/settings' }, }; +// Dynamic route patterns +const DYNAMIC_ROUTES: { pattern: RegExp; getLabel: (match: RegExpMatchArray) => string; parent: string }[] = [ + { pattern: /^\/batches\/(.+)$/, getLabel: () => 'Batch Details', parent: '/batches' }, + { pattern: /^\/rooms\/(.+)$/, getLabel: () => 'Room Details', parent: '/rooms' }, + { pattern: /^\/tasks\/(.+)$/, getLabel: () => 'Task Details', parent: '/tasks' }, +]; + function getBreadcrumbs(pathname: string): BreadcrumbItem[] { const crumbs: BreadcrumbItem[] = []; let currentPath = pathname; - // Build breadcrumb chain + // Check for dynamic routes first + for (const route of DYNAMIC_ROUTES) { + const match = pathname.match(route.pattern); + if (match) { + crumbs.unshift({ label: route.getLabel(match), path: pathname }); + currentPath = route.parent; + break; + } + } + + // Build breadcrumb chain from static routes while (currentPath && ROUTE_CONFIG[currentPath]) { const config = ROUTE_CONFIG[currentPath]; - crumbs.unshift({ label: config.label, path: currentPath }); + // Don't add if already in crumbs (from dynamic route) + if (!crumbs.find(c => c.path === currentPath)) { + crumbs.unshift({ label: config.label, path: currentPath }); + } currentPath = config.parent || ''; } @@ -58,11 +78,11 @@ export function Breadcrumbs() { return (