Build a Pokémon Search App

Tell us what’s happening:

I have tested my code over and over again, for some reason in the platform I get the error [failed to fetch] that may be happening. I even tried to see if it worked by taking to production, and it works in production from a server: https://experiences.guillermocopello.com /, I don’t understand what may be happening

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pokemon Search App</title>
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <main>
        <div class="app" id="app">
            <form action="" class="form">
                <label for="pokemon">Search for Pokémon Name or ID:
                    <input required type="text" id="search-input" name="pokemon" placeholder="Buscar Pokemon">
                </label>
                <button id="search-button">Search</button>
            </form>

            <div id="pokemon-info">
                <table>
                    <tr>
                        <td id="pokemon-name">Pokemon Name:</td>
                        <td><span id="pokemon-id"></span></td>
                    </tr>
                    <tr>
                        <td>Weight:</td>
                        <td><span id="weight"></span></td>
                    </tr>
                    <tr>
                        <td>Height:</td>
                        <td><span id="height"></span></td>
                    </tr>
                </table>
                <img src="" alt="pokemon-avatar">
                <p id="types"></p>

                <table>
                    <tr>
                        <td>HP:</td>
                        <td><span id="hp"></span></td>
                    </tr>
                    <tr>
                        <td>Attack:</td>
                        <td><span id="attack"></span></td>
                    </tr>
                    <tr>
                        <td>Defense:</td>
                        <td><span id="defense"></span></td>
                    </tr>
                    <tr>
                        <td>Special Attack:</td>
                        <td><span id="special-attack"></span></td>
                    </tr>
                    <tr>
                        <td>Special Defense:</td>
                        <td><span id="special-defense"></span></td>
                    </tr>
                    <tr>
                        <td>Speed:</td>
                        <td><span id="speed"></span></td>
                    </tr>
                </table>

            </div>
        </div>
        </div>
    </main>
    <script src="./script.js"></script>
</body>

</html>
/* file: styles.css */
@import url("https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=Merriweather:ital,wght@0,300;0,400;0,700;0,900;1,300;1,400;1,700;1,900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap");

:root {
  --bg-body: #3e5684;
  --light-box: #7bdeff;
  --dark-box: #4d4fa1;
  --buttons: #8d69db;
  /* text for bg light */
  --light-tx: #15242c;
  /* text for bg dark */
  --dark-tx: #69d7db;

  --box-radius: 12px;
}

html {
  box-sizing: border-box;
  font-size: 18px; 
  color: var(--light-tx);
}

body {
  margin: 0;
  padding: 20px;
  height: auto;
  background: var(--bg-body);
  font-family: "Ubuntu", sans-serif, serif;
  font-size: 1rem;
}

.app {
  display: flex;
  flex-direction: column;
  width: 50%;
  height: auto;
  padding-top: 14px;
  padding-bottom: 14px;
  margin: 0 auto;
  background-color: var(--light-box);
  border-radius: 18px;
  align-items: center;
}

#search-input {
  padding-left: 25px;
  padding-right: 25px;
  border-radius: var(--box-radius);
  border-width: 0;
  margin-left: 0;
  cursor: pointer;
  background-image/*color*/: url()
    /*, var(--buttons) */;
}

#search-button {
  background: var(--buttons);
  min-width: 1.2rem;
  padding: 8px;
}

/* Estilos para la información del Pokemon */
#pokemon-info {
    height: auto;
  margin: 20px 0;
}

.display-info {
    height: auto;
    /* visibility: hidden; */
}

.pokemon-atributes {
    display: grid;
    grid-template-columns: 3fr 1fr;

}


@media (max-width: 600px) {
  body {
    padding: 10px;
  }

  #search-input,
  #search-button {
    width: 100%;
  }
}


.label {
  background-color: lightgray;
  text-align: center;
  vertical-align: middle;
  line-height: 30px;
}
/* file: script.js */
const pokeAPI = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon";
const pokemonInfo = document.getElementById("pokemon-info");
const searchButton = document.getElementById("search-button");
const searchInput = document.getElementById("search-input");

const fetchFeatures = async (url) => {
  try {
    const response = await fetch(url);
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
  }
};

const validationInput = () => {
  let searchValue = searchInput.value.trim();
  const inputIdRegex = /^\d+$/;

  if (inputIdRegex.test(searchValue)) {
    return parseInt(searchValue);
  } else {
    return searchValue.toLowerCase();
  }
};

const findPokemon = (results, nameOrId) => {
  return results.find(item => item.name.toLowerCase() === nameOrId || parseInt(item.url.split('/').slice(-2)[0]) === nameOrId);
};

const searchByNameOrId = async () => {
  try {
    const response = await fetch(pokeAPI);
    const data = await response.json();
    const nameOrId = validationInput();
    const result = findPokemon(data.results, nameOrId);
    if (!result) {
      alert("Pokemon not Found");
      return;
    }
    const pokemonFeatures = await fetchFeatures(result.url);
    displayPokemonFeatures(pokemonFeatures);
  } catch (error) {
    console.error(error);
  }
};

const displayPokemonFeatures = (data) => {
  const { name, id, weight, height, sprites, stats, types } = data;
  const { front_default } = sprites;

  const kindPokemon = types.map((type) => {
    return `<span>${type.type.name}</span>`;
  }).join(' ');

  const statisticRows = stats.map((stat) => {
    return `<tr>
      <td>${stat.stat.name}:</td>
      <td><span class="base-stat">${stat.base_stat}</span></td>
      </tr>`;
  }).join('');

  pokemonInfo.innerHTML = `
    <div id="pokemon-info">
      <table>
          <tr>
              <td id="pokemon-name">Pokemon Name: ${name}</td>
              <td><span id="pokemon-id">#${id}</span></td>
          </tr>
          <tr>
              <td>Weight:</td>
              <td><span id="weight">${weight}</span></td>
          </tr>
          <tr>
              <td>Height:</td>
              <td><span id="height">${height}</span></td>
          </tr>
      </table>
      <img src="${front_default}" alt="pokemon-avatar">
      <p id="types">${kindPokemon}</p>

      <table>
          ${statisticRows}
      </table>
    </div>
  `;
};

searchButton.addEventListener("click", (event) => {
  event.preventDefault();
  searchByNameOrId();
});

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36

Challenge Information:

Build a Pokémon Search App

It is a CORS block. You are using the URL from the url property and they are http not https.

"url": "http://pokeapi-proxy.freecodecamp.rocks/api/pokemon/1/"

You can do a replace to add the “https” manually, but you do not need to use that URL. It is the same as the main API URL just with the name or id added to the path.

https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/nameOrId

It was reported on the forum, and it was suggested that they open an issue for it, but I don’t think they did.


You can’t have “Pokemon Name:” inside the element being checked for the name.

Your initial HTML has the correct id attributes, but your updated HTML after the fetch does not (i.e. the statisticRows).

1 Like

Thanks so much, i’ve fixed my errors and i was able to pass the exercise, i really appreciate it