1import { API } from "./API.js"; 2 3//DOM Elements 4const FILTER_LIST = document.querySelector("#select-category"); 5const NEWS_COUNTER = document.querySelector("#news-count"); 6const INPUT_SEARCH = document.querySelector("#input-search-news"); 7const DATE_PICKER = document.querySelector("#datePicker"); 8 9//DELETE AND SEARCH 10const FILTER_BUTTONS = document.querySelectorAll("#category-buttons > li"); 11const DATE_BUTTONS = document.querySelectorAll("#date-buttons > li"); 12 13const ITEMS_LIST = document.querySelector("#items-list"); 14 15//HANDLERS DOM ELEMENTS 16const LOADER = document.querySelector("#loader"); 17 18let _FILTER = ""; 19let _DATE_FILTER = []; 20let _SEARCH = ""; 21 22const itemComponent = (info) => { 23 const li = document.createElement("li"); 24 25 li.innerHTML = ` 26 <a href="${info.link}" class="no-underline flex flex-col h-full border-solid border border-gray-200 rounded-xl overflow-hidden group"> 27 <figure class="h-[300px] relative"> 28 <figcaption class="flex gap-3 absolute z-[20] bg-color1 p-2 bottom-3 left-3 rounded-lg"> 29 <p class="!m-0 !p-0 !font-semibold text-white !uppercase">${ 30 info.category ? info.category : "Sin CategorÃa" 31 }</p> 32 </figcaption> 33 <img src="${info.image}" alt="${info.title}" class="w-full object-cover relative h-[300px]"> 34 </figure> 35 <section class="flex items-center justify-center gap-2 p-2 bg-color1 text-white"> 36 <i class="fa-regular fa-calendar-days"></i> 37 <p class="!uppercase !m-0 !p-0">${info.date}</p> 38 </section> 39 <section class="flex flex-col h-full justify-between gap-4 p-3"> 40 <h3 class="line-clamp-3 text-[25px] group-hover:text-color1 !font-bold text-color8 transition-colors duration-300 !m-0 !p-0"> 41 ${info.title} 42 </h3> 43 <p class="text-black font-light leading-6 line-clamp-2"> 44 ${info.comments} 45 </p> 46 <p class="underline text-black font-semibold group-hover:text-color1 transition-colors duration-300"> 47 Conocer más 48 </p> 49 </section> 50 </a> 51 `; 52 53 return li; 54}; 55 56const drawPagination = async (count, currentPage) => { 57 const pagination = document.getElementById("countPagination"); 58 pagination.innerHTML = ""; // Clear existing pagination buttons 59 60 const totalPages = Math.ceil(count / 8); // Usar PAGE_SIZE = 8 61 const maxVisiblePages = 4; 62 let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2)); 63 let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1); 64 65 if (endPage - startPage < maxVisiblePages - 1) { 66 startPage = Math.max(1, endPage - maxVisiblePages + 1); 67 } 68 69 if (startPage > 1) { 70 const prevButton = document.createElement("button"); 71 prevButton.setAttribute("type", "button"); 72 prevButton.setAttribute( 73 "class", 74 "bg-black !m-0 !p-0 border-none cursor-pointer w-[40px] h-[40px] rounded-full flex items-center justify-center transition-color duration-500 hover:opacity-80" 75 ); 76 prevButton.innerHTML = `<i class="fa-solid fa-chevron-left text-white text-[18px]"></i>`; 77 prevButton.addEventListener("click", () => { 78 ITEMS_LIST.innerHTML = ""; 79 LOADER.classList.remove("hidden"); 80 drawPagination(count, currentPage - 1); 81 API.goToPage(currentPage - 1, _FILTER, _DATE_FILTER, _SEARCH).then( 82 ({ results }) => { 83 drawItems(results, currentPage - 1); 84 } 85 ); 86 }); 87 pagination.appendChild(prevButton); 88 } 89 90 for (let i = startPage; i <= endPage; i++) { 91 const page = document.createElement("button"); 92 page.setAttribute("type", "button"); 93 page.setAttribute( 94 "class", 95 "page-button text-[16px] !m-0 !p-0 border-none cursor-pointer w-[40px] h-[40px] rounded-full flex items-center justify-center transition-color duration-500 font-bold hover:opacity-80" 96 ); 97 page.textContent = i; 98 if (i === currentPage) { 99 page.classList.add("bg-color1"); 100 } else { 101 page.classList.add("bg-color7"); 102 } 103 page.addEventListener("click", async () => { 104 ITEMS_LIST.innerHTML = ""; 105 LOADER.classList.remove("hidden"); 106 API.goToPage(i, _FILTER, _DATE_FILTER, _SEARCH).then(({ results }) => { 107 drawItems(results, i); 108 }); 109 drawPagination(count, i); // Update pagination to reflect the active page 110 });
111 pagination.appendChild(page); 112 } 113 114 if (endPage < totalPages) { 115 const nextButton = document.createElement("button"); 116 nextButton.setAttribute("type", "button"); 117 nextButton.setAttribute( 118 "class", 119 "bg-black !m-0 !p-0 border-none cursor-pointer w-[40px] h-[40px] rounded-full flex items-center justify-center transition-color duration-500 hover:opacity-80" 120 ); 121 nextButton.innerHTML = `<i class="fa-solid fa-chevron-right text-white text-[18px]"></i>`; 122 nextButton.addEventListener("click", () => { 123 ITEMS_LIST.innerHTML = ""; 124 LOADER.classList.remove("hidden"); 125 drawPagination(count, currentPage + 1); 126 API.goToPage(currentPage + 1, _FILTER, _DATE_FILTER, _SEARCH).then( 127 ({ results }) => { 128 drawItems(results, currentPage + 1); 129 } 130 ); 131 }); 132 pagination.appendChild(nextButton); 133 } 134 135 // Update active page button 136 const btnPages = document.querySelectorAll("#countPagination > .page-button"); 137 btnPages.forEach((btn) => { 138 btn.classList.remove("bg-color7"); 139 140 btn.classList.add("bg-color1"); 141 if (parseInt(btn.textContent) === currentPage) { 142 btn.classList.remove("bg-color1"); 143 144 btn.classList.add("bg-color7"); 145 } 146 }); 147}; 148 149const drawItems = async (items, currentPage) => { 150 LOADER.classList.add("hidden"); 151 ITEMS_LIST.innerHTML = ""; // Clear existing cards 152 153 items.forEach((item) => { 154 const itemHTML = itemComponent(item); 155 ITEMS_LIST.appendChild(itemHTML); 156 }); 157 158 // Update active page button 159 const btnPages = document.querySelectorAll("#countPagination > .page-button");
160 btnPages.forEach((btn) => { 161 btn.classList.remove("bg-color7"); 162 163 btn.classList.add("bg-color1"); 164 if (parseInt(btn.textContent) === currentPage) { 165 btn.classList.remove("bg-color1"); 166 167 btn.classList.add("bg-color7"); 168 } 169 }); 170}; 171 172const mainInterfaceFunctions = () => { 173 // Inicializar Flatpickr y guardar la instancia 174 const flatpickrInstance = flatpickr("#datePicker", { mode: "range", 175 dateFormat: "Y-m-d",}); 176 177 INPUT_SEARCH.addEventListener("input", async (e) => { 178 _SEARCH = e.target.value; 179 updateDOM(); 180 }); 181 182 FILTER_LIST.addEventListener("change", async (e) => { 183 FILTER_BUTTONS[0].classList.remove("opacity-80"); 184 FILTER_BUTTONS[0].addEventListener("click", async () => { 185 _FILTER = e.target.value; 186 FILTER_BUTTONS[0].classList.add("hidden"); 187 FILTER_BUTTONS[1].classList.remove("hidden"); 188 updateDOM(); 189 }); 190 if (!FILTER_BUTTONS[1].classList.contains("hidden")) { 191 _FILTER = e.target.value; 192 updateDOM(); 193 } 194 FILTER_BUTTONS[1].addEventListener("click", async () => { 195 _FILTER = ""; 196 FILTER_LIST.value = ""; 197 FILTER_BUTTONS[1].classList.add("hidden"); 198 FILTER_BUTTONS[0].classList.remove("hidden"); 199 FILTER_BUTTONS[0].classList.add("opacity-80"); 200 updateDOM(); 201 }); 202 }); 203 204 DATE_PICKER.addEventListener("change", async (e) => { 205 DATE_BUTTONS[0].classList.remove("opacity-80"); 206 207 DATE_BUTTONS[0].addEventListener("click", async () => { 208 const dateRange = e.target.value.split(" to "); 209 const startDate = dateRange[0]; 210 const endDate = dateRange[1]; 211 212 _DATE_FILTER = [startDate, endDate]; 213 DATE_BUTTONS[0].classList.add("hidden"); 214 DATE_BUTTONS[1].classList.remove("hidden"); 215 updateDOM(); 216 DATE_PICKER.setAttribute("disabled", "true"); // Deshabilitar el selector de fecha 217 }); 218 DATE_BUTTONS[1].addEventListener("click", async () => { 219 _DATE_FILTER = []; 220 flatpickrInstance.clear(); // Limpiar el valor del selector de fecha 221 DATE_PICKER.value = ""; 222 DATE_BUTTONS[1].classList.add("hidden"); 223 DATE_BUTTONS[0].classList.remove("hidden"); 224 DATE_BUTTONS[0].classList.add("opacity-80"); 225 DATE_PICKER.removeAttribute("disabled"); // Habilitar el selector de fecha 226 updateDOM(); 227 }); 228 }); 229}; 230 231const updateDOM = async () => { 232 LOADER.classList.remove("hidden"); 233 const { results } = await API.goToPage( 234 1, 235 _FILTER, 236 _DATE_FILTER, 237 _SEARCH 238 ); 239 const allItemsCount = await API.getAllItemsCount( 240 _FILTER, 241 _DATE_FILTER, 242 _SEARCH 243 ); 244 animateCount(NEWS_COUNTER, 0, allItemsCount, 1000); 245 246 if (results.length === 0) { 247 ITEMS_LIST.innerHTML = ""; 248 drawPagination(allItemsCount, 1); 249 ITEMS_LIST.appendChild(noFoundComponent()); 250 LOADER.classList.add("hidden"); 251 return; 252 } 253 drawItems(results, 1); 254 drawPagination(allItemsCount, 1); 255 LOADER.classList.add("hidden"); 256}; 257 258const noFoundComponent = () => { 259 const li = document.createElement("li"); 260 li.className = "col-span-1 lg:col-span-4 w-full h-full"; 261 li.innerHTML = ` 262 <section 263 class="lg:min-h-[1500px] h-full w-full flex flex-col gap-4 items-center justify-center" 264 id="not-found" 265 > 266 <img src="/SiteAssets/v1/assets/components/home-noticias/not-found.svg" alt="not found" class="w-[200px] h-[200px]" /> 267 <p class="text-[20px] font-semibold text-center">No se encontraron elementos</p> 268 </section>`; 269 return li; 270}; 271 272function animateCount(element, start = 0, end = 0, duration = 1000) { 273 anime({ 274 targets: element, 275 innerHTML: [start, end], 276 easing: "linear", 277 round: 1, // Redondear a números enteros 278 duration: duration, 279 }); 280} 281 282export const UI = { 283 drawPagination, 284 drawItems, 285 animateCount, 286 mainInterfaceFunctions, 287};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.