Josif_tepe

Untitled

Nov 3rd, 2025
656
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const API_URL = "https://raw.githubusercontent.com/sweko/uacs-internet-programming-exams/main/dry-run-mid-term-2024/data/authors.json";
  2. let authors = [];
  3. let currentSort = { key: null, direction: 'asc' };
  4.  
  5. document.addEventListener("DOMContentLoaded", async () => {
  6.   await fetchAuthors();
  7.   initFilters();
  8.   renderTable(authors);
  9. });
  10.  
  11. async function fetchAuthors() {
  12.   try {
  13.     const res = await fetch(API_URL);
  14.     authors = await res.json();
  15.     console.log(authors);
  16.     console.log(authors);
  17.   } catch (err) {
  18.     console.error("Error fetching authors:", err);
  19.   }
  20. }
  21.  
  22. function initFilters() {
  23.   const nationalitySet = new Set(authors.map(a => a.nationality));
  24.   const select = document.getElementById("nationality-search");
  25.   nationalitySet.forEach(n => {
  26.     const opt = document.createElement("option");
  27.     opt.value = n;
  28.     opt.textContent = n;
  29.     select.appendChild(opt);
  30.   });
  31.  
  32.   document.querySelectorAll("#name-search, #nationality-search, #alive-search, #year-search")
  33.     .forEach(el => el.addEventListener("input", applyFilters));
  34.  
  35.   document.getElementById("clearFilters").addEventListener("click", () => {
  36.     document.getElementById("name-search").value = "";
  37.     document.getElementById("nationality-search").value = "";
  38.     document.getElementById("alive-search").checked = false;
  39.     document.getElementById("year-search").value = "";
  40.     renderTable(authors);
  41.   });
  42.  
  43.   document.querySelectorAll("th[data-sort]").forEach(th => {
  44.     th.addEventListener("click", () => sortTable(th.dataset.sort));
  45.   });
  46.  
  47.   document.getElementById("close-modal").onclick = () => {
  48.     document.getElementById("booksModal").style.display = "none";
  49.   };
  50. }
  51.  
  52. function applyFilters() {
  53.   let filtered = [...authors];
  54.   const name = document.getElementById("name-search").value.toLowerCase();
  55.   const nationality = document.getElementById("nationality-search").value;
  56.   const alive = document.getElementById("alive-search").checked;
  57.   const year = parseInt(document.getElementById("year-search").value);
  58.  
  59.   filtered = filtered.filter(a => {
  60.     const isAlive = !a.death_date;
  61.     const { start, end } = getYearsActive(a);
  62.     return (!name || a.name.toLowerCase().includes(name)) &&
  63.            (!nationality || a.nationality === nationality) &&
  64.            (!alive || isAlive) &&
  65.            (!year || (start <= year && year <= end));
  66.   });
  67.  
  68.   renderTable(filtered);
  69. }
  70.  
  71. function renderTable(data) {
  72.   const tbody = document.querySelector("#authorsTable tbody");
  73.   tbody.innerHTML = "";
  74.  
  75.   data.forEach(a => {
  76.     const row = document.createElement("tr");
  77.     const isAlive = !a.death_date;
  78.     const age = calculateAge(a);
  79.     const { start, end } = getYearsActive(a);
  80.     const yearsActive = `${start} - ${end}`;
  81.     const books = a.bibliography || [];
  82.     const bibliographyCount = books.length;
  83.     const summary = getBibliographySummary(books);
  84.  
  85.     row.innerHTML = `
  86.       <td>${a.id}</td>
  87.       <td>${a.name}</td>
  88.       <td>${a.birth_date}</td>
  89.       <td><input type="checkbox" ${isAlive ? "checked" : ""} disabled></td>
  90.       <td>${age}</td>
  91.       <td>${a.nationality}</td>
  92.       <td>${bibliographyCount}</td>
  93.       <td><a href="#" onclick='openBooksModal(${JSON.stringify(JSON.stringify(books))})'>${summary}</a></td>
  94.       <td>${yearsActive}</td>
  95.     `;
  96.     tbody.appendChild(row);
  97.   });
  98. }
  99.  
  100. function calculateAge(a) {
  101.   const birth = new Date(a.birth_date);
  102.   const end = a.death_date ? new Date(a.death_date) : new Date();
  103.   return end.getFullYear() - birth.getFullYear();
  104. }
  105.  
  106. function getBibliographySummary(books) {
  107.   const countByType = {};
  108.   books.forEach(b => countByType[b.type] = (countByType[b.type] || 0) + 1);
  109.  
  110.   const parts = Object.entries(countByType).map(([type, count]) =>
  111.     `${count} ${type}${count > 1 ? "s" : ""}`
  112.   );
  113.   return parts.join(", ");
  114. }
  115.  
  116. function getYearsActive(a) {
  117.   if (!a.bibliography || a.bibliography.length === 0)
  118.     return { start: "-", end: "-" };
  119.  
  120.   const years = a.bibliography.map(b => b.year);
  121.   const start = Math.min(...years);
  122.   let end = Math.max(...years);
  123.   const currentYear = new Date().getFullYear();
  124.   const isAlive = !a.death_date;
  125.  
  126.   if (!isAlive) end = new Date(a.death_date).getFullYear();
  127.   else if (currentYear - end <= 2) end = "present";
  128.  
  129.   return { start, end };
  130. }
  131.  
  132. function openBooksModal(booksStr) {
  133.   const books = JSON.parse(booksStr);
  134.   const tbody = document.querySelector("#booksTable tbody");
  135.   tbody.innerHTML = "";
  136.  
  137.   books.sort((a, b) => b.year - a.year)
  138.        .forEach(b => {
  139.          const tr = document.createElement("tr");
  140.          tr.innerHTML = `<td>${b.name}</td><td>${b.year}</td><td>${b.type}</td>`;
  141.          tbody.appendChild(tr);
  142.        });
  143.  
  144.   document.getElementById("booksModal").style.display = "flex";
  145. }
  146.  
  147. function sortTable(key) {
  148.   const dir = (currentSort.key === key && currentSort.direction === "asc") ? "desc" : "asc";
  149.   currentSort = { key, direction: dir };
  150.  
  151.   const sorted = [...authors].sort((a, b) => compareAuthors(a, b, key, dir));
  152.   document.querySelectorAll("th[data-sort]").forEach(th => th.classList.remove("sort-asc", "sort-desc"));
  153.   document.querySelector(`th[data-sort="${key}"]`).classList.add(dir === "asc" ? "sort-asc" : "sort-desc");
  154.   renderTable(sorted);
  155. }
  156.  
  157. function compareAuthors(a, b, key, dir) {
  158.   const factor = dir === "asc" ? 1 : -1;
  159.   const valA = getComparableValue(a, key);
  160.   const valB = getComparableValue(b, key);
  161.   return (valA > valB ? 1 : valA < valB ? -1 : 0) * factor;
  162. }
  163.  
  164. function getComparableValue(a, key) {
  165.   switch (key) {
  166.     case "age": return calculateAge(a);
  167.     case "alive": return a.death_date ? 0 : 1;
  168.     case "bibliographyCount": return a.bibliography.length;
  169.     case "yearsActive":
  170.       const { start, end } = getYearsActive(a);
  171.       return start * 10000 + (end === "present" ? new Date().getFullYear() : end);
  172.     default: return a[key];
  173.   }
  174. }
  175.  
Advertisement
Add Comment
Please, Sign In to add comment