import AccountBalanceWalletOutlinedIcon from "@mui/icons-material/AccountBalanceWalletOutlined"; import AssessmentOutlinedIcon from "@mui/icons-material/AssessmentOutlined"; import AutorenewOutlinedIcon from "@mui/icons-material/AutorenewOutlined"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; import FolderOutlinedIcon from "@mui/icons-material/FolderOutlined"; import Inventory2OutlinedIcon from "@mui/icons-material/Inventory2Outlined"; import NotificationsNoneOutlinedIcon from "@mui/icons-material/NotificationsNoneOutlined"; import ReceiptLongOutlinedIcon from "@mui/icons-material/ReceiptLongOutlined"; import SearchIcon from "@mui/icons-material/Search"; import SettingsOutlinedIcon from "@mui/icons-material/SettingsOutlined"; import StorefrontOutlinedIcon from "@mui/icons-material/StorefrontOutlined"; import { isReadyToPay } from "@seahaven-ap/shared"; import { AppBar, Badge, Box, FormControl, IconButton, InputAdornment, InputLabel, MenuItem, Select, Stack, TextField, Toolbar, Tooltip, Typography, } from "@mui/material"; import type { ReactElement, ReactNode } from "react"; import { useMemo } from "react"; import { useLocation } from "react-router"; import { brand } from "@/lib/brand"; import { formatNavBadgeCount, navModules } from "@/layout/nav"; import { getMockInvoices, getMockUsers } from "@/mocks"; import { useMockSession } from "@/providers/use-mock-session"; import { useNavigate, type Path } from "@/router"; const RAIL_WIDTH = 96; const iconByTestId: Record = { "nav-procurement": StorefrontOutlinedIcon, "nav-invoice-processing": ReceiptLongOutlinedIcon, "nav-payment-processing": AccountBalanceWalletOutlinedIcon, "nav-approvals": FolderOutlinedIcon, "nav-vendors": Inventory2OutlinedIcon, "nav-recurring": AutorenewOutlinedIcon, "nav-past-invoices": FolderOutlinedIcon, "nav-reports": AssessmentOutlinedIcon, "nav-settings": SettingsOutlinedIcon, }; type AppShellProps = { children: ReactNode; }; function isSelected(pathname: string, to: Path): boolean { if (to === "/") { return pathname === "/" || pathname.startsWith("/invoices/"); } return pathname === to || pathname.startsWith(`${to}/`); } export function AppShell({ children }: AppShellProps): ReactElement { const location = useLocation(); const navigate = useNavigate(); const { user, setCurrentUserId } = useMockSession(); const users = getMockUsers(); const badgeByTestId = useMemo(() => { const invoices = getMockInvoices(); const attentionCount = invoices.filter( (invoice) => invoice.status === "pending_approval", ).length; const readyToPayCount = invoices.filter((invoice) => isReadyToPay(invoice.status)).length; return { "nav-invoice-processing": formatNavBadgeCount(attentionCount), "nav-payment-processing": formatNavBadgeCount(readyToPayCount), } as Record; }, []); return ( theme.zIndex.drawer + 1, background: brand.headerGradient, color: "#fff", }} > navigate("/")} sx={{ fontWeight: 800, letterSpacing: "0.08em", fontSize: "1.05rem", mr: 1, flexShrink: 0, border: 0, background: "transparent", color: "inherit", cursor: "pointer", p: 0, fontFamily: "inherit", }} > {brand.wordmark} ), endAdornment: ( Advanced ), }, }} /> Billy coded 1,693 fields on 99 invoices this month | Learn more {user.name} Mock user theme.zIndex.appBar - 1, }} > {navModules .filter((item) => !brand.hideModuleTestIds.includes(item.testId as never)) .map((item) => { const selected = isSelected(location.pathname, item.to); const Icon = iconByTestId[item.testId] ?? ReceiptLongOutlinedIcon; const badgeContent = badgeByTestId[item.testId]; return ( navigate(item.to)} sx={{ border: 0, cursor: "pointer", bgcolor: selected ? "rgba(47,128,237,0.12)" : "transparent", color: selected ? "primary.main" : "text.secondary", borderLeft: selected ? "3px solid" : "3px solid transparent", borderColor: selected ? "primary.main" : "transparent", borderRadius: 1, py: 1, px: 0.5, display: "flex", flexDirection: "column", alignItems: "center", gap: 0.5, position: "relative", }} > {item.label} ); })} {children} ); }