import React, { useEffect, useMemo, useRef, useState } from 'react'; import { Link, Outlet, useLocation, useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { Bell, ChevronDown, LogOut, Menu, Search, Shield, User, } from 'lucide-react'; import { cn } from '@/lib/utils'; import { DOORMILE_WORDMARK_URL } from '@/assets/brand'; import { Avatar } from '@/components/ds/Avatar'; import { Badge } from '@/components/ui/badge'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'; import { useAuth } from '@/lib/AuthContext'; import { useExceptions } from '@/lib/doormileHooks'; import { formatDoormileTimestamp } from '@/lib/doormileTimestamp'; import doormileMark from 'assets/images/doormile-mark.png'; import AIPanel from '@/components/assistant/DoormileAI/AIPanel'; /** * The console shell. * * Single 56px header bar, compact search with a keyboard shortcut, hairline tab * indicator, mobile sheet — the design is unchanged. What changed is what it * points at: the Doormile Express destinations rather than the hiring ones. * * Seven destinations sit on the bar and the remaining eleven live in two * grouped menus (Fleet Ops, Reports), built from the same DropdownMenu the * account menu already uses. Eighteen flat tabs would not fit a 56px bar at any * width, and a console header should recede rather than become the loudest * thing on the page. */ const ROOT = '/doormile'; /* `doormile-logo.png` is a white wordmark — invisible on this bar's light chrome as-is. Recolored to brand red via filter rather than swapping the asset, same trick the source console's own TopNav uses on the identical file, so the two headers render the mark in the same color from the same source PNG. */ const LOGO_FILTER = { filter: 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)', }; /** Destinations that sit directly on the header bar. */ const NAV = [ { label: 'Dispatch', path: '/doormile/dispatch' }, { label: 'Orders', path: '/doormile/orders' }, { label: 'Deliveries', path: '/doormile/deliveries' }, { label: 'Riders', path: '/doormile/riders' }, { label: 'Clients', path: '/doormile/tenants' }, { label: 'Pricing', path: '/doormile/pricing' }, { label: 'Customers', path: '/doormile/customers' }, ]; /** Destinations grouped behind a menu, in the order the console lists them. */ const NAV_GROUPS = [ { label: 'Fleet Ops', items: [ { label: 'Hubs', path: '/doormile/hubs' }, { label: 'Vehicles', path: '/doormile/vehicles' }, { label: 'Tripsheets', path: '/doormile/tripsheets' }, { label: 'Exceptions', path: '/doormile/exceptions' }, { label: 'Competitive Intel', path: '/doormile/competitive-intel' }, { label: 'App Users', path: '/doormile/app-users' }, ], }, { label: 'Reports', items: [ { label: 'Orders Summary', path: '/doormile/reports/orderssummary' }, { label: 'Orders Details', path: '/doormile/reports/ordersdetails' }, { label: 'Riders Summary', path: '/doormile/reports/riderssummary' }, { label: 'Profitability', path: '/doormile/reports/profitability' }, ], }, ]; /** Every destination, flattened — what the mobile sheet renders. */ const ALL_DESTINATIONS = [...NAV, ...NAV_GROUPS.flatMap((group) => group.items)]; function GlobalSearch() { const navigate = useNavigate(); const [query, setQuery] = useState(''); const [focused, setFocused] = useState(false); const inputRef = useRef(null); /* Cmd/Ctrl+K focuses search — jump-to control shortcut */ useEffect(() => { const onKey = (e) => { if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); inputRef.current?.focus(); } }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, []); return (
{ e.preventDefault(); /* Orders is the console's search surface: it holds every booking, and an operator searching from the header is nearly always chasing one order number or one customer. */ if (query.trim()) navigate(`/doormile/orders?search=${encodeURIComponent(query.trim())}`); }} role="search" className={cn( 'relative hidden items-center transition-all duration-base ease-out md:flex', focused || query ? 'w-64' : 'w-44' )} >