import { useState } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBullhorn, faChartMixed, faChevronLeft, faChevronRight, faClockRotateLeft, faCommentDots, faGear, faGrid2, faHospitalUser, faCalendarCheck, faPhone, faUsers, faArrowRightFromBracket, faTowerBroadcast, faChartLine, faFileAudio, faPhoneMissed, } from "@fortawesome/pro-duotone-svg-icons"; import { faIcon } from "@/lib/icon-wrapper"; import { useAtom } from "jotai"; import { Link, useNavigate } from "react-router"; import { ModalOverlay, Modal, Dialog } from "@/components/application/modals/modal"; import { Button } from "@/components/base/buttons/button"; import { MobileNavigationHeader } from "@/components/application/app-navigation/base-components/mobile-header"; import { NavAccountCard } from "@/components/application/app-navigation/base-components/nav-account-card"; import { NavItemBase } from "@/components/application/app-navigation/base-components/nav-item"; import type { NavItemType } from "@/components/application/app-navigation/config"; import { Avatar } from "@/components/base/avatar/avatar"; import { useAuth } from "@/providers/auth-provider"; import { useAgentState } from "@/hooks/use-agent-state"; import { useThemeTokens } from "@/providers/theme-token-provider"; import { sidebarCollapsedAtom } from "@/state/sidebar-state"; import { cx } from "@/utils/cx"; const EXPANDED_WIDTH = 292; const COLLAPSED_WIDTH = 64; const IconGrid2 = faIcon(faGrid2); const IconBullhorn = faIcon(faBullhorn); const IconCommentDots = faIcon(faCommentDots); const IconChartMixed = faIcon(faChartMixed); const IconGear = faIcon(faGear); const IconPhone = faIcon(faPhone); const IconClockRewind = faIcon(faClockRotateLeft); const IconUsers = faIcon(faUsers); const IconHospitalUser = faIcon(faHospitalUser); const IconCalendarCheck = faIcon(faCalendarCheck); const IconTowerBroadcast = faIcon(faTowerBroadcast); const IconChartLine = faIcon(faChartLine); const IconFileAudio = faIcon(faFileAudio); const IconPhoneMissed = faIcon(faPhoneMissed); type NavSection = { label: string; items: NavItemType[]; }; const getNavSections = (role: string): NavSection[] => { if (role === 'admin') { return [ { label: 'Supervisor', items: [ { label: 'Dashboard', href: '/', icon: IconGrid2 }, { label: 'Team Performance', href: '/team-performance', icon: IconChartLine }, { label: 'Live Call Monitor', href: '/live-monitor', icon: IconTowerBroadcast }, ]}, { label: 'Data & Reports', items: [ { label: 'Leads', href: '/leads', icon: IconUsers }, { label: 'Patients', href: '/patients', icon: IconHospitalUser }, { label: 'Appointments', href: '/appointments', icon: IconCalendarCheck }, { label: 'Call Log', href: '/call-history', icon: IconClockRewind }, { label: 'Call Recordings', href: '/call-recordings', icon: IconFileAudio }, { label: 'Missed Calls', href: '/missed-calls', icon: IconPhoneMissed }, ]}, { label: 'Marketing', items: [ { label: 'Campaigns', href: '/campaigns', icon: IconBullhorn }, ]}, // Settings hub absorbs branding, rules, team, clinics, doctors, // telephony, ai, widget — one entry, navigates to the hub which // links to each section page. { label: 'Admin', items: [ { label: 'Settings', href: '/settings', icon: IconGear }, ]}, ]; } if (role === 'cc-agent') { return [ { label: 'Call Center', items: [ { label: 'Call Desk', href: '/', icon: IconPhone }, { label: 'Call History', href: '/call-history', icon: IconClockRewind }, { label: 'Patients', href: '/patients', icon: IconHospitalUser }, { label: 'Appointments', href: '/appointments', icon: IconCalendarCheck }, { label: 'My Performance', href: '/my-performance', icon: IconChartMixed }, ]}, ]; } return [ { label: 'Main', items: [ { label: 'Lead Workspace', href: '/', icon: IconGrid2 }, { label: 'All Leads', href: '/leads', icon: IconUsers }, { label: 'Patients', href: '/patients', icon: IconHospitalUser }, { label: 'Appointments', href: '/appointments', icon: IconCalendarCheck }, { label: 'Campaigns', href: '/campaigns', icon: IconBullhorn }, { label: 'Outreach', href: '/outreach', icon: IconCommentDots }, ]}, { label: 'Insights', items: [ { label: 'Analytics', href: '/reports', icon: IconChartMixed }, ]}, ]; }; const getRoleSubtitle = (role: string): string => { switch (role) { case 'admin': return 'Marketing Admin'; case 'cc-agent': return 'Call Center Agent'; default: return 'Marketing Executive'; } }; interface SidebarProps { activeUrl?: string; } export const Sidebar = ({ activeUrl = "/" }: SidebarProps) => { const { logout, user } = useAuth(); const { tokens } = useThemeTokens(); const navigate = useNavigate(); const [collapsed, setCollapsed] = useAtom(sidebarCollapsedAtom); const agentConfig = typeof window !== 'undefined' ? localStorage.getItem('helix_agent_config') : null; const agentId = agentConfig ? (() => { try { return JSON.parse(agentConfig).ozonetelAgentId; } catch { return null; } })() : null; const ozonetelState = useAgentState(agentId); const avatarStatus: 'online' | 'offline' = ozonetelState === 'ready' ? 'online' : 'offline'; const width = collapsed ? COLLAPSED_WIDTH : EXPANDED_WIDTH; const [logoutOpen, setLogoutOpen] = useState(false); const handleSignOut = () => { setLogoutOpen(true); }; const confirmSignOut = async () => { setLogoutOpen(false); await logout(); navigate('/login'); }; const navSections = getNavSections(user.role); const content = ( ); return ( <> {content}
{content}
{/* Logout confirmation modal */}

Sign out?

You will be logged out of Helix Engage and your Ozonetel agent session will end. Any active calls will be disconnected.

); };