Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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();
- } catch (err) {
- console.error("Error fetching authors:", err);
- }
- }
- function initFilters() {
- const nationalitySet = new Set(authors.map(a => a.nationality));
- const select = document.getElementById("filterNationality");
- nationalitySet.forEach(n => {
- const opt = document.createElement("option");
- opt.value = n;
- opt.textContent = n;
- select.appendChild(opt);
- });
- document.querySelectorAll("#filterName, #filterNationality, #filterAlive, #filterActiveYear")
- .forEach(el => el.addEventListener("input", applyFilters));
- document.getElementById("clearFilters").addEventListener("click", () => {
- document.getElementById("filterName").value = "";
- document.getElementById("filterNationality").value = "";
- document.getElementById("filterAlive").checked = false;
- document.getElementById("filterActiveYear").value = "";
- renderTable(authors);
- });
- document.querySelectorAll("th[data-sort]").forEach(th => {
- th.addEventListener("click", () => sortTable(th.dataset.sort));
- });
- document.getElementById("closeModal").onclick = () => {
- document.getElementById("booksModal").style.display = "none";
- };
- }
- function applyFilters() {
- let filtered = [...authors];
- const name = document.getElementById("filterName").value.toLowerCase();
- const nationality = document.getElementById("filterNationality").value;
- const alive = document.getElementById("filterAlive").checked;
- const year = parseInt(document.getElementById("filterActiveYear").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 = `
- <td>${a.id}</td>
- <td>${a.name}</td>
- <td>${a.birth_date}</td>
- <td><input type="checkbox" ${isAlive ? "checked" : ""} disabled></td>
- <td>${age}</td>
- <td>${a.nationality}</td>
- <td>${bibliographyCount}</td>
- <td><a href="#" onclick='openBooksModal(${JSON.stringify(JSON.stringify(books))})'>${summary}</a></td>
- <td>${yearsActive}</td>
- `;
- 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 = `<td>${b.name}</td><td>${b.year}</td><td>${b.type}</td>`;
- 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];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment