UNPKG

besper-frontend-site-dev-main

Version:

Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment

377 lines (333 loc) 11.8 kB
/** * Customer Outreach Management Page Script - Bulletproof loading pattern * Manage customer outreach and communications */ class AdminCustomerOutreachManagementPage { constructor(options = {}) { this.options = { containerId: 'besper-site-content', environment: 'prod', ...options, }; this.initialized = false; // BULLETPROOF: Defer all complex operations to avoid blocking class export this.authService = null; this.operatorsService = null; this.isAuthenticated = false; // Initialize auth safely in next tick to ensure class export completes first if (typeof window !== 'undefined') { setTimeout(() => { this.initializeAuth(); }, 1); } } /** * Initialize authentication safely without blocking class export */ initializeAuth() { try { this.authService = this.getAuthService(); this.operatorsService = this.getOperatorsService(); } catch (error) { console.warn('Auth initialization failed, using fallback:', error); this.authService = this.createFallbackAuthService(); this.operatorsService = this.createFallbackOperatorsService(); } } /** * Get authentication service from global scope or create simple fallback */ getAuthService() { // Try to access global token auth service if available if (typeof window !== 'undefined' && window.tokenAuthService) { return window.tokenAuthService; } return this.createFallbackAuthService(); } /** * Get operators service from global scope or create simple fallback */ getOperatorsService() { // Try to access global page operators service if available if (typeof window !== 'undefined' && window.pageOperatorsService) { return window.pageOperatorsService; } return this.createFallbackOperatorsService(); } /** * Create safe fallback auth service */ createFallbackAuthService() { return { isUserAuthenticated: () => { try { return ( typeof window !== 'undefined' && window.auth && typeof window.auth.getToken === 'function' && !!window.auth.getToken() ); } catch (error) { return false; } }, getToken: () => { try { if ( typeof window !== 'undefined' && window.auth && typeof window.auth.getToken === 'function' ) { return window.auth.getToken(); } } catch (error) { console.warn('Token access failed:', error); } return null; }, getUserPermission: key => { try { if (typeof window === 'undefined') return null; const mappings = { contactId: window.contact_id || window.user_contactid, userName: window.user_name, name: window.user_name, userEmail: window.user_email, email: window.user_email, workspaceId: window.workspace_id, accountId: window.account_id, subscriptionId: window.subscription_id, }; return mappings[key] || null; } catch (error) { console.warn('User permission access failed:', error); return null; } }, }; } /** * Create safe fallback operators service */ createFallbackOperatorsService() { return { callOperator: async () => { console.warn( 'Operators service not available, returning empty response' ); return { success: false, message: 'Service not available' }; }, }; } /** * Initialize the page - IMMEDIATE RENDERING * Shows UI instantly without waiting for authentication */ async initialize(_data = {}) { if (this.initialized) return; try { // IMMEDIATE: Show the UI without any loading delays this.renderImmediateUI(); // IMMEDIATE: Setup basic interactions this.setupInteractions(); this.initialized = true; // DEFERRED: Initialize authentication features in background this.initializeAuthenticationFeaturesInBackground(); } catch (error) { console.error( 'Error initializing customer outreach management page:', error ); this.showError(error); } } /** * Render immediate UI structure - shows content instantly */ renderImmediateUI() { const container = document.getElementById(this.options.containerId); if (!container) return; // Clear any existing loading indicators container.innerHTML = ''; // Show immediate customer outreach management interface container.innerHTML = ` <div style="background: #f8f9fa; color: #022d54; font-family: Arial, sans-serif;"> <div style="max-width: 1200px; margin: 0 auto; padding: 2rem 1rem;"> <!-- Header --> <div style="margin-bottom: 2rem;"> <h1 style="color: #022d54; font-weight: 300; font-size: 28px; margin-bottom: 0.5rem;">Customer Outreach Management</h1> <p style="color: #6c757d; font-size: 14px; margin: 0;">Manage customer outreach and communications</p> </div> <!-- Main Content Area with Skeleton Loading --> <div style="background: white; border-radius: 8px; border: 1px solid #e0e0e0; overflow: hidden;"> <div style="padding: 1rem; border-bottom: 1px solid #e0e0e0;"> <h3 style="margin: 0; color: #022d54; font-size: 16px; font-weight: 500;">Loading Content...</h3> </div> <div id="page-content-area" style="padding: 2rem;"> <!-- Skeleton Loading Animation --> <div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; animation: pulse 1.5s ease-in-out infinite;"></div> <div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; width: 80%; animation: pulse 1.5s ease-in-out infinite;"></div> <div style="height: 20px; background: #e0e0e0; border-radius: 4px; margin-bottom: 1rem; width: 60%; animation: pulse 1.5s ease-in-out infinite;"></div> <div style="height: 100px; background: #e0e0e0; border-radius: 4px; animation: pulse 1.5s ease-in-out infinite;"></div> </div> </div> </div> </div> <!-- Skeleton Loading Animation --> <style> @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } } </style> `; } /** * Setup interactions - immediate setup without waiting */ setupInteractions() { // TODO: Add page-specific interactions here console.log('Customer Outreach Management interactions ready'); } /** * Initialize authentication features completely in background - NO UI BLOCKING */ async initializeAuthenticationFeaturesInBackground() { // Use requestIdleCallback for true background processing const initializeAuth = () => { try { // Ensure services are ready if (!this.authService) { this.initializeAuth(); } // Check authentication status without blocking if (this.authService) { this.isAuthenticated = this.authService.isUserAuthenticated(); if (this.isAuthenticated) { // Load data in background this.loadDataInBackground(); } else { this.showUnauthenticatedView(); } } } catch (error) { console.warn( 'Background authentication features initialization failed:', error ); // Continue silently - authentication is not critical for UI display } }; // Use requestIdleCallback for non-blocking background execution if (typeof requestIdleCallback !== 'undefined') { requestIdleCallback(initializeAuth, { timeout: 5000 }); } else { // Fallback for browsers without requestIdleCallback setTimeout(initializeAuth, 50); } } /** * Load data in background */ async loadDataInBackground() { try { console.log('Loading customer outreach management data in background...'); // TODO: Replace with actual data loading // Example: // const data = await this.fetchData(); // this.updateUIWithData(data); // For now, just remove skeleton loading after delay setTimeout(() => { this.updateUIWithActualContent(); }, 1000); } catch (error) { console.error('Background data loading failed:', error); } } /** * Update UI with actual content (replace skeleton loading) */ updateUIWithActualContent() { const contentArea = document.getElementById('page-content-area'); if (contentArea) { contentArea.innerHTML = ` <div style="padding: 1rem;"> <p>Customer Outreach Management content has loaded successfully!</p> <!-- TODO: Add actual customer outreach management content here --> </div> `; } } /** * Show unauthenticated view */ showUnauthenticatedView() { const contentArea = document.getElementById('page-content-area'); if (contentArea) { contentArea.innerHTML = ` <div style="text-align: center; padding: 2rem;"> <h2 style="color: #022d54;">Authentication Required</h2> <p style="color: #6c757d;">Please log in to access customer outreach management.</p> </div> `; } } /** * Show error message */ showError(error) { const container = document.getElementById(this.options.containerId); if (container) { container.innerHTML = ` <div style="background: #f8f9fa; display: flex; align-items: center; justify-content: center; padding: 4rem 1rem;"> <div style="text-align: center; padding: 2rem; background: white; border-radius: 8px; border: 1px solid #e0e0e0; max-width: 500px;"> <h3 style="color: #d32f2f; margin-bottom: 1rem;">Error Loading Customer Outreach Management</h3> <p style="color: #6c757d; margin-bottom: 1.5rem;">${error.message || error}</p> <button onclick="location.reload()" style="padding: 10px 20px; background: #022d54; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 14px;"> Try Again </button> </div> </div> `; } } } // BULLETPROOF EXPORT MECHANISM - Ensures class is always available (function () { 'use strict'; // Multiple export strategies to ensure maximum compatibility // Strategy 1: Direct window assignment (most reliable) if (typeof window !== 'undefined') { window.AdminCustomerOutreachManagementPage = AdminCustomerOutreachManagementPage; } // Strategy 2: Module exports for Node.js environments if (typeof module !== 'undefined' && module.exports) { module.exports = AdminCustomerOutreachManagementPage; } // Strategy 3: Global fallback if (typeof global !== 'undefined') { global.AdminCustomerOutreachManagementPage = AdminCustomerOutreachManagementPage; } // Strategy 4: AMD/RequireJS support if (typeof define === 'function' && define.amd) { define([], function () { return AdminCustomerOutreachManagementPage; }); } // Strategy 5: Self-executing verification setTimeout(function () { if ( typeof window !== 'undefined' && !window.AdminCustomerOutreachManagementPage ) { console.warn( 'AdminCustomerOutreachManagementPage export failed, retrying...' ); window.AdminCustomerOutreachManagementPage = AdminCustomerOutreachManagementPage; } }, 10); })();