// main.js import { teamMembers, teamTagData } from './data/team.js'; import { initializeSearchUI } from './utils/search.js'; import { overallBackgroundImage } from './data/areas.js'; import { scrollToSection } from './utils/dom.js'; import { updatePageBackgroundPosition } from './utils/router.js'; // Import the new function let allArtifactsData; // Declare a variable to hold the fetched artifacts // Team member component export function createTeamMember(name, role, hfUsername, tags) { const colors = ['blue', 'green', 'purple', 'orange', 'indigo', 'pink']; const colorIndex = name.length % colors.length; const color = colors[colorIndex]; const initials = name.split(' ').map(n => n[0]).join(''); const tagElements = tags.map(tag => { const tagInfo = teamTagData[tag]; return `${tagInfo.name}`; }).join(''); return `
${name}

${name}

${role}

${tagElements}
`; } // Make router's scrollToSection globally available for onclick handlers window.scrollToSection = scrollToSection; // Scroll to top functionality function scrollToTop() { window.scrollTo({ top: 0, behavior: 'smooth' }); } // Make scrollToTop globally available window.scrollToTop = scrollToTop; // Initialize team members function initializeTeamMembers() { const teamContainer = document.getElementById('team-grid'); if (!teamContainer) return; teamContainer.innerHTML = teamMembers.map(member => createTeamMember(member.name, member.role, member.username, member.tags) ).join(''); } // Note: Navigation handling moved to router.js for unified control // Initialize scroll to top button functionality function initializeScrollToTop() { const scrollToTopBtn = document.getElementById('scroll-to-top'); if (!scrollToTopBtn) return; // Add click event listener scrollToTopBtn.addEventListener('click', scrollToTop); // Show/hide button based on scroll position function toggleScrollToTopButton() { const scrollPosition = window.pageYOffset || document.documentElement.scrollTop; const showThreshold = 300; // Show button after scrolling 300px if (scrollPosition > showThreshold) { scrollToTopBtn.classList.remove('opacity-0', 'invisible'); scrollToTopBtn.classList.add('opacity-100', 'visible'); } else { scrollToTopBtn.classList.remove('opacity-100', 'visible'); scrollToTopBtn.classList.add('opacity-0', 'invisible'); } } // Listen for scroll events window.addEventListener('scroll', toggleScrollToTopButton); // Initial check toggleScrollToTopButton(); } // Main initialization document.addEventListener('DOMContentLoaded', async function() { // Mark as async const backgroundImg = document.querySelector('#overall-background img'); if (backgroundImg) { backgroundImg.src = `images/${overallBackgroundImage.image}`; backgroundImg.alt = overallBackgroundImage.altText; } // Fetch artifacts once try { const response = await fetch('/data/artifacts.json'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } allArtifactsData = await response.json(); console.log('Artifacts loaded once in main.js:', allArtifactsData.length, 'items'); } catch (error) { console.error('Failed to load artifacts in main.js:', error); allArtifactsData = []; } // Make allArtifactsData globally available for other modules window.allArtifacts = allArtifactsData; // Initialize scroll to top functionality initializeScrollToTop(); // Initialize search UI, passing the loaded artifacts initializeSearchUI(allArtifactsData); // The router will handle page-specific component initialization // No need to call initializeTeamMembers, initializeHomeAreaCards, etc. here // as they will be called by the router when loading the home page // Sidebar toggle functionality const searchToggle = document.getElementById('search-toggle'); const searchSidebar = document.getElementById('search-sidebar'); const searchClose = document.getElementById('search-close'); const mainContent = document.getElementById('main-content'); const overlay = document.getElementById('sidebar-overlay'); // Left sidebar toggle functionality const sidebarToggle = document.getElementById('sidebar-toggle'); const leftSidebar = document.getElementById('left-sidebar'); const mainContentEl = document.getElementById('main-content'); const leftSidebarBg = document.getElementById('left-sidebar-background'); // Get the background element function toggleLeftSidebar() { const isOpen = !leftSidebar.classList.contains('-translate-x-full'); if (isOpen) { // Close sidebar leftSidebar.classList.add('-translate-x-full'); mainContentEl.style.marginLeft = '0'; leftSidebarBg.classList.add('hidden'); // Hide the left sidebar background updatePageBackgroundPosition(); // Update page background position immediately on close } else { // Open sidebar - initially hide its background leftSidebarBg.classList.add('hidden'); // Ensure it's hidden before animation starts leftSidebar.classList.remove('-translate-x-full'); mainContentEl.style.marginLeft = '256px'; // Wait for transition to end before updating background position AND showing sidebar background const handleTransitionEnd = () => { leftSidebarBg.classList.remove('hidden'); // Now show the left sidebar background updatePageBackgroundPosition(); leftSidebar.removeEventListener('transitionend', handleTransitionEnd); }; leftSidebar.addEventListener('transitionend', handleTransitionEnd); } } if (sidebarToggle) sidebarToggle.addEventListener('click', toggleLeftSidebar) function toggleSearch() { const isOpen = !searchSidebar.classList.contains('translate-x-full'); const leftSidebarOpen = !leftSidebar.classList.contains('-translate-x-full'); const rightSidebarBg = document.getElementById('right-sidebar-background'); if (isOpen) { searchSidebar.classList.add('translate-x-full'); rightSidebarBg.classList.add('hidden'); if (leftSidebarOpen) { mainContent.style.marginLeft = '256px'; mainContent.classList.remove('mr-80'); } else { mainContent.style.marginLeft = '0'; mainContent.classList.remove('mr-80'); } overlay.classList.add('hidden'); } else { searchSidebar.classList.remove('translate-x-full'); rightSidebarBg.classList.remove('hidden'); if (leftSidebarOpen) { mainContent.style.marginLeft = '256px'; mainContent.classList.add('mr-80'); } else { mainContent.style.marginLeft = '0'; mainContent.classList.add('mr-80'); } overlay.classList.remove('hidden'); } } if (searchToggle) searchToggle.addEventListener('click', toggleSearch); if (searchClose) searchClose.addEventListener('click', toggleSearch); if (overlay) overlay.addEventListener('click', toggleSearch); // Scroll spy for left navigation const sections = document.querySelectorAll('section[id], div[id]'); const navLinks = document.querySelectorAll('.page-nav-link'); function updateActiveNavigation() { let current = ''; const scrollPos = window.scrollY + 150; sections.forEach(section => { const sectionTop = section.offsetTop; const sectionHeight = section.offsetHeight; if (scrollPos >= sectionTop && scrollPos < sectionTop + sectionHeight) { current = section.getAttribute('id'); } }); navLinks.forEach(link => { link.classList.remove('text-blue-600', 'bg-blue-50'); link.classList.add('text-gray-700'); if (link.getAttribute('href') === `#${current}`) { link.classList.remove('text-gray-700'); link.classList.add('text-blue-600', 'bg-blue-50'); } }); } window.addEventListener('scroll', updateActiveNavigation); updateActiveNavigation(); // Initial call });