import { NavLink } from "react-router-dom"; import { Activity, CheckCircle2, GitCompareArrows, GitMerge, Inbox as InboxIcon, Layers, LayoutDashboard, LogOut, Receipt, Stethoscope, Upload as UploadIcon, Users, } from "lucide-react"; import { cn } from "@/lib/utils"; import { useReconciliation } from "@/hooks/useReconciliation"; import { useAuth } from "@/auth/useAuth"; const nav = [ { to: "/", label: "Dashboard", icon: LayoutDashboard, end: true }, { to: "/claims", label: "Claims", icon: Receipt }, { to: "/remittances", label: "Remittances", icon: Stethoscope }, { to: "/providers", label: "Providers", icon: Users }, { to: "/upload", label: "Upload", icon: UploadIcon }, { to: "/activity", label: "Activity Log", icon: Activity }, ]; /** * Sidebar. Three sections under the brand mark: * - WORKSPACE — the day-to-day surface * - WORKFLOWS — triage & reconciliation lanes * - REFERENCE — long-tail batches & acks * * The active state uses a 2px left accent + an inset tint + a * subtle inner ring so the selected item reads instantly. Counts * (e.g. unmatched on Reconciliation) live as mono digits aligned to * the right edge so the eye can scan state at a glance. */ export function Sidebar() { const { unmatched } = useReconciliation(); const unmatchedCount = (unmatched.data?.claims.length ?? 0) + (unmatched.data?.remittances.length ?? 0); return ( ); } /** * Bottom-of-sidebar identity card. Driven by `useAuth()` so the * username + role update whenever the operator's session changes * (e.g. an admin re-grants a role via the admin pages, or the * session expires and a fresh login lands them back with a * different username). */ function CurrentUserCard() { const { user, logout } = useAuth(); if (!user) { // Shouldn't happen — the route guard ensures the sidebar only // mounts after auth is established. Render a harmless placeholder // so the layout doesn't reflow if the context ever lags. return (
Signed out
); } // Use the first letter of the username for the avatar monogram; // fall back to "?" if the username is somehow empty. const initial = user.username?.[0]?.toUpperCase() ?? "?"; return (
{initial}
{user.username}
{user.role}
); } function SectionLabel({ children }: { children: React.ReactNode }) { return (
{children}
); } function NavItem({ item, }: { item: { to: string; label: string; // Lucide icons accept `strokeWidth` as a wider union (string | number | null | undefined); // we declare it as `number | string` so any Lucide icon can be assigned // here without the prop-types assignability complaint from TS. icon: React.ComponentType<{ className?: string; strokeWidth?: number | string }>; end?: boolean; }; }) { return ( cn( "group relative flex items-center gap-3 rounded-md px-3 py-1.5 text-[13px] font-medium transition-colors", isActive ? "nav-active" : "text-muted-foreground hover:text-foreground hover:bg-muted/40" ) } > {item.label} ); }