Add sorting options for programs by category, A-Z, deadline, and status

This commit is contained in:
Paweł
2024-12-13 01:40:51 +00:00
parent 82b518e9a6
commit 0cc29b1659
3 changed files with 108 additions and 3 deletions

View File

@@ -29,6 +29,13 @@
<button class="filter-btn" data-category="completed">Completed</button>
</div>
<div class="sort-container">
<button class="sort-btn active" data-sort="default">By Category</button>
<button class="sort-btn" data-sort="alphabetical">A-Z</button>
<button class="sort-btn" data-sort="deadline">By Deadline</button>
<button class="sort-btn" data-sort="status">By Status</button>
</div>
<div id="programs-container">
</div>

View File

@@ -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 = `
<h2 class="headline">${category.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}</h2>
<div class="programs-grid">
${programsList.map(program => createProgramCard(program)).join('')}
</div>
`;
container.appendChild(section);
}
} else {
const sortedPrograms = sortPrograms(programs, currentSort);
const section = document.createElement('section');
section.className = 'category-section';
section.innerHTML = `
<h2 class="headline">${category.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}</h2>
<div class="programs-grid">
${programsList.map(program => createProgramCard(program)).join('')}
${sortedPrograms.map(program => createProgramCard(program)).join('')}
</div>
`;
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) => {

View File

@@ -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;
}
}