Build a Pokémon Search App Project - Build a Pokémon Search App

Tell us what’s happening:

I am passing all the tests except for the “Red” one. If I type the word in the input field it correctly displays the alert is is supposed to. But the test just doesn’t pass. Any help would be much appreciated!

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>Pokémon Search App Demo Project</title>
      <link href="styles.css" rel="stylesheet"/> 
    </head>
    <body>
      <header>
        <h1 id="page-title">Pokémon Search App</h1>
        <p id="page-subtitle">Demo Project</p>
      </header>

      <main>
          <div id="main-container">
            <label id="search-input-label" for="search-input">Search for a Pokémon by Name or ID</label>
            <div id="input-container">
              <input id="search-input" type="text" required/>
              <button id="search-button" type="submit">Search</button>
            </div>
            <div id="pokémon-container">
              <div id="name-and-id">
                <p id="pokemon-name"></p>
                <p id="pokemon-id"></p>              
              </div>
              <div id="types-container"></div>
              <div id="sprite-image-container"></div>
              <div id="weight-and-height">
                <p id="weight">Weight: <span id="pokemon-weight-value"></span></p>
                <p id="height">Height: <span id="pokemon-height-value"></span></p>
              </div>      
            </div>
                    
            <table id="table-with-stats">
                <thead>
                  <tr id="table-header-row">
                    <th id="table-stat">Stat</th>
                    <th id="table-value">Value</th>
                  </tr>
                </thead>

                <tbody id="table-body">
                  <tr>
                    <td class="stat-name">HP</td>
                    <td class="stat-value" id="hp"></td>  
                  </tr>
                  <tr>
                    <td class="stat-name">ATTACK</td>
                    <td class="stat-value" id="attack"></td>    
                  </tr>
                  <tr>
                    <td class="stat-name">DEFENSE</td>
                    <td class="stat-value" id="defense"></td>    
                  </tr>
                  <tr>  
                    <td class="stat-name">SPECIAL ATTACK</td>
                    <td class="stat-value" id="special-attack"></td>    
                  </tr>
                  <tr>
                    <td class="stat-name">SPECIAL DEFENSE</td>
                    <td class="stat-value" id="special-defense"></td>    
                  </tr>
                  <tr>
                    <td class="stat-name">SPEED</td>
                    <td class="stat-value" id="speed"></td>    
                  </tr>  
                </tbody>
              </table>
          </div>
      </main>
      <script src="script.js"></script>
    </body>
  </html>
/* file: script.js */
// DECLARE VARIABLES
const pokemonAPI = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon"

const userInput = document.getElementById("search-input");
const searchBtn = document.getElementById("search-button");
// const pokemonContainer = document.getElementById("pokémon-container");
const pokemonName = document.getElementById("pokemon-name");
const pokemonId = document.getElementById("pokemon-id");
const typesContainer = document.getElementById("types-container");
const tableStats = document.getElementById("table-body");
const spriteImageContainer = document.getElementById("sprite-image-container");
const pokemonWeightValue = document.getElementById("pokemon-weight-value");
const pokemonHeightValue = document.getElementById("pokemon-height-value");

// STATS
const statsObject = {
  "hp": document.getElementById("hp"),
  "attack": document.getElementById("attack"),
  "defense": document.getElementById("defense"),
  "special-attack": document.getElementById("special-attack"),
  "special-defense": document.getElementById("special-defense"),
  "speed": document.getElementById("speed")
};

// DECLARING FUNCTIONS


// FETCHING API
const getData = async () => {
  try {
    const response = await fetch(pokemonAPI);
    const data = await response.json();

    // EVENT LISTENERS
    searchBtn.addEventListener("click", () => eventListenersFunction(data, userInput.value));

    window.addEventListener("keydown", (event) => {
      if (event.key === "Enter") {
        eventListenersFunction(data, userInput.value);
      }
    });
  } catch (err) {
    console.log(err);
  }
}

// CLEAR FUNC
const clear = () => {
  pokemonName.textContent = "";
  pokemonId.textContent = "";
  typesContainer.textContent = "";
  spriteImageContainer.textContent = "";
  pokemonWeightValue.textContent = "";
  pokemonHeightValue.textContent = "";
  
  // CLEARING TABLE STATS 
  for (let value in statsObject) {
    if (statsObject.hasOwnProperty(value)) {
      statsObject[value].textContent = "";
    }
  }
}

// EVENT LISTENERS FUNC
const eventListenersFunction = (pData, pInput) => {
  const parsedInput = pInput
  .replace(/♀/, " f")
  .replace(/♂/, " m")
  .replace(/[^a-zA-Z0-9\s]/g, "")
  .split(" ")
  .join("-")
  .toLowerCase();
  
  if (parsedInput === "") {
    clear();
    alert("Please enter a name or an id");
  }

  if (isAValidPokemon(pData, parsedInput)) {
    return getPokemon(parsedInput);
  } else {
    clear();
    return alert("Pokémon not found");
  }
};

// POKEMON VALIDITY FUNC 
const isAValidPokemon = (pData, pParsedInput) => {
  const pokemons = pData.results;
  return pokemons.some(pokemon => {
   return pParsedInput === pokemon.name || pParsedInput === pokemon.id.toString();
  })
}

// GET POKEMON DATA FUNCTIONS

const getPokemon = async (pParsedInput) => {
  const pokemon = pParsedInput;
  try {
      const response = await fetch(`${pokemonAPI}/${pokemon}`);
      const currentPokemon = await response.json();
      const { sprites, name, id, weight, height, types, stats } = currentPokemon;
      const frontImage = sprites["front_default"]; 
      const formattedName = name[0].toUpperCase() + name.slice(1).replace("-f", "♀").replace("-m", "♂");
//  RENDERING BASE POKEMON INFO
      pokemonName.textContent = formattedName;
      pokemonId.textContent = `#${id}`;

      formattedTypes(types);

      spriteImageContainer.innerHTML = `<img id="sprite" src="${frontImage}"/>`

      pokemonWeightValue.textContent = weight;
      pokemonHeightValue.textContent = height;
      
//  RENDERING POKEMON STATS INFO
      formattedStats(stats);

//  RENDERING BASE POKEMON INFO (Dynamically)
      // pokemonContainer.innerHTML = `
      //   <div id="name-and-id">
      //     <p id="pokemon-name">${formattedName}</p>
      //     <p id="pokemon-id">#${id}</p>        
      //   </div>

      //   <img id="sprite" src="${frontImage}"/>

      //   <div id="weight-and-height">
      //     <p id="weight">Weight: ${weight}</p>
      //     <p id="height">Height: ${height}</p>
      //   </div>
      //   `;
      
  } catch (err) {
    console.log(err);
  }
}

const formattedTypes = (pTypes) => {
  typesContainer.innerHTML = pTypes.map(el => {
  const typeName = el.type.name;
  const formattedTypeName = typeName[0].toUpperCase() + typeName.slice(1);
  return `
    <span class="type ${typeName}">${formattedTypeName}</span>
  `;
  }).join('');
}

const formattedStats = (pStats) => {
  pStats.forEach(stat => {
    let statValue = stat["base_stat"];
    let statName = stat.stat.name;
    if (statsObject.hasOwnProperty([statName])) {
      return statsObject[statName].textContent = statValue;
    }
  });          
}

// FUNCTION CALLS
getData();
/* file: styles.css */
:root {
  --red: #f00000;
  --dark-red: #a80000;
  --black: #222224;
  --gray: #f0f0f0; 
  --dark-gray: #a8a8a8;
}

/* DIFFERENT TYPES COLORS */
.normal {
  background-color: #b7b7aa;
}

.fire {
  background-color: #ff6f52;
}

.water {
  background-color: #42a1ff;
}

.electric {
  background-color: #fecc33;
}

.grass {
  background-color: #78cc55;
}

.ice {
  background-color: #66ccfe;
}

.fighting {
  background-color: #d3887e;
}

.poison {
  background-color: #c68bb7;
}

.ground {
  background-color: #dfba52;
}

.flying {
  background-color: #8899ff;
}

.psychic {
  background-color: #ff66a3;
}

.bug {
  background-color: #aabb23;
}

.rock {
  background-color: #baaa66;
}

.ghost {
  background-color: #9995d0;
}

.dragon {
  background-color: #9e93f1;
}

.dark {
  background-color: #b59682;
}

.steel {
  background-color: #abaabb;
}

.fairy {
  background-color: #ed99ed;
}

@font-face {
  font-family: pokemonFont;
  src: url(PokemonSolidNormal-xyWR.ttf);
}

*,
:before,
:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 10px;
}

body {
  background-color: var(--black);
  text-align: center;
  padding: 0 1rem;
}

header {
  margin-top: 2rem;
  color: var(--gray);
}

#page-title {
  font-size: 5rem;
}

#page-subtitle {
  font-size: 3rem;
  margin-top: 1rem;
  font-style: italic;
}

#main-container {
  width: 400px;
  height: auto;
  margin: 3rem auto 0;
  border: 3px solid var(--dark-gray);
  padding: 1.5rem;
  background-color: var(--gray);
  border-radius: 5px;
}

#search-input-label {
  display: block;
  font-size: 2rem;
}

#input-container {
  margin-top: 1rem;
  display: flex;
  justify-content: space-evenly;
}

#search-input {
  font-size: 2.5rem;
  width: 60%;
  border: 2px solid var(--black);
}

#search-button {
  font-size: 2.5rem;
  align-self: center;
  padding: 0.5rem;
  background-color: var(--red);
  color: var(--gray);
  border-radius: 5px;
  border: 2px solid var(--black);
  cursor: pointer;
}

/* POKEMON CONTAINER STYLING */
#name-and-id {
  margin-top: 1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: pokemonFont, sans-serif;
  height: 40px;
}

#pokemon-name, #pokemon-id {
  font-size: 2rem;
  height: 40px;
  display: flex;
  align-items: center;
}

#types-container {
  height: 40px;
  margin-top: 0.5rem;
  display: flex;
  justify-content: flex-start;
  align-items: center;
}

.type {
  border: 1px solid black;
  color: black;
  padding: 0.5rem;
  font-size: 1.5rem;
  margin: 0 0.2rem;
}

#sprite-image-container {
  height: 250px;
}

#sprite {
  height: 100%;
  width: auto; 
}

#weight-and-height {
  font-size: 2rem;
  font-weight: bold;
  display: flex;
  justify-content: space-between;
  align-self: center;
}

/* TABLE (STATS) STYLING */
#table-with-stats {
  width: 100%;
  margin-top: 2rem;
  border-collapse: collapse;
}

td, th {
  border: 0px solid transparent;
  background-clip: padding-box;
}

tr > th + th {
  border-left-width: 10px;
}

tr > td + td {
  border-left-width: 10px;
}

th {
  border-bottom-width: 10px;
}

tr + tr > td {
  border-top-width: 10px;
}

td, th {
  padding: 0.5rem;
}

#table-stat {
  width: 70%;
}

#table-stat, #table-value {
  font-size: 2.5rem;
  background-color: var(--red);
  color: var(--gray);
  }

.stat-name, .stat-value {
  font-size: 1.4rem;
  background-color: var(--dark-gray);
}

.stat-name, .stat-value {
  font-weight: bold;
}

@media only screen and (max-width: 450px) {
  #page-title {
    font-size: 3.5rem;
  }
  
  #page-subtitle {
    font-size: 2rem;
  }
    
  #main-container {
    width: 320px;
  }

  #sprite-image-container {
    height: 200px;
  }
  

}

Your browser information:

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

Challenge Information:

Build a Pokémon Search App Project - Build a Pokémon Search App

Hello, you are missing parenthese on a callback at the bottom of your JS file, also you have duplicate values in the CSS. Good luck

Thanks for the answer but I can’t quite see where are the missing parentheses? Can you point to the exact function? And which values are duplicated in the CSS?

Ok so this came in as an error pStats.forEach(stat => and .stat-name, .stat-value { font-weight: bold; } the css might not make much of a difference though.