// Main application state let allProjects = []; let filteredProjects = []; let currentPlatformFilter = 'all'; let currentUsecaseFilter = 'all'; let currentSearchQuery = ''; let currentSort = 'name'; // Load projects data async function loadProjects() { try { const response = await fetch('projects.json'); allProjects = await response.json(); filteredProjects = [...allProjects]; renderProjects(); updateProjectCount(); } catch (error) { console.error('Error loading projects:', error); document.getElementById('projects-grid').innerHTML = `

Error loading projects

Unable to load the projects data. Please try refreshing the page.

`; } } // Apply all filters function applyFilters() { filteredProjects = allProjects.filter(project => { // Platform filter const platformMatch = currentPlatformFilter === 'all' || project.platforms.includes(currentPlatformFilter); // Use case filter const usecaseMatch = currentUsecaseFilter === 'all' || project.usecases.includes(currentUsecaseFilter); // Search query const searchMatch = currentSearchQuery === '' || project.name.toLowerCase().includes(currentSearchQuery.toLowerCase()) || project.description.toLowerCase().includes(currentSearchQuery.toLowerCase()); return platformMatch && usecaseMatch && searchMatch; }); sortProjects(); renderProjects(); updateProjectCount(); } // Sort projects function sortProjects() { switch (currentSort) { case 'name': filteredProjects.sort((a, b) => a.name.localeCompare(b.name)); break; case 'platform': filteredProjects.sort((a, b) => { const platformA = a.platforms[0] || ''; const platformB = b.platforms[0] || ''; return platformA.localeCompare(platformB); }); break; case 'usecase': filteredProjects.sort((a, b) => { const usecaseA = a.usecases[0] || ''; const usecaseB = b.usecases[0] || ''; return usecaseA.localeCompare(usecaseB); }); break; } } // Render projects to the grid function renderProjects() { const grid = document.getElementById('projects-grid'); if (filteredProjects.length === 0) { grid.innerHTML = `

No projects found

Try adjusting your filters or search query.

`; return; } grid.innerHTML = filteredProjects.map(project => createProjectCard(project)).join(''); } // Create a project card HTML function createProjectCard(project) { const platformTags = project.platforms .map(p => `${formatTag(p)}`) .join(''); const usecaseTags = project.usecases .map(u => `${formatTag(u)}`) .join(''); const starBadge = project.github_repo ? `GitHub stars` : ''; return `

${escapeHtml(project.name)} ${starBadge}

${escapeHtml(project.description)}

${platformTags} ${usecaseTags}
`; } // Format tag names for display function formatTag(tag) { return tag .split('-') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(' '); } // Escape HTML to prevent XSS function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // Update project count display function updateProjectCount() { const count = document.getElementById('project-count'); count.textContent = `(${filteredProjects.length} of ${allProjects.length})`; } // Set up event listeners function setupEventListeners() { // Platform filter buttons document.querySelectorAll('#platform-filters .filter-btn').forEach(btn => { btn.addEventListener('click', () => { // Remove active class from all platform buttons document.querySelectorAll('#platform-filters .filter-btn').forEach(b => { b.classList.remove('active'); }); // Add active class to clicked button btn.classList.add('active'); // Update filter currentPlatformFilter = btn.dataset.filter; applyFilters(); }); }); // Use case filter buttons document.querySelectorAll('#usecase-filters .filter-btn').forEach(btn => { btn.addEventListener('click', () => { // Remove active class from all usecase buttons document.querySelectorAll('#usecase-filters .filter-btn').forEach(b => { b.classList.remove('active'); }); // Add active class to clicked button btn.classList.add('active'); // Update filter currentUsecaseFilter = btn.dataset.filter; applyFilters(); }); }); // Search input const searchInput = document.getElementById('search-input'); searchInput.addEventListener('input', (e) => { currentSearchQuery = e.target.value; applyFilters(); }); // Sort select const sortSelect = document.getElementById('sort-select'); sortSelect.addEventListener('change', (e) => { currentSort = e.target.value; sortProjects(); renderProjects(); }); } // Initialize the application document.addEventListener('DOMContentLoaded', () => { setupEventListeners(); loadProjects(); });