mirror of
https://github.com/Alvin-Zilverstand/pokedex.git
synced 2026-03-06 13:25:11 +01:00
Enhance Pokémon data retrieval by optimizing SQL query, adding caching for images, and improving error handling in the frontend
This commit is contained in:
@@ -10,13 +10,26 @@ if ($conn->connect_error) {
|
|||||||
die("Connection failed: " . $conn->connect_error);
|
die("Connection failed: " . $conn->connect_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header("Cache-Control: max-age=3600"); // Cache for 1 hour
|
||||||
|
|
||||||
if (isset($_GET['id'])) {
|
if (isset($_GET['id'])) {
|
||||||
$id = intval($_GET['id']);
|
$id = intval($_GET['id']);
|
||||||
$sql = "SELECT * FROM pokemon WHERE id = $id";
|
$sql = "SELECT p.*, s.flavor_text, GROUP_CONCAT(t.name) AS types, GROUP_CONCAT(a.name) AS abilities, st.hp, st.attack, st.defense, st.sp_attack, st.sp_defense, st.speed
|
||||||
|
FROM pokemon p
|
||||||
|
LEFT JOIN species s ON p.id = s.pokemon_id
|
||||||
|
LEFT JOIN pokemon_types pt ON p.id = pt.pokemon_id
|
||||||
|
LEFT JOIN types t ON pt.type_id = t.id
|
||||||
|
LEFT JOIN pokemon_abilities pa ON p.id = pa.pokemon_id
|
||||||
|
LEFT JOIN abilities a ON pa.ability_id = a.id
|
||||||
|
LEFT JOIN stats st ON p.id = st.pokemon_id
|
||||||
|
WHERE p.id = $id
|
||||||
|
GROUP BY p.id";
|
||||||
$result = $conn->query($sql);
|
$result = $conn->query($sql);
|
||||||
|
|
||||||
if ($result->num_rows > 0) {
|
if ($result->num_rows > 0) {
|
||||||
$pokemon = $result->fetch_assoc();
|
$pokemon = $result->fetch_assoc();
|
||||||
|
$pokemon['types'] = explode(',', $pokemon['types']);
|
||||||
|
$pokemon['abilities'] = explode(',', $pokemon['abilities']);
|
||||||
echo json_encode($pokemon);
|
echo json_encode($pokemon);
|
||||||
} else {
|
} else {
|
||||||
echo json_encode(["error" => "No Pokémon found"]);
|
echo json_encode(["error" => "No Pokémon found"]);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ async function loadPokemon(id) {
|
|||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("An error occurred while fetching Pokémon data:", error);
|
console.error("An error occurred while fetching Pokémon data:", error);
|
||||||
return false;
|
return (window.location.href = "./index.html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ function rgbaFromHex(hexColor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setTypeBackgroundColor(pokemon) {
|
function setTypeBackgroundColor(pokemon) {
|
||||||
const mainType = pokemon.types[0].type.name;
|
const mainType = pokemon.types[0];
|
||||||
const color = typeColors[mainType];
|
const color = typeColors[mainType];
|
||||||
|
|
||||||
if (!color) {
|
if (!color) {
|
||||||
@@ -158,7 +158,7 @@ function createAndAppendElement(parent, tag, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function displayPokemonDetails(pokemon) {
|
function displayPokemonDetails(pokemon) {
|
||||||
const { name, id, types, weight, height, abilities, stats } = pokemon;
|
const { name, id, types, weight, height, abilities, hp, attack, defense, sp_attack, sp_defense, speed } = pokemon;
|
||||||
const capitalizePokemonName = capitalizeFirstLetter(name);
|
const capitalizePokemonName = capitalizeFirstLetter(name);
|
||||||
|
|
||||||
document.querySelector("title").textContent = capitalizePokemonName;
|
document.querySelector("title").textContent = capitalizePokemonName;
|
||||||
@@ -174,15 +174,15 @@ function displayPokemonDetails(pokemon) {
|
|||||||
).textContent = `#${String(id).padStart(3, "0")}`;
|
).textContent = `#${String(id).padStart(3, "0")}`;
|
||||||
|
|
||||||
const imageElement = document.querySelector(".detail-img-wrapper img");
|
const imageElement = document.querySelector(".detail-img-wrapper img");
|
||||||
imageElement.src = `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/dream-world/${id}.svg`;
|
imageElement.src = pokemon.image_url;
|
||||||
imageElement.alt = name;
|
imageElement.alt = name;
|
||||||
|
|
||||||
const typeWrapper = document.querySelector(".power-wrapper");
|
const typeWrapper = document.querySelector(".power-wrapper");
|
||||||
typeWrapper.innerHTML = "";
|
typeWrapper.innerHTML = "";
|
||||||
types.forEach(({ type }) => {
|
types.forEach((type) => {
|
||||||
createAndAppendElement(typeWrapper, "p", {
|
createAndAppendElement(typeWrapper, "p", {
|
||||||
className: `body3-fonts type ${type.name}`,
|
className: `body3-fonts type ${type}`,
|
||||||
textContent: type.name,
|
textContent: type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -196,10 +196,10 @@ function displayPokemonDetails(pokemon) {
|
|||||||
const abilitiesWrapper = document.querySelector(
|
const abilitiesWrapper = document.querySelector(
|
||||||
".pokemon-detail-wrap .pokemon-detail.move"
|
".pokemon-detail-wrap .pokemon-detail.move"
|
||||||
);
|
);
|
||||||
abilities.forEach(({ ability }) => {
|
abilities.forEach((ability) => {
|
||||||
createAndAppendElement(abilitiesWrapper, "p", {
|
createAndAppendElement(abilitiesWrapper, "p", {
|
||||||
className: "body3-fonts",
|
className: "body3-fonts",
|
||||||
textContent: ability.name,
|
textContent: ability,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,29 +210,31 @@ function displayPokemonDetails(pokemon) {
|
|||||||
hp: "HP",
|
hp: "HP",
|
||||||
attack: "ATK",
|
attack: "ATK",
|
||||||
defense: "DEF",
|
defense: "DEF",
|
||||||
"special-attack": "SATK",
|
sp_attack: "SATK",
|
||||||
"special-defense": "SDEF",
|
sp_defense: "SDEF",
|
||||||
speed: "SPD",
|
speed: "SPD",
|
||||||
};
|
};
|
||||||
|
|
||||||
stats.forEach(({ stat, base_stat }) => {
|
const stats = { hp, attack, defense, sp_attack, sp_defense, speed };
|
||||||
|
|
||||||
|
Object.keys(stats).forEach((stat) => {
|
||||||
const statDiv = document.createElement("div");
|
const statDiv = document.createElement("div");
|
||||||
statDiv.className = "stats-wrap";
|
statDiv.className = "stats-wrap";
|
||||||
statsWrapper.appendChild(statDiv);
|
statsWrapper.appendChild(statDiv);
|
||||||
|
|
||||||
createAndAppendElement(statDiv, "p", {
|
createAndAppendElement(statDiv, "p", {
|
||||||
className: "body3-fonts stats",
|
className: "body3-fonts stats",
|
||||||
textContent: statNameMapping[stat.name],
|
textContent: statNameMapping[stat],
|
||||||
});
|
});
|
||||||
|
|
||||||
createAndAppendElement(statDiv, "p", {
|
createAndAppendElement(statDiv, "p", {
|
||||||
className: "body3-fonts",
|
className: "body3-fonts",
|
||||||
textContent: String(base_stat).padStart(3, "0"),
|
textContent: String(stats[stat]).padStart(3, "0"),
|
||||||
});
|
});
|
||||||
|
|
||||||
createAndAppendElement(statDiv, "progress", {
|
createAndAppendElement(statDiv, "progress", {
|
||||||
className: "progress-bar",
|
className: "progress-bar",
|
||||||
value: base_stat,
|
value: stats[stat],
|
||||||
max: 100,
|
max: 100,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ fetch(`./get-pokemon.php`)
|
|||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
allPokemons = data;
|
allPokemons = data;
|
||||||
|
cacheImages(allPokemons);
|
||||||
displayPokemons(allPokemons);
|
displayPokemons(allPokemons);
|
||||||
} else {
|
} else {
|
||||||
console.error("Unexpected response format:", data);
|
console.error("Unexpected response format:", data);
|
||||||
@@ -30,14 +31,32 @@ async function fetchPokemonDataBeforeRedirect(id) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch Pokémon data before redirect");
|
console.error("Failed to fetch Pokémon data before redirect:", error);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cacheImages(pokemons) {
|
||||||
|
pokemons.forEach((pokemon) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = pokemon.image_url;
|
||||||
|
img.onload = () => {
|
||||||
|
localStorage.setItem(`pokemon_image_${pokemon.id}`, pokemon.image_url);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCachedImageUrl(pokemonId) {
|
||||||
|
return localStorage.getItem(`pokemon_image_${pokemonId}`);
|
||||||
|
}
|
||||||
|
|
||||||
function displayPokemons(pokemons) {
|
function displayPokemons(pokemons) {
|
||||||
listWrapper.innerHTML = "";
|
listWrapper.innerHTML = "";
|
||||||
|
|
||||||
pokemons.forEach((pokemon) => {
|
pokemons.forEach((pokemon) => {
|
||||||
|
const cachedImageUrl = getCachedImageUrl(pokemon.id);
|
||||||
|
const imageUrl = cachedImageUrl || pokemon.image_url;
|
||||||
|
|
||||||
const listItem = document.createElement("div");
|
const listItem = document.createElement("div");
|
||||||
listItem.className = "list-item";
|
listItem.className = "list-item";
|
||||||
listItem.innerHTML = `
|
listItem.innerHTML = `
|
||||||
@@ -45,7 +64,7 @@ function displayPokemons(pokemons) {
|
|||||||
<p class="caption-fonts">#${pokemon.id}</p>
|
<p class="caption-fonts">#${pokemon.id}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="img-wrap">
|
<div class="img-wrap">
|
||||||
<img src="${pokemon.image_url}" alt="${pokemon.name}" />
|
<img src="${imageUrl}" alt="${pokemon.name}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="name-wrap">
|
<div class="name-wrap">
|
||||||
<p class="body3-fonts">#${pokemon.name}</p>
|
<p class="body3-fonts">#${pokemon.name}</p>
|
||||||
@@ -56,6 +75,8 @@ function displayPokemons(pokemons) {
|
|||||||
const success = await fetchPokemonDataBeforeRedirect(pokemon.id);
|
const success = await fetchPokemonDataBeforeRedirect(pokemon.id);
|
||||||
if (success) {
|
if (success) {
|
||||||
window.location.href = `./detail.html?id=${pokemon.id}`;
|
window.location.href = `./detail.html?id=${pokemon.id}`;
|
||||||
|
} else {
|
||||||
|
console.error(`Failed to fetch data for Pokémon ID: ${pokemon.id}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user