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}
);
}