/* AAU CRM — route registry + mount */ const ROUTES = [ { path: '/exec', comp: ExecDashboard }, { path: '/flow', comp: FlowMap }, { path: '/marketing/overview', comp: MarketingOverview }, { path: '/marketing/connections', comp: DataSources }, { path: '/marketing/ads', comp: AdTracking }, { path: '/marketing/ads/:campaignId', comp: CampaignOptimizer }, { path: '/marketing/content', comp: ContentAnalytics }, { path: '/marketing/calendar', comp: ContentCalendar }, { path: '/marketing/sources', comp: SourcePerformance }, { path: '/marketing/channel/:channelId', comp: ChannelDetail }, { path: '/marketing/attribution', comp: AttributionHub }, { path: '/marketing/settings', comp: MarketingSettings }, { path: '/inbox', comp: UnifiedInbox, flush: true }, { path: '/inbox/report', comp: InboxDailyReport }, { path: '/calls', comp: CallLogQC }, { path: '/leads/kanban', comp: PipelineKanban }, { path: '/leads/pipeline-config', comp: PipelineConfig }, { path: '/leads', comp: PipelineTable }, { path: '/sales/today', comp: WorkQueue }, { path: '/sales/activity', comp: SalesActivity }, { path: '/sales/report', comp: SalesReport }, { path: '/leads/:id', comp: CustomerProfile360 }, { path: '/courses', comp: CourseCatalog }, { path: '/classes', comp: ClassesPage }, { path: '/enrollments', comp: EnrollmentPage }, { path: '/instructors', comp: InstructorsPage }, { path: '/finance', comp: FinancePnL }, { path: '/finance/cohorts', comp: FinancePnL }, { path: '/finance/revenue', comp: FinancePnL }, { path: '/finance/compare', comp: FinancePnL }, { path: '/finance/sources', comp: FinancePnL }, { path: '/enablement/intelligence', comp: ConversationIntelligence }, { path: '/enablement/assets', comp: AssetLibrary }, { path: '/enablement/scripts', comp: ScriptFlowBuilder }, { path: '/enablement/kb', comp: KnowledgeBase }, { path: '/settings/ai-chat', comp: AIChatConfig }, { path: '/qc/rulesets', comp: QCRulesets }, { path: '/qc/review', comp: QCReview }, { path: '/qc/dashboard', comp: QCDashboard }, { path: '/qc/reports', comp: QCReports }, { path: '/analytics/funnel', comp: AttributionHub }, { path: '/analytics/attribution', comp: AttributionHub }, { path: '/planning', comp: PlanScreen }, { path: '/planning/tracking', comp: PlanTrackScreen }, { path: '/admin/users', comp: UserManagement }, { path: '/admin/permissions', comp: RBACMatrix }, { path: '/system/channels', comp: ChatChannels }, { path: '/system/mcp', comp: MCPConnections }, { path: '/system/ai-settings', comp: AISettings }, { path: '/changelog', comp: ChangelogScreen }, { path: '/system/agents', comp: AgentsCenter }, { path: '/system/activity', comp: ActivityLog }, { path: '/system/notifications', comp: NotificationLog }, { path: '/system/ai-cost', comp: AICost }, { path: '/system/demo', comp: DemoData }, { path: '/settings', comp: SystemSettings }, ]; if (!location.hash) location.hash = '#/exec'; // Wait for the data-access layer to (try to) hydrate from the backend before // mounting, so screens render live data in LIVE mode. Falls back to mock if the // backend is unreachable (window.AAU_BOOT always resolves). function mountApp() { ReactDOM.createRoot(document.getElementById('root')).render( ); } Promise.resolve(window.AAU_BOOT).then(mountApp).catch(mountApp);