const API_URL = "https://raw.githubusercontent.com/sweko/uacs-internet-programming-exams/main/dry-run-mid-term-2024/data/authors.json"; let authors = []; let currentSort = { key: null, direction: 'asc' }; document.addEventListener("DOMContentLoaded", async () => { await fetchAuthors(); initFilters(); renderTable(authors); }); async function fetchAuthors() { try { const res = await fetch(API_URL); authors = await res.json(); console.log(authors); console.log(authors); } catch (err) { console.error("Error fetching authors:", err); } } function initFilters() { const nationalitySet = new Set(authors.map(a => a.nationality)); const select = document.getElementById("nationality-search"); nationalitySet.forEach(n => { const opt = document.createElement("option"); opt.value = n; opt.textContent = n; select.appendChild(opt); }); document.querySelectorAll("#name-search, #nationality-search, #alive-search, #year-search") .forEach(el => el.addEventListener("input", applyFilters)); document.getElementById("clearFilters").addEventListener("click", () => { document.getElementById("name-search").value = ""; document.getElementById("nationality-search").value = ""; document.getElementById("alive-search").checked = false; document.getElementById("year-search").value = ""; renderTable(authors); }); document.querySelectorAll("th[data-sort]").forEach(th => { th.addEventListener("click", () => sortTable(th.dataset.sort)); }); document.getElementById("close-modal").onclick = () => { document.getElementById("booksModal").style.display = "none"; }; } function applyFilters() { let filtered = [...authors]; const name = document.getElementById("name-search").value.toLowerCase(); const nationality = document.getElementById("nationality-search").value; const alive = document.getElementById("alive-search").checked; const year = parseInt(document.getElementById("year-search").value); filtered = filtered.filter(a => { const isAlive = !a.death_date; const { start, end } = getYearsActive(a); return (!name || a.name.toLowerCase().includes(name)) && (!nationality || a.nationality === nationality) && (!alive || isAlive) && (!year || (start <= year && year <= end)); }); renderTable(filtered); } function renderTable(data) { const tbody = document.querySelector("#authorsTable tbody"); tbody.innerHTML = ""; data.forEach(a => { const row = document.createElement("tr"); const isAlive = !a.death_date; const age = calculateAge(a); const { start, end } = getYearsActive(a); const yearsActive = `${start} - ${end}`; const books = a.bibliography || []; const bibliographyCount = books.length; const summary = getBibliographySummary(books); row.innerHTML = ` ${a.id} ${a.name} ${a.birth_date} ${age} ${a.nationality} ${bibliographyCount} ${summary} ${yearsActive} `; tbody.appendChild(row); }); } function calculateAge(a) { const birth = new Date(a.birth_date); const end = a.death_date ? new Date(a.death_date) : new Date(); return end.getFullYear() - birth.getFullYear(); } function getBibliographySummary(books) { const countByType = {}; books.forEach(b => countByType[b.type] = (countByType[b.type] || 0) + 1); const parts = Object.entries(countByType).map(([type, count]) => `${count} ${type}${count > 1 ? "s" : ""}` ); return parts.join(", "); } function getYearsActive(a) { if (!a.bibliography || a.bibliography.length === 0) return { start: "-", end: "-" }; const years = a.bibliography.map(b => b.year); const start = Math.min(...years); let end = Math.max(...years); const currentYear = new Date().getFullYear(); const isAlive = !a.death_date; if (!isAlive) end = new Date(a.death_date).getFullYear(); else if (currentYear - end <= 2) end = "present"; return { start, end }; } function openBooksModal(booksStr) { const books = JSON.parse(booksStr); const tbody = document.querySelector("#booksTable tbody"); tbody.innerHTML = ""; books.sort((a, b) => b.year - a.year) .forEach(b => { const tr = document.createElement("tr"); tr.innerHTML = `${b.name}${b.year}${b.type}`; tbody.appendChild(tr); }); document.getElementById("booksModal").style.display = "flex"; } function sortTable(key) { const dir = (currentSort.key === key && currentSort.direction === "asc") ? "desc" : "asc"; currentSort = { key, direction: dir }; const sorted = [...authors].sort((a, b) => compareAuthors(a, b, key, dir)); document.querySelectorAll("th[data-sort]").forEach(th => th.classList.remove("sort-asc", "sort-desc")); document.querySelector(`th[data-sort="${key}"]`).classList.add(dir === "asc" ? "sort-asc" : "sort-desc"); renderTable(sorted); } function compareAuthors(a, b, key, dir) { const factor = dir === "asc" ? 1 : -1; const valA = getComparableValue(a, key); const valB = getComparableValue(b, key); return (valA > valB ? 1 : valA < valB ? -1 : 0) * factor; } function getComparableValue(a, key) { switch (key) { case "age": return calculateAge(a); case "alive": return a.death_date ? 0 : 1; case "bibliographyCount": return a.bibliography.length; case "yearsActive": const { start, end } = getYearsActive(a); return start * 10000 + (end === "present" ? new Date().getFullYear() : end); default: return a[key]; } }