From 83f36a86ec68f46efcc9131c47a127f19b4b0955 Mon Sep 17 00:00:00 2001 From: vista-man <524715@vistacollege.nl> Date: Thu, 27 Mar 2025 12:06:42 +0100 Subject: [PATCH] =?UTF-8?q?Implement=20caching=20for=20Pok=C3=A9mon=20data?= =?UTF-8?q?,=20enhance=20competitor=20fetching,=20and=20improve=20sorting?= =?UTF-8?q?=20and=20search=20functionalities?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- v2/pokemon.js | 263 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 212 insertions(+), 51 deletions(-) diff --git a/v2/pokemon.js b/v2/pokemon.js index b21b89c..e8f5854 100644 --- a/v2/pokemon.js +++ b/v2/pokemon.js @@ -3,39 +3,52 @@ const CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 hours in milliseconds const listWrapper = document.querySelector(".list-wrapper"); const searchInput = document.querySelector("#search-input"); + const numberAscFilter = document.querySelector("#number-asc"); + const numberDescFilter = document.querySelector("#number-desc"); + const nameAscFilter = document.querySelector("#name-asc"); + const nameDescFilter = document.querySelector("#name-desc"); const notFoundMessage = document.querySelector("#not-found-message"); - const sortWrapper = document.querySelector(".sort-wrapper"); + const competitorsWrapper = document.querySelector("#competitors-wrapper"); let allPokemons = []; let filteredPokemons = []; document.addEventListener("DOMContentLoaded", () => { - fetchPokemons(); - setupSorting(); + const cachedData = localStorage.getItem("pokemons"); + const cacheTimestamp = localStorage.getItem("pokemons_timestamp"); + + if (cachedData && cacheTimestamp && (Date.now() - cacheTimestamp) < CACHE_DURATION) { + allPokemons = JSON.parse(cachedData); + console.log("Loaded Pokémon data from cache:", allPokemons); + filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); + displayPokemons(filteredPokemons); + fetchCompetitors(); + } else { + fetchPokemons(); + } }); function fetchPokemons() { console.log("Fetching Pokémon data from server..."); fetch(`./get-pokemon.php`) - .then((response) => { - if (!response.ok) { - throw new Error(`HTTP error! status: ${response.status}`); - } - return response.json(); - }) - .then((data) => { - if (data.error) { - console.error("Error from server:", data.error); - return; - } - - if (Array.isArray(data)) { - allPokemons = data; - console.log("Fetched Pokémon data:", allPokemons); - filteredPokemons = allPokemons; - displayPokemons(filteredPokemons); - } else { - console.error("Unexpected response format:", data); + .then((response) => response.text()) + .then((text) => { + console.log("Server response:", text); + try { + const data = JSON.parse(text); + if (Array.isArray(data)) { + allPokemons = data; + localStorage.setItem("pokemons", JSON.stringify(allPokemons)); + localStorage.setItem("pokemons_timestamp", Date.now().toString()); + console.log("Fetched and cached Pokémon data:", allPokemons); + filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); + displayPokemons(filteredPokemons); + fetchCompetitors(); + } else { + console.error("Unexpected response format:", data); + } + } catch (error) { + console.error("Error parsing JSON:", error); } }) .catch((error) => { @@ -43,6 +56,28 @@ }); } + async function fetchPokemonDataBeforeRedirect(id) { + try { + console.log(`Fetching data for Pokémon ID ${id} before redirect...`); + const response = await fetch(`./get-pokemon.php?id=${id}`); + const text = await response.text(); + console.log(`Response for Pokémon ID ${id}:`, text); + if (!text) { + throw new Error("Empty response from server"); + } + const pokemon = JSON.parse(text); + + if (pokemon.error) { + throw new Error(pokemon.error); + } + + return true; + } catch (error) { + console.error(`Failed to fetch Pokémon data before redirect for ID ${id}:`, error); + return false; + } + } + function displayPokemons(pokemons) { console.log("Displaying Pokémon data:", pokemons); listWrapper.innerHTML = ""; @@ -52,53 +87,179 @@ listItem.className = "list-item"; listItem.innerHTML = `
-

#${String(pokemon.id).padStart(3, "0")}

+

#${pokemon.id}

- ${pokemon.name} + ${pokemon.name}

${pokemon.name}

`; + listItem.addEventListener("click", async () => { + const success = await fetchPokemonDataBeforeRedirect(pokemon.id); + if (success) { + window.location.href = `./detail.html?id=${pokemon.id}`; + } else { + console.error(`Failed to fetch data for Pokémon ID: ${pokemon.id}`); + } + }); + listWrapper.appendChild(listItem); }); - if (pokemons.length === 0) { + lazyLoadImages(); + } + + function lazyLoadImages() { + console.log("Initializing lazy loading for images..."); + const images = document.querySelectorAll('.img-wrap img[data-src]'); + const config = { + root: null, + rootMargin: '0px', + threshold: 0.1 + }; + + let observer = new IntersectionObserver((entries, self) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + preloadLowResImage(entry.target); + self.unobserve(entry.target); + } + }); + }, config); + + images.forEach(image => { + observer.observe(image); + }); + } + + function preloadLowResImage(img) { + const srcLow = img.getAttribute('data-src-low'); + if (!srcLow) { + return; + } + console.log("Preloading low-resolution image:", srcLow); + img.src = srcLow; + preloadHighResImage(img); + } + + function preloadHighResImage(img) { + const src = img.getAttribute('data-src'); + if (!src) { + return; + } + const highResImg = new Image(); + highResImg.src = src; + highResImg.onload = () => { + console.log("Preloading high-resolution image:", src); + setTimeout(() => { + img.src = src; + }, 2000); // Wait for 2 seconds before switching to high-resolution image + }; + } + + searchInput.addEventListener("keyup", handleSearch); + numberAscFilter.addEventListener("change", handleSort); + numberDescFilter.addEventListener("change", handleSort); + nameAscFilter.addEventListener("change", handleSort); + nameDescFilter.addEventListener("change", handleSort); + + function handleSearch() { + const searchTerm = searchInput.value.toLowerCase(); + console.log("Handling search with term:", searchTerm); + + filteredPokemons = allPokemons.filter((pokemon) => { + const pokemonID = pokemon.id.toString(); + const pokemonName = pokemon.name.toLowerCase(); + return (pokemonID.startsWith(searchTerm) || pokemonName.startsWith(searchTerm)) && !pokemon.deleted; + }); + + displayPokemons(filteredPokemons); + + if (filteredPokemons.length === 0) { notFoundMessage.style.display = "block"; } else { notFoundMessage.style.display = "none"; } } - function setupSorting() { - const sortOptions = document.querySelectorAll(".filter-wrap input[name='filters']"); - sortOptions.forEach((option) => { - option.addEventListener("change", handleSortChange); - }); - } - - function handleSortChange(event) { - const sortValue = event.target.value; - - switch (sortValue) { - case "number-asc": - filteredPokemons.sort((a, b) => a.id - b.id); - break; - case "number-desc": - filteredPokemons.sort((a, b) => b.id - a.id); - break; - case "name-asc": - filteredPokemons.sort((a, b) => a.name.localeCompare(b.name)); - break; - case "name-desc": - filteredPokemons.sort((a, b) => b.name.localeCompare(a.name)); - break; - default: - console.warn("Unknown sort option:", sortValue); + function handleSort() { + if (numberAscFilter.checked) { + filteredPokemons.sort((a, b) => a.id - b.id); + } else if (numberDescFilter.checked) { + filteredPokemons.sort((a, b) => b.id - a.id); + } else if (nameAscFilter.checked) { + filteredPokemons.sort((a, b) => a.name.localeCompare(b.name)); + } else if (nameDescFilter.checked) { + filteredPokemons.sort((a, b) => b.name.localeCompare(a.name)); } displayPokemons(filteredPokemons); } -})(); + + const closeButton = document.querySelector(".search-close-icon"); + closeButton.addEventListener("click", clearSearch); + + function clearSearch() { + console.log("Clearing search input and displaying all Pokémon..."); + searchInput.value = ""; + filteredPokemons = allPokemons.filter(pokemon => !pokemon.deleted); + displayPokemons(filteredPokemons); + notFoundMessage.style.display = "none"; + } + + function fetchCompetitors() { + console.log("Fetching competitors data from server..."); + fetch(`./get-competitors.php`) + .then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.json(); + }) + .then((data) => { + if (data.error) { + console.error("Error from server:", data.error); + displayCompetitorsError(data.error); + } else { + displayCompetitors(data); + } + }) + .catch((error) => { + console.error("Error fetching competitors data:", error); + displayCompetitorsError("Failed to load competitors data. Please try again later."); + }); + } + + function displayCompetitorsError(message) { + const competitorsWrapper = document.querySelector("#competitors-wrapper"); + competitorsWrapper.innerHTML = `

${message}

`; + } + + function displayCompetitors(competitors) { + competitorsWrapper.innerHTML = ""; + + competitors.forEach((competitor) => { + const listItem = document.createElement("div"); + listItem.className = "list-item"; + listItem.innerHTML = ` +
+

User ID: ${competitor.user_id}

+
+
+ ${competitor.name} +
+
+

${competitor.name}

+
+
+

Pokémon Count: ${competitor.pokemon_count}

+
+ `; + + competitorsWrapper.appendChild(listItem); + }); + } +})(); \ No newline at end of file