/** * Admin Core Module * Contains core utilities, navigation, viewport management, and initialization coordination */ // Global admin state let adminAppState = { currentSection: 'dashboard' }; // Utility function to create a local date from YYYY-MM-DD string // This prevents timezone issues when displaying dates function createLocalDate(dateString) { if (!dateString) return null; const parts = dateString.split('-'); if (parts.length !== 3) return new Date(dateString); // fallback to original behavior // Create date using local timezone (year, month-1, day) return new Date(parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2])); } // A function to set viewport dimensions for admin page function setAdminViewportDimensions() { const doc = document.documentElement; // Set height and width doc.style.setProperty('--app-height', `${window.innerHeight}px`); doc.style.setProperty('--app-width', `${window.innerWidth}px`); // Handle safe area insets for devices with notches or home indicators if (CSS.supports('padding: env(safe-area-inset-top)')) { doc.style.setProperty('--safe-area-top', 'env(safe-area-inset-top)'); doc.style.setProperty('--safe-area-bottom', 'env(safe-area-inset-bottom)'); doc.style.setProperty('--safe-area-left', 'env(safe-area-inset-left)'); doc.style.setProperty('--safe-area-right', 'env(safe-area-inset-right)'); } else { doc.style.setProperty('--safe-area-top', '0px'); doc.style.setProperty('--safe-area-bottom', '0px'); doc.style.setProperty('--safe-area-left', '0px'); doc.style.setProperty('--safe-area-right', '0px'); } } // Add mobile menu functionality function setupMobileMenu() { const menuToggle = document.getElementById('mobile-menu-toggle'); const sidebar = document.getElementById('admin-sidebar'); const closeSidebar = document.getElementById('close-sidebar'); const adminNavLinks = document.querySelectorAll('.admin-nav a'); if (menuToggle && sidebar) { // Toggle menu menuToggle.addEventListener('click', () => { sidebar.classList.toggle('active'); menuToggle.classList.toggle('active'); document.body.classList.toggle('sidebar-open'); }); // Close sidebar button if (closeSidebar) { closeSidebar.addEventListener('click', () => { sidebar.classList.remove('active'); menuToggle.classList.remove('active'); document.body.classList.remove('sidebar-open'); }); } // Close sidebar when clicking outside document.addEventListener('click', (e) => { if (sidebar.classList.contains('active') && !sidebar.contains(e.target) && !menuToggle.contains(e.target)) { sidebar.classList.remove('active'); menuToggle.classList.remove('active'); document.body.classList.remove('sidebar-open'); } }); // Close sidebar when navigation link is clicked on mobile adminNavLinks.forEach(link => { link.addEventListener('click', () => { if (window.innerWidth <= 768) { sidebar.classList.remove('active'); menuToggle.classList.remove('active'); document.body.classList.remove('sidebar-open'); } }); }); } } // Setup navigation between admin sections function setupNavigation() { const navLinks = document.querySelectorAll('.admin-nav a'); const sections = document.querySelectorAll('.admin-section'); navLinks.forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); const targetId = link.getAttribute('href').substring(1); // Update active nav navLinks.forEach(l => l.classList.remove('active')); link.classList.add('active'); // Show target section sections.forEach(section => { section.style.display = section.id === targetId ? 'block' : 'none'; }); // Update URL hash and app state window.location.hash = targetId; adminAppState.currentSection = targetId; // Load section-specific data loadSectionData(targetId); // Close mobile menu if open const sidebar = document.getElementById('admin-sidebar'); if (sidebar && sidebar.classList.contains('open')) { sidebar.classList.remove('open'); } }); }); // Set initial active state based on current hash or default const currentHash = window.location.hash || '#dashboard'; const activeLink = document.querySelector(`.admin-nav a[href="${currentHash}"]`); if (activeLink) { activeLink.classList.add('active'); } // Check for initial hash routing const hash = window.location.hash; if (hash) { const sectionId = hash.substring(1); adminAppState.currentSection = sectionId; if (sectionId === 'shifts') { showSection('shifts'); } } } // Helper function to show a specific section function showSection(sectionId) { const sections = document.querySelectorAll('.admin-section'); const navLinks = document.querySelectorAll('.admin-nav a'); // Hide all sections sections.forEach(section => { section.style.display = section.id === sectionId ? 'block' : 'none'; }); // Update active nav navLinks.forEach(link => { const linkTarget = link.getAttribute('href').substring(1); link.classList.toggle('active', linkTarget === sectionId); }); // Update app state adminAppState.currentSection = sectionId; // Load section-specific data loadSectionData(sectionId); } // Load section-specific data based on current section function loadSectionData(sectionId) { switch(sectionId) { case 'walk-sheet': if (typeof checkAndLoadWalkSheetConfig === 'function') { checkAndLoadWalkSheetConfig(); } break; case 'dashboard': if (typeof loadDashboardData === 'function') { loadDashboardData(); } break; case 'shifts': if (typeof loadAdminShifts === 'function') { console.log('Loading shifts for admin panel...'); loadAdminShifts(); } break; case 'users': if (typeof loadUsers === 'function') { loadUsers(); } break; case 'convert-data': // Initialize data convert event listeners when section is shown setTimeout(() => { if (typeof window.setupDataConvertEventListeners === 'function') { console.log('Setting up data convert event listeners...'); window.setupDataConvertEventListeners(); } else { console.error('setupDataConvertEventListeners not found'); } }, 100); break; case 'cuts': // Initialize admin cuts manager when section is shown setTimeout(() => { if (typeof window.adminCutsManager === 'object' && window.adminCutsManager.initialize) { if (!window.adminCutsManager.isInitialized) { console.log('Initializing admin cuts manager from showSection...'); window.adminCutsManager.initialize().catch(error => { console.error('Failed to initialize cuts manager:', error); }); } else { console.log('Admin cuts manager already initialized'); } } else { console.error('adminCutsManager not found in showSection'); } }, 100); break; } } // Show status message function showStatus(message, type = 'info') { let container = document.getElementById('status-container'); // Create container if it doesn't exist if (!container) { container = document.createElement('div'); container.id = 'status-container'; container.className = 'status-container'; // Ensure proper z-index even if CSS hasn't loaded container.style.zIndex = '12300'; document.body.appendChild(container); } const messageDiv = document.createElement('div'); messageDiv.className = `status-message ${type}`; messageDiv.textContent = message; // Add click to dismiss functionality messageDiv.addEventListener('click', () => { messageDiv.remove(); }); // Add a small close button for better UX const closeBtn = document.createElement('span'); closeBtn.innerHTML = ' ×'; closeBtn.style.float = 'right'; closeBtn.style.fontWeight = 'bold'; closeBtn.style.marginLeft = '10px'; closeBtn.style.cursor = 'pointer'; closeBtn.setAttribute('title', 'Click to dismiss'); messageDiv.appendChild(closeBtn); container.appendChild(messageDiv); // Auto-remove after 5 seconds setTimeout(() => { if (messageDiv.parentNode) { messageDiv.remove(); } }, 5000); } // Escape HTML function escapeHtml(text) { if (text === null || text === undefined) { return ''; } const div = document.createElement('div'); div.textContent = String(text); return div.innerHTML; } // Debounce function for input events function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Initialize the admin core when DOM is loaded function initializeAdminCore() { // Set initial viewport dimensions and listen for resize events setAdminViewportDimensions(); window.addEventListener('resize', setAdminViewportDimensions); window.addEventListener('orientationchange', () => { // Add a small delay for orientation change to complete setTimeout(setAdminViewportDimensions, 100); }); setupNavigation(); setupMobileMenu(); // Check if URL has a hash to show specific section const hash = window.location.hash; if (hash === '#walk-sheet') { showSection('walk-sheet'); } else if (hash === '#convert-data') { showSection('convert-data'); } else if (hash === '#cuts') { showSection('cuts'); } else { // Default to dashboard showSection('dashboard'); } } // Export functions for use by other modules window.adminCore = { showSection, showStatus, escapeHtml, debounce, createLocalDate, initializeAdminCore, adminAppState };