From 0cc29b1659f981d29a67a125ba2fb1a07d203e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82?= <81538700+PawiX25@users.noreply.github.com> Date: Fri, 13 Dec 2024 01:40:51 +0000 Subject: [PATCH] Add sorting options for programs by category, A-Z, deadline, and status --- index.html | 7 ++++++ script.js | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++--- styles.css | 37 ++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 13ee2fd..6cf7d2a 100644 --- a/index.html +++ b/index.html @@ -29,6 +29,13 @@ +
+ + + + +
+
diff --git a/script.js b/script.js index bc35f39..5511efe 100644 --- a/script.js +++ b/script.js @@ -192,24 +192,79 @@ function countActivePrograms() { return count; } +let currentSort = 'default'; + +function sortPrograms(programs, sortType) { + const flattened = Object.entries(programs).flatMap(([category, progs]) => + progs.map(p => ({...p, category})) + ); + + switch(sortType) { + case 'alphabetical': + return flattened.sort((a, b) => a.name.localeCompare(b.name)); + case 'deadline': + return flattened.sort((a, b) => { + if (!a.deadline) return 1; + if (!b.deadline) return -1; + return new Date(a.deadline) - new Date(b.deadline); + }); + case 'status': + const statusOrder = { active: 0, upcoming: 1, completed: 2 }; + return flattened.sort((a, b) => statusOrder[a.status] - statusOrder[b.status]); + default: + return flattened; + } +} + function renderPrograms() { const container = document.getElementById('programs-container'); + container.innerHTML = ''; const activeCount = countActivePrograms(); document.getElementById('active-count').textContent = activeCount; - for (const [category, programsList] of Object.entries(programs)) { + if (currentSort === 'default') { + for (const [category, programsList] of Object.entries(programs)) { + const section = document.createElement('section'); + section.className = 'category-section'; + section.innerHTML = ` +

${category.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}

+
+ ${programsList.map(program => createProgramCard(program)).join('')} +
+ `; + container.appendChild(section); + } + } else { + const sortedPrograms = sortPrograms(programs, currentSort); const section = document.createElement('section'); section.className = 'category-section'; section.innerHTML = ` -

${category.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}

- ${programsList.map(program => createProgramCard(program)).join('')} + ${sortedPrograms.map(program => createProgramCard(program)).join('')}
`; container.appendChild(section); } } +function updateSort(sortType) { + currentSort = sortType; + const buttons = document.querySelectorAll('.sort-btn'); + buttons.forEach(btn => { + btn.classList.toggle('active', btn.dataset.sort === sortType); + }); + renderPrograms(); + + const activeFilter = document.querySelector('.filter-btn.active'); + if (activeFilter) { + filterPrograms(activeFilter.dataset.category); + } + const searchInput = document.getElementById('program-search'); + if (searchInput.value) { + searchPrograms(searchInput.value); + } +} + function filterPrograms(category) { const sections = document.querySelectorAll('.category-section'); const buttons = document.querySelectorAll('.filter-btn'); @@ -326,6 +381,12 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('theme-toggle').addEventListener('click', toggleTheme); setInterval(updateDeadlines, 60000); + + document.querySelectorAll('.sort-btn').forEach(button => { + button.addEventListener('click', () => { + updateSort(button.dataset.sort); + }); + }); }); document.addEventListener('click', (e) => { diff --git a/styles.css b/styles.css index 3f43352..659ebba 100644 --- a/styles.css +++ b/styles.css @@ -1019,4 +1019,41 @@ body.modal-open { .program-position:hover { opacity: 1; +} + +.sort-container { + display: flex; + gap: var(--spacing-2); + flex-wrap: wrap; + margin-bottom: var(--spacing-4); +} + +.sort-btn { + background: var(--elevated); + color: var(--text); + border: 1px solid var(--border); + box-shadow: none; + transition: all 0.3s ease; + font-size: var(--font-1); + padding: var(--spacing-1) var(--spacing-2); +} + +.sort-btn.active { + background: var(--primary); + color: var(--white); + border-color: var(--primary); +} + +.sort-btn:hover { + transform: none; + box-shadow: none; + background: var(--smoke); +} + +@media screen and (max-width: 48em) { + .filter-container, + .sort-container { + justify-content: center; + margin: var(--spacing-2) 0; + } } \ No newline at end of file